• Unity3D Shader Stencil模版测试学习


    官方文档地址:

    https://docs.unity3d.com/Manual/SL-Stencil.html

    参考博客:

    http://blog.csdn.net/onafioo/article/details/53943264

    http://blog.csdn.net/u013833399/article/details/47340447

    (因表述的内容都大致一样,一些内容直接引用自原作者)

    1.简介

    在Unity中一个像素会有多个缓存信息,模版缓存(其实Stencil不应该被翻译成模版,但网上都这么写)是其中之一。

    模板缓冲区可以为屏幕上的每个像素点保存一个无符号整数值,

    通过一些比较来改变当前像素区域模版缓冲的值,从而改变深度关系,似乎UGUI的Mask也是通过其实现的

    延迟光照中Stencil有一些限制,具体看unity的文档,这里只介绍正向光照中的使用

    Stencil所在的渲染管线中的顺序位置:

    Stencil的所有参数如下

    Stencil
    {
        Ref 1//Reference Value
        ReadMask 255
        WriteMask 255
        Comp Always //Comparison Function
        Pass Replace
        Fail Keep
        ZFail Replace
    }

    Ref 就是参考值,当参数允许赋值时,会把参考值赋给当前像素

    ReadMask 对当前参考值和已有值进行mask操作,默认值255,一般不用

    WriteMask 写入Mask操作,默认值255,一般不用

    Comp 比较方法。是拿Ref参考值和当前像素缓存上的值进行比较。默认值always

    • Greater - 大于
    • GEqual - 大于等于
    • Less - 小于
    • LEqual - 小于等于
    • Equal - 等于
    • NotEqual - 不等于
    • Always - 永远通过
    • Never - 永远通不过

    Pass 当模版测试和深度测试都通过时,进行处理

    Fail 当模版测试和深度测试都失败时,进行处理

    ZFail 当模版测试通过而深度测试失败时,进行处理

    pass,Fail,ZFail都属于Stencil操作,他们参数统一如下:

    • Keep 保持(即不把参考值赋上去,直接不管)
    • Zero 归零
    • Replace 替换(拿参考值替代原有值)
    • IncrSat 值增加1,但不溢出,如果到255,就不再加
    • DecrSat 值减少1,但不溢出,值到0就不再减
    • Invert 反转所有位,如果1就会变成254
    • IncrWrap 值增加1,会溢出,所以255变成0
    • DecrWrap 值减少1,会溢出,所以0变成255

    2.实践

    下面结合案例,说一下Stencil的使用

    现在有一个球和面片,通过Stencil模版测试把stencil值一致的物体渲染为蓝色

    为了更直观使用了两个shader,面片是shader1,球是shader2

    球肯定是优先渲染,并且设置好stencil的值,面片后渲染,并且判断stencil的值

    文件结构:

    MaskTest2是球的shader

    Shader "Unlit/MaskTest2"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
        }
        SubShader
        {
            Tags{ "RenderType" = "Opaque" "Queue" = "Geometry" }
    
            Stencil
            {
                Ref 1
                Comp Always
                Pass Replace
            }
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
                
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
                
                fixed4 frag (v2f i) : SV_Target
                {
                    return fixed4(1,1,1,1);
                }
                ENDCG
            }
        }
    }
    MaskTest2

    Stencil里,比较条件设置为总通过,通过操作设置为替换Ref值

    这样球部分的像素Stencil值就是1

    Stencil
    {
        Ref 1
        Comp Always
        Pass Replace
    }

    MaskTest1是面片的Shader

    Shader "Unlit/MaskTest1"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
        }
        SubShader
        {
            Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+1" }
    
            Stencil
            {
                Ref 1
                Comp equal
            }
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
                
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
                
                fixed4 frag (v2f i) : SV_Target
                {
                    return fixed4(0,0,1,1);
                }
                ENDCG
            }
        }
    }
    View Code

    Stencil里,比较条件是和Ref值一致时,才会执行渲染

    否则跳出

    Stencil
    {
        Ref 1
        Comp equal
    }

    蓝色是片段shader里写好的

    fixed4 frag (v2f i) : SV_Target
    {
        return fixed4(0,0,1,1);
    }

    这样就可以达到上述效果。

    测试工程文件下载:http://files.cnblogs.com/files/hont/StencilMaskTest.zip

  • 相关阅读:
    修改git提交的用户名和密码
    并发编程大师系列之:wait/notify/notifyAll/condition
    并发编程大师系列之:Synchronized的类锁和对象锁
    并发编程大师系列之:线程的定义和中断 interrupt
    SpringBoot项目mysql配置文件密码加密(jasypt)
    Linux下安装nginx实现伪分布
    idea远程debug调试阿里云ECS
    使用docker简单启动springboot项目
    用Navicat连接阿里云ECS服务器上的MySQL数据库
    Linux下安装JDK1.8
  • 原文地址:https://www.cnblogs.com/hont/p/6579848.html
Copyright © 2020-2023  润新知