Shader編程學習筆記(九)—— Cg語言入門1 - 輸入輸出和語義


Cg入門一:輸入輸出和語義

  本小節對Cg語言進行一個入門了解。

  在以前的課程中,我們了解了渲染管線、頂點和片段程序和顏色計算等,在本小結中來了解一個簡單的shader的頂點和片段程序的輸入輸出以及常用語義。

  編寫一個簡單的頂點和片段着色器,代碼如下:

Shader "Lesson/vertex&fragment"{
    SubShader{
        pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            void vert(in float2 objPos:POSITION, out float4 pos:POSITION){
                pos = float4(objPos,0,1);
            }

            void frag(out float4 col:COLOR){
                col = float4(1,0,0,1);
            }
            ENDCG
        }
    }
}
vertex&fragment

  Surface Shader沒有pass通道,Vertex & Frament Shader至少有一個pass通道。其中,Cg是一個鑲嵌的代碼段,在ShaderLab語法中需要使用關鍵詞“CGPROGRAM”和“ENDCG”將Cg代碼段包含起來才能編譯使用,需要注意的是這兩個關鍵詞都是大寫的。

  頂點程序會對頂點做一系列的處理,如幾何變換,在處理后把需要的數據傳遞給片段程序,片段程序拿到頂點程序當中處理后的數據繼續進行最終的計算。“void vert(in float2 objPos:POSITION, out float4 pos:POSITION)” 中有兩個參數,其中第一個參數中的“in”表示引擎提供的輸入,“float2”表示數據的類型為二階的向量,參數名“objPos”冒號后需要帶上語義,語義指的是頂點程序和片段程序能夠被識別的變量的實際意義,這里使用“POSITION”。第二個參數中“out”表示輸出,數據類型為“float4”,語義也是“POSITION”。如果頂點程序要輸出一個“POSITION”語義的變量,這個變量必須要以“float4”四階向量的形式。另外,在片段程序中需要有語義為“COLOR”的變量作為輸入,這里使用“out float4 col:COLOR”作為顏色變量的輸出,語義“COLOR”就是指“COLOR0”。

  接下來創建一個使用該shader的Material,並在場景創建一個Cube使用該Material。效果如下:

  拖動場景窗口,可以發現物體的大小隨着窗口的變化而變化。目前需要了解的就是傳遞給頂點程序的就是模型的頂點數據,由模型的(x,y)湊成一個四階向量,“POSITION”語義變量並沒有在片段程序中輸出,但是物體確實有大小上的變化,實際上“POSITION”語義是比較特殊的,可以不用在片段程序中直接使用“POSITION”輸出,它被圖形硬件直接做最后的處理和顯示。在這里目前需要關心的是顏色的顯示,我們可以在頂點程序中為顏色計算做一個輸出,代碼和效果如下:

Shader "Lesson/vertex&fragment"{
    SubShader{
        pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            void vert(in float2 objPos:POSITION, out float4 col:COLOR, out float4 pos:POSITION){
                pos = float4(objPos,0,1);
                col = float4(0,0,1,1);
            }

            void frag(inout float4 col:COLOR){
                // col = float4(0,1,0,1);
            }
            ENDCG
        }
    }
}
vertex&fragment

 

  片段程序的顏色設置已經注釋掉了,否則會覆蓋頂點程序的顏色值。需要注意的是作為輸出的“COLOR”變量要放在作為輸出的“POSITION”語義之前,如“vert(in float2 objPos:POSITION, out float4 col:COLOR, out float4 pos:POSITION)”,否則顏色輸出始終是無法改變的。

  計算機圖形硬件想要對3D場景中的物體做一個正確的顯示時,它需要經過一系列的坐標系變換,如果輸入一個物體的坐標系,這個物體的坐標系是沒有參考價值的,它只存在物體自身的空間當中,物體在世界坐標中,與其他物體之間有一個相對位置,被攝像機照射時,物體在不同的位置,攝像機最終獲取的結果是不一樣的。通過這一些列的變換,會得到一個稱為“CVV(Canonical View Volume)”的裁剪立方體,“CVV”實際上就是在進行攝像機透視投影在齊次空間當中的一個裁剪立方體,稱為“正規化可視空間”,它的x值和y值總是在-1到1之間。

  對於Unity中默認創建的一個Cube,它的網格數據的頂點信息中存儲的x值和y值最大為0.5,最小為-0.5,模型的坐標中心為正中間(0,0)。當模型空間當中的x和y作為一個“POSITION”語義的輸入時,可以知道它最大值為(0.5,0.5,0,1),最小為(-0.5,-0.5,0,1),在“CVV”的裁剪立方體當中x值和y值始終是-0.5到0.5,場景窗口最左邊位置x為-1,正中間x為0,最右邊位置x為1,y值同理。因此拖動窗口時,物體總是會隨着窗口的變化而變化。

  注釋掉片段程序中的顏色輸出,在頂點程序中將位置信息“pos”作為顏色信息,在Cg當中只要數據類型相同,兩者之間是可以互相賦值的,盡管語義不同,語義只是在頂點和片段程序中輸入輸出的一個規范。代碼和效果如下:

Shader "Lesson/vertex&fragment"{
    SubShader{
        pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            void vert(in float2 objPos:POSITION, out float4 col:COLOR, out float4 pos:POSITION){
                pos = float4(objPos,0,1);
                col = pos;
            }

            void frag(inout float4 col:COLOR){
                // col = float4(0,1,0,1);
            }
            ENDCG
        }
    }
}
vertex&fragment

  物體的顏色會隨着位置的變化而變化,顏色值的范圍是(-0.5,-0.5,0,1)到(0.5,0.5,0,1)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM