Unity中Shader的示例分析
Unity中Shader的示例分析
这篇文章给大家分享的是有关Unity中Shader的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
模板测试概要
言归正传,stencil与颜色缓冲区和深度缓冲区类似,模板缓冲区可以为屏幕上的每个像素点保存一个无符号整数值(通常的话是个8位整数)。这个值的具体意义视程序的具体应用而定。在渲染的过程中,可以用这个值与一个预先设定的参考值相比较,根据比较的结果来决定是否更新相应的像素点的颜色值。这个比较的过程被称为模板测试。模板测试发生在透明度测试(alpha test)之后,深度测试(depth test)之前。如果模板测试通过,则相应的像素点更新,否则不更新。图形渲染管线中,基于单个像素的测试操作的顺序如下图
模板测试语法
一般来说,stencil完整语法格式如下:
stencil{RefreferenceValueReadMaskreadMaskWriteMaskwriteMaskCompcomparisonFunctionPassstencilOperationFailstencilOperationZFailstencilOperation}
Ref
RefreferenceValue
Ref用来设定参考值referenceValue,这个值将用来与模板缓冲中的值进行比较。referenceValue是一个取值范围位0-255的整数。
ReadMask
ReadMaskreadMask
ReadMask 从字面意思的理解就是读遮罩,readMask将和referenceValue以及stencilBufferValue进行按位与(&)操作,readMask取值范围也是0-255的整数,默认值为255,二进制位11111111,即读取的时候不对referenceValue和stencilBufferValue产生效果,读取的还是原始值。
WriteMask
WriteMaskwriteMask
WriteMask是当写入模板缓冲时进行掩码操作(按位与【&】),writeMask取值范围是0-255的整数,默认值也是255,即当修改stencilBufferValue值时,写入的仍然是原始值。
Comp
CompcomparisonFunction
Comp是定义参考值(referenceValue)与缓冲值(stencilBufferValue)比较的操作函数,默认值:always
Pass
PassstencilOperation
Pass是定义当模板测试(和深度测试)通过时,则根据(stencilOperation值)对模板缓冲值(stencilBufferValue)进行处理,默认值:keep
Fail
FailstencilOperation
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&readMaskcomparisonFunctionstencilBufferValue&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{Ref2CompalwaysPassreplace}
在上面的代码中,第一行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中的关键代码:
ColorMask0ZWriteOffStencil{Ref1CompAlwaysPassReplace}
上面这段代码中,ColorMask 0作用是屏蔽颜色的输出,即不输出颜色到屏幕。ZWrite Off用来关闭深度写入,防止深度测试中后面的角色的像素被剔除掉;在stencil中 Ref 1将referenceValue设置成1,Comp Always 保证模板测试始终通过,Pass Replace 操作则将stencilBufferValue刷新为1;即这段代码的功能是在屏幕上对应模型的位置不输入任何颜色,而将对应位置的模板缓冲值刷新为1;
接下来需要在角色使用的shader中添加如下关键代码:
Stencil{Ref1CompEqual}
,
上面这段代码中,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"}CGINCLUDEstructappdata{float4vertex:POSITION;};structv2f{float4pos:SV_POSITION;};v2fvert(appdatav){v2fo;o.pos=mul(UNITY_MATRIX_MVP,v.vertex);returno;}half4frag(v2fi):SV_Target{returnhalf4(1,1,0,1);}ENDCGPass{ColorMask0ZWriteOffStencil{Ref1CompAlwaysPassReplace}CGPROGRAM#pragmavertexvert#pragmafragmentfragENDCG}}}
Shader"Custom/UnlitStencilVF"{Properties{_MainTex("Base(RGB)",2D)="white"{}}SubShader{Tags{"Queue"="Geometry""RenderType"="Opaque"}LOD100Pass{Stencil{Ref1CompEqual}CGPROGRAM#pragmavertexvert#pragmafragmentfrag#pragmamulti_compile_fog#include"UnityCG.cginc"structappdata_t{float4vertex:POSITION;float2texcoord:TEXCOORD0;};structv2f{float4vertex:SV_POSITION;half2texcoord:TEXCOORD0;UNITY_FOG_COORDS(1)};sampler2D_MainTex;float4_MainTex_ST;v2fvert(appdata_tv){v2fo;o.vertex=mul(UNITY_MATRIX_MVP,v.vertex);o.texcoord=TRANSFORM_TEX(v.texcoord,_MainTex);UNITY_TRANSFER_FOG(o,o.vertex);returno;}fixed4frag(v2fi):SV_Target{fixed4col=tex2D(_MainTex,i.texcoord);UNITY_APPLY_FOG(i.fogCoord,col);UNITY_OPAQUE_ALPHA(col.a);returncol;}ENDCG}}}
感谢各位的阅读!关于“Unity中Shader的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
推荐阅读
-
如何将三个变量放在一个表格中(unity pro xl 如何在硬件中添加变量标签)
unityproxl如何在硬件中添加变量标签?不知道你的变量标签是咋系统设置的,我这边打印出来可变数据标签的话,是会先将标签内...
-
VS Code里如何使用Debugger for Unity插件调试
-
Unity如何实现射击小游戏
-
Unity如何实现炸弹人游戏
-
Unity中怎么通过LitJson对JSON数据创建与使用
Unity中怎么通过LitJson对JSON数据创建与使用这篇文章...
-
OpenGL Shader如何实现简单转场效果
-
Unity实现动物识别的代码怎么写
-
怎么用Unity命令行打包WebGL
怎么用Unity命令行打包WebGL本文小编为大家详细介绍“怎么用...
-
如何教训unity与3dmax美工部分的总结
如何教训unity与3dmax美工部分的总结今天给大家介绍一下如何...
-
Unity图形学中的ShaderLab怎么入门