Unity Shader模板测试

发表于2018-07-15
评论0 7k浏览
模板测试stencil test是3d渲染管线中介于透明测试alpha test和深度测试depth test之间的测试,目的是根据条件来比较设置的参考值referenceValue和模板缓冲区stencil buff中对应的值stencilBuffValue的大小,如果条件满足就让片段fragment(候选的像素)进入下一测试,即深度测试,条件不满足就过滤掉片段,不把对应材质的片段输出到屏幕。

条件判断公式如下:
if(referenceValue & readMask comparisonFunction stencilBuffValue & readMask)
    条件满足,通过片段
else
    条件不满足,过滤片段
其中,stencilBuffValue是模板缓存中的值,其他由我们定义。

语法

1、命令
Stencil
{
    Ref referenceValue //参考值
    ReadMask  readMask  //读取掩码,取值范围也是0-255的整数,默认值为255,二进制位11111111,即读取的时候不对referenceValue和stencilBufferValue产生效果,读取的还是原始值
    WriteMask writeMask  //输出掩码,当写入模板缓冲时进行掩码操作(按位与【&】),writeMask取值范围是0-255的整数,默认值也是255,即当修改stencilBufferValue值时,写入的仍然是原始值
    Comp comparisonFunction  //条件,关键字有,Greater(>),GEqual(>=),Less(<),LEqual(<=),Equal(=),NotEqual(!=),Always(总是满足),Never(总是不满足)
    Pass stencilOperation  //条件满足后的处理
    Fail stencilOperation  //条件不满足后的处理
    ZFail stencilOperation  //深度测试失败后的处理
}

2、Comparison Function
比较函数是其中之一:
- Greater
只显示引用值大于缓冲区值的像素。
- GEqual
仅呈现引用值大于或等于缓冲区中的值的像素
- Less
只显示引用值小于缓冲区中值的像素。
- LEqual
仅呈现引用值小于或等于缓冲区中的值的像素。
- Equal
只呈现引用值等于缓冲区中的值的像素。
- NotEqual
只呈现引用值与缓冲区中的值不同的像素。
- Always
让模板测试总是通过。
- Never
让模板测试总是失败。

3、更新操作:
Pass(模板测试和深度测试都通过了,该如果更新深度缓冲)、Fail(当模板测试和深度测试失败时)、ZFail(当模板测试通过而深度测试失败时)可设置的关键字如下:
- 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,(然后继续自减)。

穿透效果:

创建三个GameObject按照离相机有近到远分别是Sphere_InfrontWall、Wall、Cube_BehindWall。

由于Stencil的设置与渲染顺序有关,因此这里先使用Render Queue固定渲染顺序为:Wall、Sphere_InfrontWall、Cube_BehindWall(可任意设定,并根据设定的顺序编写Stencil代码)


附上代码:
Shader "Hidden/Wall"
{
    Properties
    {
        _MainColor ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always
        Tags { "Queue" = "Background" }
        Pass
        {
            Stencil
            {
                Ref 9
                Comp Always
                Pass Replace
                //此时,模板缓冲值为9
            }
            Color[_MainColor]
        }
    }
}

Shader "Hidden/InfrontWall"
{
    Properties
    {
        _MainColor ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always
        Tags { "Queue" = "Geometry" }
        Pass
        {
            Stencil
            {
                Ref 2
                //丢掉与Wall重叠的区域
                Comp NotEqual
                Pass Replace
                // 此时模板缓冲值为2
            }
            Color[_MainColor]
        }
    }
}

Shader "Hidden/BehindWall"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always
        Tags { "Queue" = "Transparent" }
        Pass
        {
            Stencil
            {
                Ref 2
                Comp Equal 
                //显示与InfrontWall重叠的区域
            }
            SetTexture[_MainTex]
        }
    }
}
来自:https://blog.csdn.net/v_xchen_v/article/details/79380258

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引