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有关的物体不显示问题,下篇文章将详细讲解该问题,并提供解决方法。

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/10028.html
欢迎加入梓喵出没博客交流群:313732000

我来吐槽

*

*