從今天起,開始翻譯Unity關於shader的官方文檔。翻譯水平比較通常,目的主要是經過翻譯來提高對shader的看法,也讓其餘人更容易的瞭解shader。如下開始正文內容:html
和光交互的shader寫起來很複雜,有不一樣的光照類型、陰影選項、渲染路徑(正向渲染和延遲渲染),有時shader須要考慮全部的複雜性。數據結構
Unity中的Surface Shader是一個代碼生成器,用它來寫光照shader(lit shader)相比於使用低階的頂點/像素shader(vertex/pixel shader)程序,會更加容易。注意Surface Shader中並無固定的語言和奇幻的東西(magic or ninjas involved)。它僅僅是生成本來必須由手工重複編寫的代碼。你也能夠用Cg/HLSL來寫shader代碼。app
這裏有一些例子: Surface Shader Examples、Surface Shader Custom Lighting Examples。函數
你定義一個「surface 函數」,其輸入是你所須要的任意UVs或數據,輸出是SurfaceOutput數據結構。SurfaceOutput簡單地描述了surface的屬性(properties of the surface),如反射率顏色(albedo color)、法線(normal)、散射(emission)、鏡面反射(specularity )等。學習
Surface Shader編譯器會肯定須要什麼輸入,有什麼輸出等,也會產生實際的頂點&像素shader(vertex&pixel shaders),以及渲染路徑來處理正向和延遲渲染。測試
surface標準的輸出結構以下:動畫
struct SurfaceOutput
2 { 3 fixed3 Albedo; // 漫反射顏色 4 fixed3 Normal; // 切線空間法線,若是賦值的話 5 fixed3 Emission; 6 half Specular; // 高光強度,範圍是0-1 7 fixed Gloss; // specular intensity 8 fixed Alpha; // 透明度 9 };
在Unity 5中,surface shader 也能使用物理光照模型。內建的標準和標準鏡面光照模型(見下文)分別使用如下輸出結構:spa
struct SurfaceOutputStandard
{
fixed3 Albedo; // 基礎 (漫反射或鏡面反射) 顏色
fixed3 Normal; // 切線空間法線,若是賦值的話
half3 Emission; half Metallic; // 0=非金屬, 1=金屬 half Smoothness; // 0=粗糙, 1=光滑 half Occlusion; // 遮擋(默認1) fixed Alpha; // 透明度 }; struct SurfaceOutputStandardSpecular { fixed3 Albedo; // 漫反射顏色 fixed3 Specular; // 鏡面反射顏色 fixed3 Normal; // 切線空間法線,若是賦值的話 half3 Emission; half Smoothness; // 0=粗糙, 1=光滑 half Occlusion; // 遮擋(默認1) fixed Alpha; // 透明度 };
參見:Surface Shader Examples, Surface Shader Custom Lighting Examples and Surface Shader Tessellation。翻譯
Surface shader放在CGPROGRAM..ENDCG塊中,就像其餘任何的shader同樣。不一樣處在於:3d
#pragma surface指令以下:
#pragma surface surfaceFunction lightModel [optionalparams]
透明度和alpha測試(Transparency and alpha testing)由alpha和alphatest指令控制。一般透明度有兩種類型:傳統alpha混合(用於對象淡出)或更逼近物理的「混合預乘」(容許半透明的表面保持合適的鏡面反射)。開啓半透明度使得產生的surface shader代碼包含blending指令:基於給定的變量,開啓alpha裁剪將會在生成的像素shader中進行碎片丟棄。
alpha
或 alpha:auto — 將會選擇fade-transparency (同alpha:fade
)做爲簡單的光照函數,選擇premultiplied transparency (同alpha:premul
)做爲物理光照函數。
alpha:fade
— 容許傳統的透明度漸隱。alpha:premul
— 容許預乘alpha透明度。alphatest:VariableName
— 容許alpha裁剪透明度。截斷值是一個名爲VariableName的float類型變量。你還可使用addshadow指令來生成合適的投影通道。keepalpha
— 默認alpha通道中的不透明度爲1.0(白色),不管輸出結構中的Alpha是多少或者光照函數的返回值是多少。decal:add
— 附加的貼花shader(如terrain AddPass)。這對位於其餘表面正上方和使用附加混合的對象來講是有意義的。decal:blend
— 半透明貼花shader。這對位於其餘表面正上方和使用alpha混合的對象來講是有意義的。定製修改器函數(Custom modifier functions)可以用來改變或者計算輸入的頂點數據,或者改變最終計算出的片斷顏色。
vertex:VertexFunction
— 定製頂點修改器函數. 此函數在生成的頂點shader的開始處被調用,能夠修改或計算預頂點數據,參見 Surface Shader Examples。finalcolor:ColorFunction
— 定製的最終顏色修改器函數。參見Surface Shader Examples。陰影和鑲嵌(Shadows and Tessellation)— 附加指令,用於控制陰影和鑲嵌的處理。
addshadow
— 生成一個投影通道。通常還要使用定製頂點修改器,這樣投影也能獲取任何程序上的頂點動畫。 當shader經過fallback來使用投影時,一般不須要任何特別的陰影處理。fullforwardshadows
— 支持 Forward 渲染路徑中全部的光照陰影模型。默認shader只支持正向渲染中來自單方向光產生的陰影。若是你須要用點光源或聚光光源來產生陰影,使用該指令。tessellate:TessFunction
— 使用DX11 GPU 鑲嵌; 該函數計算鑲嵌因子。詳情參見 Surface Shader Tessellation。代碼生成選項 — 默認生成的surface shader代碼會嘗試去處理全部可能的光照/陰影/光照貼圖場景。儘管如此,在某些狀況下你並不須要其中一些,你能夠調整生成的代碼來跳過它們。這樣就能產生更小、加載速度更快的shader。
exclude_path:deferred
, exclude_path:forward
, exclude_path:prepass
- 對於給定的渲染路徑(分別是Deferred Shading, Forward 和 Legacy Deferred),不生成相應的通道。noshadow
— 在此shader中關閉全部支持陰影功能。noambient
— 不該用任何環境光或光照探測(light probes)。novertexlights
— 不在正向渲染中應用任何光照探測或預頂點光照。nolightmap
— 在此shader中關閉全部支持光照貼圖功能。nodynlightmap
— 在此shader中關閉支持運行時動態全局光照(runtime dynamic global illumination)功能。nodirlightmap
- 在此shader中關閉支持方向光照貼圖功能。nofog
— 關閉內建的支持全部霧效果功能。nometa
— 不產生「meta」通道(該meta用來由光照貼圖和動態全局光照提取表面信息)。noforwardadd
— 關閉Forward 渲染附加通道。 這使得shader支持單方向徹底光照,以及全部其餘由每一個頂點/SH計算的光照。同時使得shader更小。混合選項
softvegetation
— 當柔性植被開啓時,surface shader纔會被渲染。interpolateview
— 在頂點shader中計算視線方向並進行插值,而不是在像素shader中進行計算。這使得像素shader更快,但會多消耗一個紋理插值器。halfasview
— 將half-direction 向量,而不是視線方向向量,傳遞給光照函數。Half-direction 將被逐頂點計算和單位化。這會更快,但不會徹底正確。approxview
— 在Unity 5.0中被移除,請用interpolateview
替代。dualforward
- 在forward渲染路徑中使用dual lightmaps 。要了解使用上述不一樣選項所帶來確切的變化,使用Shader Inspector中的「Show Generated Code」 按鈕將會有所幫助。
輸入結構 Input
一般有shader所需的任意紋理座標。紋理座標必須命名爲「uv」+「紋理名稱」(或者以「uv2」開頭,來使用第二個紋理座標集)。
輸入結構中還能放入一下額外的變量:
float3 viewDir
— 將會包含視線方向,用來計算視差影響,邊緣光照等。float4
with COLOR
semantic — 將會包含每一個頂點插值後的顏色。float4 screenPos
— 將會包含反射或屏幕空間影響下的屏幕空間座標。float3 worldPos
— 將會包含世界空間座標。float3 worldRefl
— 若是surface shader沒有賦值o.Normal,將會包含世界反射向量。參見例子:Reflect-Diffuse shader。float3 worldNormal
— 若是surface shader沒有賦值o.Normal,將會包含世界法向量。float3 worldRefl; INTERNAL_DATA
— 若是surface shader沒有賦值o.Normal,將會包含世界法向量。爲了得到逐像素法線貼圖的反射向量,請使用WorldReflectionVector (IN, o.Normal)。參見例子:
Reflect-Bumped shader。float3 worldNormal; INTERNAL_DATA
— 若是surface shader沒有賦值o.Normal,將會包含世界法向量。爲了得到逐像素法線貼圖的法向量,請使用WorldNormalVector (IN, o.Normal)。
目前,surface shader編譯管道的部份內容並不能理解 DirectX 11-特定的HLSL 語法, 因此若是你在使用HLSL特性,諸如StructuredBuffers, RWTextures 和其餘非DX9 語法,你必須將之包含在只針對DX11的預處理器宏中。詳情參見Platform Specific Differences 。