您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Unity中Shader的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
模板測試概要
言歸正傳,stencil與顏色緩沖區和深度緩沖區類似,模板緩沖區可以為屏幕上的每個像素點保存一個無符號整數值(通常的話是個8位整數)。這個值的具體意義視程序的具體應用而定。在渲染的過程中,可以用這個值與一個預先設定的參考值相比較,根據比較的結果來決定是否更新相應的像素點的顏色值。這個比較的過程被稱為模板測試。模板測試發生在透明度測試(alpha test)之后,深度測試(depth test)之前。如果模板測試通過,則相應的像素點更新,否則不更新。圖形渲染管線中,基于單個像素的測試操作的順序如下圖
模板測試語法
一般來說,stencil完整語法格式如下:
stencil{ Ref referenceValue ReadMask readMask WriteMask writeMask Comp comparisonFunction Pass stencilOperation Fail stencilOperation ZFail stencilOperation }
Ref
Ref referenceValue
Ref用來設定參考值referenceValue,這個值將用來與模板緩沖中的值進行比較。referenceValue是一個取值范圍位0-255的整數。
ReadMask
ReadMask readMask
ReadMask 從字面意思的理解就是讀遮罩,readMask將和referenceValue以及stencilBufferValue進行按位與(&)操作,readMask取值范圍也是0-255的整數,默認值為255,二進制位11111111,即讀取的時候不對referenceValue和stencilBufferValue產生效果,讀取的還是原始值。
WriteMask
WriteMask writeMask
WriteMask是當寫入模板緩沖時進行掩碼操作(按位與【&】),writeMask取值范圍是0-255的整數,默認值也是255,即當修改stencilBufferValue值時,寫入的仍然是原始值。
Comp
Comp comparisonFunction
Comp是定義參考值(referenceValue)與緩沖值(stencilBufferValue)比較的操作函數,默認值:always
Pass
Pass stencilOperation
Pass是定義當模板測試(和深度測試)通過時,則根據(stencilOperation值)對模板緩沖值(stencilBufferValue)進行處理,默認值:keep
Fail
Fail stencilOperation
Fail是定義當模板測試(和深度測試)失敗時,則根據(stencilOperation值)對模板緩沖值(stencilBufferValue)進行處理,默認值:keep
ZFail
ZFail是定義當模板測試通過而深度測試失敗時,則根據(stencilOperation值)對模板緩沖值(stencilBufferValue)進行處理,默認值:keep
Comp,Pass,Fail 和ZFail將會應用給背面消隱的幾何體(只渲染前面的幾何體),除非Cull Front被指定,在這種情況下就是正面消隱的幾何體(只渲染背面的幾何體)。你也可以精確的指定雙面的模板狀態通過定義CompFront,PassFront,FailFront,ZFailFront(當模型為front-facing geometry使用)和ComBack,PassBack,FailBack,ZFailBack(當模型為back-facing geometry使用)
模板測試判斷依據
和深度測試一樣,在unity中,每個像素的模板測試也有它自己一套獨立的依據,具體公式如下:
if(referenceValue&readMask comparisonFunction stencilBufferValue&readMask)
通過像素
else
拋棄像素
在這個公式中,主要分comparisonFunction的左邊部分和右邊部分
referenceValue是有Ref來定義的,這個是由程序員來定義的,readMask是模板值讀取掩碼,它和referenceValue進行按位與(&)操作作為公式左邊的結果,默認值為255,即按位與(&)的結果就是referenceValue本身。
stencilBufferValue是對應位置當前模板緩沖區的值,同樣與readMask做按位掩碼與操作,結果做為右邊的部分。
comparisonFunction比較操作通過Comp命令定義,公式左右兩邊的結果將通過它進行判斷,其取值及其意義如下面列表所示。
Greater | 相當于“>”操作,即僅當左邊>右邊,模板測試通過,渲染像素 |
GEqual | 相當于“>=”操作,即僅當左邊>=右邊,模板測試通過,渲染像素 |
Less | 相當于“<”操作,即僅當左邊<右邊,模板測試通過,渲染像素 |
LEqual | 相當于“<=”操作,即僅當左邊<=右邊,模板測試通過,渲染像素 |
Equal | 相當于“=”操作,即僅當左邊=右邊,模板測試通過,渲染像素 |
NotEqual | 相當于“!=”操作,即僅當左邊!=右邊,模板測試通過,渲染像素 |
Always | 不管公式兩邊為何值,模板測試總是通過,渲染像素 |
Never | 不敢公式兩邊為何值,模板測試總是失敗 ,像素被拋棄 |
模板緩沖值的更新
在上一步的模板測試之后,無論模板測試通過與否,都要對模板進行相應的更新。具體到怎么更新,則由程序員自己定義。上面關于模板緩沖語法中,Pass,Fail,ZFail等命令就是根據不同判斷條件對模板緩沖區的值(stencilBufferValue)進行更新的操作,這些命令取值(stencilOperation)的類型及意義如下面列表所示:
Keep | 保留當前緩沖中的內容,即stencilBufferValue不變。 |
Zero | 將0寫入緩沖,即stencilBufferValue值變為0。 |
Replace | 將參考值寫入緩沖,即將referenceValue賦值給stencilBufferValue。 |
IncrSat | stencilBufferValue加1,如果stencilBufferValue超過255了,那么保留為255,即不大于255。 |
DecrSat | stencilBufferValue減1,如果stencilBufferValue超過為0,那么保留為0,即不小于0。 |
Invert | 將當前模板緩沖值(stencilBufferValue)按位取反 |
IncrWrap | 當前緩沖的值加1,如果緩沖值超過255了,那么變成0,(然后繼續自增)。 |
DecrWrap | 當前緩沖的值減1,如果緩沖值已經為0,那么變成255,(然后繼續自減) 。 |
在更新模板緩沖值的時候,也有writeMask進行掩碼操作,用來對特定的位進行寫入和屏蔽,默認值為255(11111111),即所有位數全部寫入,不進行屏蔽操作。
舉個如下的例子:
stencil{ Ref 2 Comp always Pass replace }
在上面的代碼中,第一行Ref 2這行將referenceValue定義為2;
第二行中,Comp命令后的參數是always,此時我們不管stencilBufferValue為多少,模板測試都是成功通過的;
而第三行中,Pass replace的意思是,當模板測試通過則將referenceValue替換給stencilBufferValue,此時
stencilBufferValue值為2,因此上面的例子功能相當于將stencilBufferValue刷新為2;
小結
上面說了這么多,主要的重點如下
使用模板緩沖區最重要的兩個值:當前模板緩沖值(stencilBufferValue)和模板參考值(referenceValue)
模板測試主要就是對這個兩個值使用特定的比較操作:Never,Always,Less ,LEqual,Greater,Equal等等。
模板測試之后要對模板緩沖區的值(stencilBufferValue)進行更新操作,更新操作包括:Keep,Zero,Replace,IncrSat,DecrSat,Invert等等。
模板測試之后可以根據結果對模板緩沖區做不同的更新操作,比如模板測試成功操作Pass,模板測試失敗操作Fail,深度測試失敗操作ZFail,還有正對正面和背面精確更新操作PassBack,PassFront,FailBack等等。
實例操作
上面主要是理論知識,下面將通過一個實例大概了解下stencil的簡單應用,使用stencil緩沖用來限制渲染區域,效果如下:
這個實例需要兩個shader實現,如上面的那個用來限制區域的box所使用的shader中的關鍵代碼:
ColorMask 0 ZWrite Off Stencil{ Ref 1 Comp Always Pass Replace }
上面這段代碼中,ColorMask 0作用是屏蔽顏色的輸出,即不輸出顏色到屏幕。ZWrite Off用來關閉深度寫入,防止深度測試中后面的角色的像素被剔除掉;在stencil中 Ref 1將referenceValue設置成1,Comp Always 保證模板測試始終通過,Pass Replace 操作則將stencilBufferValue刷新為1;即這段代碼的功能是在屏幕上對應模型的位置不輸入任何顏色,而將對應位置的模板緩沖值刷新為1;
接下來需要在角色使用的shader中添加如下關鍵代碼:
Stencil { Ref 1 Comp Equal }
,
上面這段代碼中,Ref 1將referenceValue設置成1,在接下來的一行代碼中,Comp Equal的意思是,如果referenceValue=stencilBufferValue,則模板測試通過,渲染像素,否則拋棄;在這個例子中,由于屏幕中的像素默認的模板值(stencilBufferValue)為0(我猜的,貌似是正確的哈)而參考值referenceValue為1,,所以正常情況下使用這個shader的模型是不顯示的,但是在使用了第一個shader的box區域,由于stencilBufferValue被刷新為1,所以在這個區域中,角色是能夠顯示的。
本例完整代碼如下:
Shader "Custom/UnlitStencilMaskVF" { SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry-1"} CGINCLUDE struct appdata { float4 vertex : POSITION; }; struct v2f { float4 pos : SV_POSITION; }; v2f vert(appdata v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); return o; } half4 frag(v2f i) : SV_Target { return half4(1,1,0,1); } ENDCG Pass { ColorMask 0 ZWrite Off Stencil { Ref 1 Comp Always Pass Replace } CGPROGRAM #pragma vertex vert #pragma fragment frag ENDCG } } }
Shader "Custom/UnlitStencilVF" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "Queue" = "Geometry""RenderType"="Opaque" } LOD 100 Pass { Stencil { Ref 1 Comp Equal } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; half2 texcoord : TEXCOORD0; UNITY_FOG_COORDS(1) }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata_t v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.texcoord); UNITY_APPLY_FOG(i.fogCoord, col); UNITY_OPAQUE_ALPHA(col.a); return col; } ENDCG } } }
感謝各位的閱讀!關于“Unity中Shader的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。