Unity Shader中頂點座標的大小似乎會受到Draw Call合批的影響

最近美術同事希望我能幫忙做一個由內而外流光的shader,效果類似下圖:




我最初的思路是利用模型的頂點座標:美術製作模型的時候就將模型的原點設在中心。這樣我在vertex shader中用length(i.vertex)求出每個頂點到中心的距離,進而在fragment shader中求出每個像素是否該顯示流光。


於是就想做個實驗,看看Unity中的模型頂點的分佈規律。我寫了一個shader,讓離原點越近的頂點顏色越偏黑,離原點越遠的頂點越偏紅。


Shader "Custom/VisualizeVertexPos" {
    SubShader {
        Pass {
            Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off
            Lighting Off
            Fog { Color (0,0,0,0) }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma only_renderers gles d3d9 gles3 metal

            struct vertexInput {
                float4 vertex : POSITION;
            };

            struct vertexOutput {
                float4 pos : POSITION;
                fixed4 col : COLOR;
            };

            vertexOutput vert(vertexInput i)
            {
                vertexOutput o;
                o.pos = mul(UNITY_MATRIX_MVP, i.vertex);
                o.col = fixed4(length(i.vertex / 10), 0, 0, 1);
                return o;
            }

            float4 frag(vertexOutput i) : COLOR
            {
                return i.col;
            }

            ENDCG
        }
    } 
    //調試過程中註釋掉Fallback以便發現錯誤
    //FallBack "Diffuse"
}

在Unity中創建一個Unity自帶的Plane,應用這個shader,效果如下:




看來Unity自帶Plane的座標原點正好是在Plane的中心。

不過接下來問題來了。當我將Plane複製一個之後,屏幕中的兩個Plane就都變成了純紅色。




但是如果將其中一個Plane換個Shader,比如換成Diffuse,另外一個Plane就又恢復成之前中間黑色的樣子了。




兩個Plane使用同一個材質同一個Shader時,它們倆的Draw Call會合批。因此可以推測Draw Call的合批會對頂點座標的大小產生影響。

還可以進一步印證這個推測。把其中一個Plane換成Cylinder,用同一個Shader,也是兩個模型都變成了純紅色。Stats顯示Draw Calls爲1,有1個Draw Call被合批。




轉動攝像機,讓Plane或Cylinder移出攝像機視椎體外,留在視椎體內的模型的顏色就會發生變化。當只有Cylinder留在視椎體內時,Cylinder的顏色就變成了更接近黑色的暗紅。




不過值得一提的是,並不是說兩個模型使用同一個材質同一個Shader時,它們倆的Draw Call會合批。

比如,添加一個Sphere並不會對已有的模型顏色產生影響。




就此請教了另一位同事,看來是因爲Sphere頂點數太多,無法與Plane的Draw Call合批。從Stats看也的確如此,Draw Calls是2,沒有合批:




另外,如果兩個模型的縮放(Scale)不相等,這兩個模型的Draw Call也無法合批。在上面兩個Plane使用相同材質相同shader的情況中,如果把其中一個Plane的Scale改成(0.5, 0.5, 0.5),那麼Draw Calls也是2,它們又會恢復成中心是黑色的樣子。




看來還不能基於頂點座標來做這個需求,只好採用紋理座標(TEXCOORD0)了。後來的實驗表明,紋理座標的大小是不會受Draw Call合批影響的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章