Shader:双向穿越魔法门(Stencil Test)
很久之前在某 3D 滑动列表中用过模板测试(Stencil Test),这次回顾,尝试用它搞一个双面穿越门出来。
效果
原理
把一个值写入 Stencil Buffer 中,后续同位置的其他片元渲染时,若开启了模板测试,将会把自身的预设值与 Stencil Buffer 中的值对比(即 Test),基于比较结果进行片元剔除、Buffer 值更改等操作。
因此,用一个 Shader 把 Stencil Buffer 写入,门后的物体在之后渲染,用模板测试剔除不在范围内的片元,即可完成效果。
本文的效果采用双面渲染,正反面渲染写入不同的 Stencil,并有一个 C# 脚本根据摄像机位置实时调整相关参数,比单面挂墙贴画之类的要麻烦一些。
代码
Build-in 管线和 URP 有些不同,后面会提一嘴。
“MASK” Shader
增加对 Stencil 的写入:
Stencil
{
Ref [_Stencil] //注意 Stencil 为 Properties 中定义的 Int 值,取值(0-255)
Comp Always
Pass Replace
Fail Keep
ZFail Keep
//CompBack Always
//PassBack Replace
//FailBack Keep
//ZFailBack Keep
//CompFront Always
//PassFront Replace
//FailFront Keep
//ZFailFront Keep
}
关掉 ZWrite,以便让后面的物体能通过 ZTest(StencilZFail 是对模板的操作,救不了片元):
ZWrite Off
改一下 Alpha Blend 方式,一般使用 Zero One。
至于是否要加 PS 或 VS 上个色,看自己需求,一般意义不大。
物体
Build-in 管线
物体 Shader 增加和上文类似的模板测试代码,改一下 Test 方法(Comp),并酌情修改 Pass 和 Fail 的行为。
物体渲染顺序要高于 “Mask” Shader,即在 Stencil 值写入后再渲染。
URP
URP 可以用 RenderObjects 来控制渲染顺序和模板测试,举个例子:
上述配置是让 StencilEnv 层的不透明队列物体,在其他不透明物体渲染完成之后渲染,并应用指定的模板测试。
这样做不用改物体 Shader,非常方便。
当然,为了不让 StencilEnv 提前渲染,还需要在顶级 Filter 中取消 StencilEnv 层:
半透明队列物体与之类似,略过不表。
其他
如果是自己手撸的 Shader,在 URP 下可能会遇到和Depth Priming Mode
有关的物体不显示问题,下篇文章将详细讲解该问题,并提供解决方法。