天天看點

Shader預處理宏、内置狀态變量、多版本編譯等

預定義shader預處理宏:

  Target platform:

  Surface shader pass indicators:

内置全局狀态變量:

  内置的矩陣:

  内置的向量:

  光照相關的:

  變量:

  内置光照參數:

  對于不同的Rendering Path和Pass Tag,可以使用的光照參數是不一樣的。(當然所有參數你都可以在shader中使用,但并不能保證其一定會存儲有效的值)。

  Forward rendering(ForwardBase和PorwardAdd标記的pass)支援的變量:

  說明:

  (1)_LightColor0在ForwardBass裡面表示:主光,一定是Pixel(Important)、Directional光源,沒有的話則改值不可用;

  (2)_LightColor0在ForwardAdd裡面表示:目前執行的ForwardAdd的pixel光;

  _WorldSpaceLightPos0的意義和_LightColor類似,也是在Base裡表示主光,Add裡表示像素光。

  (3)unity_LightColor是距離物體最近的4個point光,也就是說同一個場景中每個物體的這4個光不一樣,注意這4個point光的選擇非常有意思;

    (a)當shader中沒有ForwardAdd Pass的時候,unity_LightColor記錄了4盞vertex point光源,無視pixel光;

    (b)當shader中包含ForwardAdd Pass的時候,unity_LightColor記錄了4盞point光源,pixel比vertex優先。

  (4)如果場景中有多個pixel光,則對每一個物體,所有的非主光的pixel光都會執行一遍ForwardAdd Pass,按照強度大小、平行光優先的順序來執行;

  (5)不要在ForwardAdd Pass裡面使用unity4LightPosX/Y/Z等資料,因為它們就是給ForwardBase Pass使用的,而且如果其中有pixel光,它們本身就會對ForwardAdd執行一遍;

  (6)可以使用Shade4PointLights函數在ForwardBase中計算Vertex光源的照明。

  Deferred shading:

  Vertex-lit rendering(Vertex标記的pass):

  頂點光照可以使用最多8盞光源,這些光源按照亮度排序,按順序存儲在一下這些資料結構中,如果光源數量少于8,那麼多出來的都将黑色:

  (1)_LightColor0表示unity_LightColor[0]

  (2)unity_LightPosition是MV空間中的位置

  (3)逐頂點光照函數float4 ShadeVertexLights(float4 vertex, float3 normal)

  注意:

  (1)_LightColor0變量不代表某個具體含義,它在不同的Render Path和Pass裡面是有不同的意義的

  (2)ShaderLab裡面的内置變量是不會及時清理的,這是Unity處于性能方面的考慮,因為在CPU和GPU之間頻繁傳遞資料是很耗資源的

  Fog和Ambient環境光資訊:

使用multi_compile編譯Shader的多個版本:

  有時候我們希望保留一個shader的大多數實作,而隻是做一些細節的修改,此時我們就可以通過該方式來生成shader的多個版本,然後在代碼中控制使用哪個版本。

  指令:

  #pragma multi_compile FANCY_STUFF_OFF FANCY_STUFF_ON

  控制:

  Material.EnableKeyword(keyword: string)/DisableKeyword(keyword: string)

  Shader.EnableKeyword(keyword: string)/DisableKeyword(keyword: string)

  在shader中根據定義好的關鍵字處理具體顯示方案:

  注意不要在shader中大量使用此指令,因為關鍵字的個數是有上限的,而多條multi_complie會交叉比對産生很多種結果。

GLSL shader程式設計

  在Shader中,除了Cg/HLSL以外,GLSL(OpenGL Shading Languate)也可以直接使用。

  一般不建議使用GLSL,除非你确定你的目标平台隻有Max OS X或相容OpenGL ES 2.0的移動裝置。

  Unity預設都會将Cg/HLSL交叉編譯出優化過得GLSL,以此來支援多平台。在desktop平台下可以通過打開#pragma glsl選項來支援。

平台特性相關的渲染差異:

  Unity封裝了大多數的平台問題,但有些時候還是需要自己處理一下的。

  紋理坐标:

  Direct3D裡面是左上角為原點;

  OpenGL和OpenGL ES是左下角為原點。

  多數時候都ok,除了在Render To Texture時。但是在RTT時,Unity對于D3D平台會自動将渲染的貼圖上下翻轉一下,以此隐藏了各平台的差異。

  D3D平台下,有一種情況不需要Unity自動翻轉渲染貼圖,那就是使用Image Effects和Anti-Aliasing時,因為直接渲染到Screen了,

  需要手動處理的情況:但同時使用screen texture和RenderTexture時,有可能會得到不一緻的坐标朝向,此時就需要在shader裡面通過代碼處理了:

  AlphaTest:

  在OpenGL ES 2.0和Direct3D 11中,沒有alpha testing的固定函數。是以在編寫programmable shader時,建議在pixel shader中使用CG/HLSL clip()函數來替代。

  D3D 11 shader編譯器比較挑剔:

  D3D 9和OpenGL使用NVIDIA的Cg來編譯shader,但D3D 11使用微軟的HLSL來編譯,此時就會産生一些差異化。

  OpenGL ES 2.0隻支援部分GLSL原生的東西,是以Unity實作了一些内置的參數,讓其以OpenGL的方式工作,但是也有一些參數是沒有的。

CSDN部落格:http://blog.csdn.net/candycat1992/article/details/47284289

繼續閱讀