溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Unity中Shader的示例分析

發(fā)布時(shí)間:2022-01-05 14:42:39 來源:億速云 閱讀:147 作者:小新 欄目:大數(shù)據(jù)

這篇文章給大家分享的是有關(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è)像素的測試操作的順序如下圖

Unity中Shader的示例分析

模板測試語法

一般來說,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。
IncrSatstencilBufferValue加1,如果stencilBufferValue超過255了,那么保留為255,即不大于255。
DecrSatstencilBufferValue減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ū)域,效果如下:

Unity中Shader的示例分析

這個(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é)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(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)容。

AI