一、Unity中Shader的三種形態(tài)
1.1 固定功能Shader
其特征是里面的核心是Material材質(zhì)屬性塊、沒(méi)有CGPROGRAM和ENDCG塊,以及各種頂點(diǎn)著色和片段著色的宏命令。
1.2 SurfaceShader
特性如下:
SurfaceShader可以認(rèn)為是一個(gè)光照Shader的語(yǔ)法塊、一個(gè)光照VS/FS的生成器。減少了開(kāi)發(fā)者寫(xiě)重復(fù)代碼的需要。
特征是在SubShader里出現(xiàn)CGPROGRAM和ENDCG塊。(而不是出現(xiàn)在Pass里。因?yàn)镾urfaceShader自己會(huì)編譯成多個(gè)Pass。)
編譯指令是:
#pragma surface surfaceFunction lightModel[optionalparams]
surfaceFunction:surfaceShader函數(shù),形如void surf (Input IN, inoutSurfaceOutput o)
lightModel:使用的光照模式。包括Lambert(漫反射)和BlinnPhong(鏡面反射)。
也可以自己定義光照函數(shù)。比如編譯指令為#pragma surface surf MyCalc
在Shader里定義half4 LightingMyCalc (SurfaceOutputs, 參數(shù)略)函數(shù)進(jìn)行處理(函數(shù)名在簽名加上了“Lighting”)。
我們自己定義輸入數(shù)據(jù)結(jié)構(gòu)(比如上面的Input)、編寫(xiě)自己的Surface函數(shù)處理輸入、最終輸出修改過(guò)后的SurfaceOutput。
SurfaceOutput的定義為:
struct SurfaceOutput
{
half3 Albedo; // 紋理顏色值(r, g, b)
half3 Normal; // 法向量(x, y, z)
half3 Emission; // 自發(fā)光顏色值(r, g, b)
half Specular; // 鏡面反射度
half Gloss; // 光澤度
half Alpha; // Alpha不透明度
};
1.3 可編程Shader
可編程Shader其實(shí)就是頂點(diǎn)著色器和片段著色器,這一部分和DirectX系的HLSL和CG著色器語(yǔ)言聯(lián)系緊密。其實(shí)就是Unity給HLSL和CG報(bào)了一個(gè)ShaderLab的殼。
頂點(diǎn)著色器:產(chǎn)生紋理坐標(biāo),顏色,點(diǎn)大小,霧坐標(biāo),然后把它們傳遞給裁剪階段。
片段著色器:進(jìn)行紋理查找,決定什么時(shí)候執(zhí)行紋理查找,是否進(jìn)行紋理查找,及把什么作為紋理坐標(biāo)。
可編程Shader的特點(diǎn)為:
功能最強(qiáng)大、最自由的形態(tài)。
特征是在Pass里出現(xiàn)CGPROGRAM和ENDCG塊
編譯指令#pragma。詳見(jiàn)官網(wǎng)Cg snippets。其中重要的包括:
| 編譯指令 | 示例/含義 |
|---|---|
| #pragma vertex name #pragma fragment name |
替換name,來(lái)指定Vertex Shader函數(shù)、Fragment Shader函數(shù)。 |
| #pragma target name | 替換name(為2.0、3.0等)。設(shè)置編譯目標(biāo)shader model的版本。 |
| #pragma only_renderers name name ... #pragma exclude_renderers name name... |
#pragma only_renderers gles gles3, #pragma exclude_renderers d3d9 d3d11 opengl,只為指定渲染平臺(tái)(render platform)編譯 |
關(guān)于引用庫(kù)。通過(guò)形如#include "UnityCG.cginc"引入指定的庫(kù)。常用的就是UnityCG.cginc了。其他庫(kù)詳見(jiàn)官網(wǎng)Built-in shader include files。
ShaderLab內(nèi)置值。Unity給Shader程序提供了便捷的、常用的值,比如下面例子中的UNITY_MATRIX_MVP就代表了這個(gè)時(shí)刻的MVP矩陣。詳見(jiàn)官網(wǎng)ShaderLab built-in values。
Shader輸入輸出參數(shù)語(yǔ)義(Semantics)。在管線流程中每個(gè)階段之間(比如Vertex Shader階段和FragmentShader階段之間)的輸入輸出參數(shù),通過(guò)語(yǔ)義字符串,來(lái)指定參數(shù)的含義。常用的語(yǔ)義包括:COLOR、SV_Position、TEXCOORD[n]。完整的參數(shù)語(yǔ)義可見(jiàn)HLSL Semantic(由于是HLSL的連接,所以可能不完全在Unity里可以使用)。
特別地,因?yàn)閂ertex Shader的的輸入往往是管線的最開(kāi)始,Unity為此內(nèi)置了常用的數(shù)據(jù)結(jié)構(gòu):
| 數(shù)據(jù)結(jié)構(gòu) | 含義 |
|---|---|
| appdata_base | 頂點(diǎn)著色器輸入位置、法線以及一個(gè)紋理坐標(biāo)。 |
| appdata_tan | 頂點(diǎn)著色器輸入位置、法線、切線以及一個(gè)紋理坐標(biāo)。 |
| appdata_full | 頂點(diǎn)著色器輸入位置、法線、切線、頂點(diǎn)顏色以及兩個(gè)紋理坐標(biāo)。 |
| appdata_img | 頂點(diǎn)著色器輸入位置以及一個(gè)紋理坐標(biāo)。 |
二、 Blending
混合操作最常見(jiàn)的用途便是用來(lái)制作透明物體、或者是進(jìn)行紋理的混合。它是Shader渲染的最后一步:

