Unity Batch 对 Vertex Shader 产生影响

今天用Vertex Shader来实现旗帜飘动,本来设想旗帜是在旗面的法线方向上下飘动的,所以在模型坐标系下给vertex.z加上一个随时间变化的sine波。简化如下:

v2f vert (appdata_base v)
{   
    v2f o;
    float angle = _Time * 50;
    float waveA = sin(v.vertex.x + angle);
    v.vertex.z += waveA;
    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
    return o; 
}

开始是正确的,但是当我将旗帜旋转90度后就发现飘动方向不再是旗面法线方向了,而变成切线方向了。
做了很多尝试,百思不得其解。Vertex Shader传入的顶点坐标是在模型坐标系下的,所以应该和GameObject的旋转是无关的,为什么加到模型坐标系下z方向的值最终会变成加在了世界坐标系z方向上呢?
后来发现这是由于Unity的Batch引起的。如果在场景中只有一面旗帜,那么不论怎么旋转,飘动方向都是对的。但当场景中放了两名旗帜后就有问题了。网上看到有人解释说Batch会改变UNITY_MATRIX_MVP。

解决方法倒是很容易,只要写Shader的时候不基于模型坐标系的方向而用法向量就行了。

v2f vert (appdata_base v)
{   
    v2f o;
    float angle = _Time * 50;
    float waveA = sin(v.vertex.x + angle);
    v.vertex.xyz += v.normal * waveA;
    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
    o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
    return o; 
}

你可能感兴趣的:(Unity)