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