如上圖所示,正被渲染的像素經(jīng)過(guò)頂點(diǎn)光照、頂點(diǎn)著色器、剔除和深度測(cè)試,霧效、Alpha測(cè)試等一系列操作之后,最后一步便是混合操作。這個(gè)時(shí)候計(jì)算結(jié)果即將被輸出到幀緩沖中。而混合操作,就是管理如何將這些像素輸出到幀緩存中的這樣一個(gè)過(guò)程——是直接替換原來(lái)的,是一加一的混合,還是有Alpha參與的不等比地混合等等。
混合操作有兩個(gè)對(duì)象:源和目標(biāo),因此也有兩個(gè)對(duì)應(yīng)的因子,即源因子和目標(biāo)因子(對(duì)應(yīng)于Blend SrcFactor DstFactor操作)。
而如果我們把RGB顏色通道和Alpha通道分開(kāi)來(lái)操作的話,混合就有了4個(gè)操作對(duì)象(對(duì)應(yīng)于Blend SrcFactor DstFactor,SrcFactorA DstFactorA操作)。
2.1 相關(guān)語(yǔ)法
Blend Off
Turn off blending 關(guān)閉混合
Blend SrcFactorDstFactor
基本的配置并啟動(dòng)混操作。對(duì)產(chǎn)生的顏色乘以SrcFactor.對(duì) 已存在于屏幕的顏色乘以DstFactor,并且兩者將被疊加在一起。
Blend SrcFactorDstFactor, SrcFactorA DstFactorA
同上,但是使用不同的要素來(lái)混合alpha通道,也就是有了4個(gè)操作對(duì)象
BlendOp Add /Min | Max | Sub | RevSub
此操作不是Blend操作一樣添加混合顏色在一起,而是對(duì)它們做不同的操作。
而如下便是常用混合操作符(blend operations)的含義列舉:
| 操作符 | 含義 |
|---|---|
| Add | 將源像素和目標(biāo)像素相加. |
| Sub | 用源像素減去目標(biāo)像素 |
| RevSub | 用目標(biāo)像素減去源像素 |
| Min | 取目標(biāo)像素和源像素顏色的較小者作為結(jié)果 |
| Max | 取目標(biāo)像素和源像素顏色的較大者作為結(jié)果 |
2.2 Blend factors列舉
以下所有的屬性都可作為SrcFactor或DstFactor。其中,Source指的是被計(jì)算過(guò)的顏色,Destination是已經(jīng)在屏幕上的顏色。
| 屬性 | 值 |
|---|---|
| One | 值為1,使用此因子來(lái)讓幀緩沖區(qū)源顏色或是目標(biāo)顏色完全的通過(guò)。 |
| Zero | 值為0,使用此因子來(lái)刪除幀緩沖區(qū)源顏色或目標(biāo)顏色的值。 |
| SrcColor | 使用此因子為將當(dāng)前值乘以幀緩沖區(qū)源顏色的值 |
| SrcAlpha | 使用此因子為將當(dāng)前值乘以幀緩沖區(qū)源顏色Alpha的值。 |
| DstColor | 使用此因子為將當(dāng)前值乘以幀緩沖區(qū)源顏色的值。 |
| DstAlpha | 使用此因子為將當(dāng)前值乘以幀緩沖區(qū)源顏色Alpha分量的值。 |
| OneMinusSrcColor | 使用此因子為將當(dāng)前值乘以(1 -幀緩沖區(qū)源顏色值) |
| OneMinusSrcAlpha | 使用此因子為將當(dāng)前值乘以(1 -幀緩沖區(qū)源顏色Alpha分量的值) |
| OneMinusDstColor | 使用此因子為將當(dāng)前值乘以(1 –目標(biāo)顏色值) |
| OneMinusDstAlpha | 使用此因子為將當(dāng)前值乘以(1 –目標(biāo)Alpha分量的值) |
2.3 常見(jiàn)語(yǔ)句
Blend SrcAlpha OneMinusSrcAlpha // Alpha混合
Blend One One // 相加
Blend One OneMinusDstColor // 比較柔和的相加(SoftAdditive)
Blend DstColor Zero // 乘法
Blend DstColor SrcColor // 2倍乘法