頂點/片元 shader 總結

Cg頂點程序必須在結構中傳遞頂點數據。幾種經常使用的頂點結構定義在文件UnityCG.cginc中,有以下三種結構體:android

一、appdata_base: 包含頂點位置,法線和一個紋理座標。
二、appdata_tan:包含頂點位置,切線,法線和一個紋理座標。
三、appdata_full:包含位置、法線、切線、頂點色和兩個紋理座標。ios

struct appdata_base {
    float4 vertex : POSITION; //頂點座標
    float3 normal : NORMAL;//法線
    float4 texcoord : TEXCOORD0;//UV
};
struct appdata_tan {

    float4 vertex : POSITION;
    float4 tangent : TANGENT;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
};
struct appdata_full {
    float4 vertex : POSITION;//頂點座標
    float4 tangent : TANGENT;//正切
    float3 normal : NORMAL;//法線
    float4 texcoord : TEXCOORD0;//第一層UV
    float4 texcoord1 : TEXCOORD1; //第二層UV
    fixed4 color : COLOR; //顏色
};

注:頂點座標和正切線爲何是float4,這有點意思,由於這裏它表示是齊次座標,好比咱們這樣表示一個float4(x,y,z,w),當w = 1的時候它表示點(x,y,z),當w= 0的時候它表示一個向量(x,y,z)。區別就在這裏,當W爲1時表示點,當W爲0時表示向量。app

  texcoord0和texcoord1分別表示兩層UV,有時候咱們模型上的貼圖須要多個圖片一塊兒貼在一處,那麼貼兩層就會有兩層UV。函數

  以上三種類型爲Unity內置的頂點Shader傳入結構體,若是想自定義也是能夠的,可是自定義結構體裏面的屬性,必須是基於appdata_full的,這樣才能識別出來,也就是自定義的結構裏的屬性必須到appdata_full裏的屬性裏去選。性能

下面給一個簡單的頂點/片元 shader 事例:優化

Shader "Custom/Example" {
    Properties {
    _MainTex ("Texture", 2D) = "white" { }   //引號裏面的"Texture"則是Unity檢視面板中對應顯示的屬性名稱
    }
    SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            //_MainTex_ST的ST應該是SamplerTexture的意思 ,就是聲明_MainTex是一張採樣圖,也就是會進行UV運算。  
            //若是沒有這句話,是不能進行TRANSFORM_TEX的運算的。_MainTex_ST.xy爲 圖中的Tiling,zw爲圖中的offset.
            float4 _MainTex_ST;

            struct v2f {
                float4  pos : SV_POSITION;
                float2  uv : TEXCOORD0;
            } ;

            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP,v.vertex); //MVP矩陣變換,將裁剪空間座標轉換爲相對屏幕位置的UV座標
                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex); //TRANSFORM_TEX的做用是用頂點的UV v.texcoord和材質球的採樣圖片_MainTex作運算,確保頂點材質球裏的縮放和偏移是正確的。等價於o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                return o;
            }

            float4 frag (v2f i) : COLOR
            {
                float4 texCol = tex2D(_MainTex,i.uv);
                float4 outp = texCol;
                return outp;
            }
            ENDCG
        }
    }
}

其中SV_POSITION,SV_前綴的變量表明system value,在DX10之後的語義綁定中被使用表明特殊的意義,和POSITION用法並沒有不一樣。惟一區別是 SV_POSTION一旦被做爲vertex shader的輸出語義,那麼這個最終的頂點位置就被固定了(不能tensellate,不能再被後續改變它的空間位置?),直接進入光柵化處理,若是做爲fragment shader的輸入語義那麼和POSITION是同樣的,表明着每一個像素點在屏幕上的位置(這個說法其實並不許確,事實是fragment 在 view space空間中的位置,但直觀的感覺是如括號以前所述通常) 
最後這個回答者說了,在DX10版本以前沒有引入SV_的預約義語義,POSITION被用做vertex shader的輸入,輸出,fragment shader的輸入參數。但DX10以後就推薦使用SV_POSITION做爲vertex shader的輸出和fragment shader的輸入了,注意vertex shader的輸入仍是使用POSITION!切記。可是DX10之後的代碼依舊兼容POSITION做爲全程表達,估計編譯器會自動判斷並替換的吧。spa

 

另外,給一點編寫shader的建議:.net

一、只計算須要計算的東西;
二、一般,須要渲染的像素比頂點數多,而頂點數又比物體數多不少。因此若是能夠,儘可能將運算從PS移到VS,或直接經過script來設置某些固定值;
三、在使用Surface Shader時,能夠經過一些指令讓shader優化不少。
  一般狀況下,Surface shader的不少默認選項都是開啓的,以適應大多數狀況,可是不少時候,你能夠關閉其中的一些選項,從而讓你的shader運行的更快:
  (1) approxview 對於使用了view direction的shader,該選項會讓view dir的normalize操做per-vertex進行,而不是per-pixel。這個優化一般效果明顯。
  (2) halfasview 可讓Specular shader變得快一些,使用一個介於光照方向和觀察方向之間的half vector來代替真正的觀察方向viewDir來計算光照函數。
  (3) noforwardadd Forward Render時,徹底只支持一盞方向光的per-pixel渲染,其他的光照所有按照per-vertex或SH渲染。這樣能夠確保shader在一個pass裏渲染完成。
  (4) noambient 禁掉ambient lighting和SH lighting,可讓shader快一點兒。
四、浮點數精度相關:
  float:最高精度,一般32位
  half:中等精度,一般16位,-60000到60000,
  fixed:最低精度,一般11位,-2.0到2.0,1/256的精度。
  儘可能使用低精度。對於color和unit length vectors,使用fixed,其餘狀況,根據取值範圍儘可能使用half,實在不夠則使用float。
  在移動平臺,關鍵是在fragment shader中儘量多的使用低精度數據。另外,對於多數移動GPU,在低精度和高精度之間轉換是很是耗的,在fixed上作swizzle操做也是很費事的。
五、Alpha Test
  Alpha test和clip()函數,在不一樣平臺有不一樣的性能開銷。
  一般使用它來cull那些徹底透明的像素。
  可是,在ios和一些android上使用的PowerVR GPUs上面,alpha test很是的昂貴。
 六、Color Mask
  在移動設備上,Color Mask也是很是昂貴的,因此儘可能別使用它,除非真的是須要。code

 

最後推薦兩篇不錯的博客,orm

https://onevcat.com/2013/07/shader-tutorial-1/

http://blog.csdn.net/ring0hx/article/details/46440037

相關文章
相關標籤/搜索