千家信息网

Unity中Shader的示例分析

发表于:2024-09-21 作者:千家信息网编辑
千家信息网最后更新 2024年09月21日,这篇文章给大家分享的是有关Unity中Shader的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。模板测试概要言归正传,stencil与颜色缓冲区和深度缓冲区类似,
千家信息网最后更新 2024年09月21日Unity中Shader的示例分析

这篇文章给大家分享的是有关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。
IncrSatstencilBufferValue加1,如果stencilBufferValue超过255了,那么保留为255,即不大于255。
DecrSatstencilBufferValue减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的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

模板 测试 缓冲 像素 更新 深度 代码 右边 缓冲区 参考 公式 参考值 结果 就是 颜色 几何 几何体 区域 命令 屏幕 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全法修改案2020 龙族幻想 本服务器注册 广东品质软件开发服务价钱 福建华工网络技术有限公司 畅捷通服务器作用 软件开发backlog需求 电厂保障网络安全方案 服务器logo设计图片大全 如何彻底删除u盘数据库 网络安全教育漫画作品 如何守住网络安全底线 服务器管理的目的 专门针对软件开发问答网站 东营商城软件开发解决方案 明日之后秋日森林合区服务器名单 if重复数据库 数据库访问技术pdf 共同筑牢网络安全防线时评作文 对网络安全攻击的看法 计算机三级网络技术考几门 效益好的科技和互联网公司 学软件开发技术哪种好找工作 方舟生存进化服务器突然不见了 池州求职招聘软件开发哪家好 诺基亚手机软件开发 计算机网络技术课多不多 塔科夫希腊服务器 华为存储服务器怎么设置不了 三网融合指哪三个网络技术 世界最好的网络安全学校
0