Unity3D--StencilTest模板测试
模板测试概要
⾔归正传,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,这个值将⽤来与StencilBuffer进⾏⽐较。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
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)
通过像素
el
抛弃像素
在这个公式中,主要分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
}
}
君士坦丁十一世
}