Unity中Shader实现模板测试Stencil

2023-09-20 17:26:51


前言

Unity中Shader实现模板测试


组件中的Mask
在这里插入图片描述
Mask 和 Rect Mask 2D 是UI中的Mask
Sprite Mask 是精灵中的Mask

一、UI中的遮罩

1、Mask ——> 模板测试

2、RectMask2D ——> UNITY_UI_CLIP_RECT


二、模板缓冲区Stencil一般是和Pass平行的部分,Pass部分写的是颜色缓冲区

Stencil:

模板缓冲区(StencilBuffer)可以为屏幕上的每个像素点保存一个无符号整数值,这个值的具体意义视程序的具体应用而定.在渲染的过程中,可以用这个值与一个预先设定的参考值相比较,根据比较的结果来决定是否更新相应的像素点的颜色值.这个比较的过程被称为模板测试.
将StencilBuffer的值与ReadMask与运算,然后与Ref值进行Comp比较,结果为true时进行Pass操作,否则进行Fail操作,操作值写入StencilBuffer前先与WriteMask与运算.

模版缓冲中的默认值为:0
公式:(Ref & ReadMask) Comp (StencilBufferValue & ReadMask)
一般读取掩码ReadMask都是默认的,不做修改
Stencil
{
Ref [_Stencil]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
Comp [_StencilComp] ((UnityEngine.Rendering.CompareFunction))
Pass [_StencilOp] (UnityEngine.Rendering.StencilOp)
Fail [_Fail]
ZFail [_ZFail]
}

Ref: 设定的参考值,这个值将用来与模板缓冲中的值进行比较.取值范围位为0-255的整数.
ReadMask: ReadMask的值将和Ref的值以及模板缓冲中的值进行按位与(&)操作,取值范围也是0-255的整数,默认值为255(二进制位11111111),即读取的时候不对Ref的值和模板缓冲中的值产生修改,读取的还是原始值.
WriteMask: WriteMask的值是当写入模板缓冲时进行的按位与操作,取值范围是0-255的整数,默认值也是255,即不做任何修改.
Comp: 定义Ref与模板缓冲中的值比较的操作函数,默认值为always.
Pass: 当模板测试(和深度测试)通过时,则根据(stencilOperation值)对模板缓冲值进行处理,默认值为keep.
Fail: 当模板测试(和深度测试)失败时,则根据(stencilOperation值)对模板缓冲值进行处理,默认值为keep.
ZFail: 当模板测试通过而深度测试失败时,则根据(stencilOperation值)对模板缓冲值进行处理,默认值为keep

Comp(比较操作)

Less: 相当于“<”操作,即仅当左边<右边,模板测试通过,渲染像素.
Greater: 相当于“>”操作,即仅当左边>右边,模板测试通过,渲染像素.
Lequal: 相当于“<=”操作,即仅当左边<=右边,模板测试通过,渲染像素.
Gequal: 相当于“>=”操作,即仅当左边>=右边,模板测试通过,渲染像素.
Equal: 相当于“=”操作,即仅当左边=右边,模板测试通过,渲染像素.
NotEqual: 相当于“!=”操作,即仅当左边!=右边,模板测试通过,渲染像素.
Always: 不管公式两边为何值,模板测试总是通过,渲染像素.
Never: 不管公式两边为何值,模板测试总是失败 ,像素被抛弃.

Pass(模版缓冲区的更新)

Keep: 保留当前缓冲中的内容,即stencilBufferValue不变.
Zero: 将0写入缓冲,即stencilBufferValue值变为0.
Replace: 将参考值写入缓冲,即将referenceValue赋值给stencilBufferValue.
IncrSat: 将当前模板缓冲值加1,如果stencilBufferValue超过255了,那么保留为255,即不大于255.
DecrSat: 将当前模板缓冲值减1,如果stencilBufferValue超过为0,那么保留为0,即不小于0.
NotEqual: 相当于“!=”操作,即仅当左边!=右边,模板测试通过,渲染像素.
Invert: 将当前模板缓冲值(stencilBufferValue)按位取反.
IncrWrap: 当前缓冲的值加1,如果缓冲值超过255了,那么变成0,(然后继续自增).
DecrWrap: 当前缓冲的值减1,如果缓冲值已经为0,那么变成255,(然后继续自减).


三、实际使用

1、在使用模板缓冲区前,需要如下图设置一个遮罩图层

在这里插入图片描述

2、设置完后,在内层的Image使用的材质的Shader中添加如下代码,即可实现只在有遮罩的部分,渲染后渲染的部分

在这里插入图片描述

Stencil
{
Ref 1
//ReadMask [_StencilReadMask]
//WriteMask [_StencilWriteMask]
Comp Equal
Pass Keep
//Fail [_Fail]
//ZFail [_ZFail]
}

这里的 Stencil Id:1 对应的是Shader中的 Ref 1。
Comp使用Equal,则是用模板缓冲区的值于 Ref 的值相比
Pass使用Keep,则是比较通过的值,保存缓冲区中的值

测试代码:

Shader"MyShader/P1_1_6"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
       
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        Stencil
         {
            Ref 1
            //ReadMask [_StencilReadMask]
            //WriteMask [_StencilWriteMask]
            Comp Equal
            Pass Keep
            //Fail [_Fail]
            //ZFail [_ZFail]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            //存储 应用程序输入到顶点着色器的信息
            struct appdata
            {
                //顶点信息
                float4 vertex:POSITION;
                float2 uv : TEXCOORD;
                //这里定义一个语义为Color的4维向量,用于传入顶点颜色,设置语义为COLOR后,这个变量就会与顶点颜色对应
                fixed4 color:COLOR;
            };
            //存储 顶点着色器输入到片元着色器的信息
            struct v2f
            {
                //裁剪空间下的位置信息(SV_POSITION是必须的)
                float4 pos:SV_POSITION;
                float2 uv : TEXCOORD;
                //这里的语义主要代表精度不同,TEXCOORD 在这里只是代表高精度
                fixed4 color : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            fixed4 _Color;
            v2f vert(appdata v)
            {
                v2f o;
                //把顶点信息转化到裁剪坐标下
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 mainTex = tex2D(_MainTex,i.uv);
                return  mainTex * i.color;
            }
            
            ENDCG
        }
    }
}

效果:
请添加图片描述

四、让实现的模板测试更加方便自定义

1、在属性面板暴露一个int类型,提供给 Ref 使用

_Ref(“Stencil Ref”,int) = 0

2、在属性面板暴露一个int类型,提供给 Comp 使用,并且设置成Unity内置的几个枚举类型[Enum(UnityEngine.Rendering.CompareFunction)]

[Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp(“Stencil Comp”,int) = 0

3、在属性面板暴露一个int类型,提供给 Pass 使用,并且设置成Unity内置的几个枚举类型[Enum(UnityEngine.Rendering.StencilOp)]

[Enum(UnityEngine.Rendering.StencilOp)]_StencilOp(“Stencil Op”,int) = 0

4、最终测试代码

Shader"MyShader/P1_1_6"
{
    Properties
    {
        //命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
        //比如说,在更改 Image 的源图片时,同时更改这个
        [PerRendererData]_MainTex("MainTex",2D) = "white"{}
        //暴露一个变量来供模板测试中 Ref 使用
        _Ref("Stencil Ref",int) = 0
        //暴露一个变量来供模板测试中 Comp 使用
        [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp("Stencil Comp",int) = 0
        
        [Enum(UnityEngine.Rendering.StencilOp)]_StencilOp("Stencil Op",int) = 0
    }
    
    SubShader
    {
        //更改渲染队列(UI的渲染队列一般是半透明层的)
        Tags {"Queue" = "TransParent"}
        //混合模式
        Blend SrcAlpha OneMinusSrcAlpha
        
        Stencil
        {
            Ref [_Ref]
            //以下两个属性一般不做修改
            //ReadMask [_StencilReadMask]
            //WriteMask [_StencilWriteMask]
            Comp [_StencilComp]
            Pass [_StencilOp]
            //Fail [_Fail]
            //ZFail [_ZFail]
        }
        Pass
        {
            CGPROGRAM
            #pragma vertex  vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            //存储 应用程序输入到顶点着色器的信息
            struct appdata
            {
                //顶点信息
                float4 vertex:POSITION;
                float2 uv : TEXCOORD;
                //这里定义一个语义为Color的4维向量,用于传入顶点颜色,设置语义为COLOR后,这个变量就会与顶点颜色对应
                fixed4 color:COLOR;
            };
            //存储 顶点着色器输入到片元着色器的信息
            struct v2f
            {
                //裁剪空间下的位置信息(SV_POSITION是必须的)
                float4 pos:SV_POSITION;
                float2 uv : TEXCOORD;
                //这里的语义主要代表精度不同,TEXCOORD 在这里只是代表高精度
                fixed4 color : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            fixed4 _Color;
            v2f vert(appdata v)
            {
                v2f o;
                //把顶点信息转化到裁剪坐标下
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 mainTex = tex2D(_MainTex,i.uv);
                return  mainTex * i.color;
            }
            
            ENDCG
        }
    }
}

效果:
请添加图片描述

更多推荐

计网第五章(运输层)(四)(TCP的流量控制)

一、基本概念流量控制就是指让发送方的发送速率不要太快,使得接收方来得及接收。可以使用滑动窗口机制在TCP连接上实现对发送方的流量控制。注意:之前在讨论可靠传输时,讨论过选择重传协议和回退N帧协议都是基于滑动窗口的机制上进行实现的。二、具体实现接收方通过向发送方发送带有自己接收窗口值的报文段来控制发送方的发送窗口。注意:

详解TCP/IP协议第五篇:详细介绍网络传输中的地址

文章目录一:通信中地址简介1:地址的唯一性(一):唯一性狭义概念(二):唯一性广义概念2:地址的层次性(一):地址分层的意义(二):MAC地址优劣(三):IP地址的便利一:通信中地址简介通信传输中,发送端和接收端可以被视为通信主体。它们都能由一个所谓“地址”的信息加以标识出来。当人们使用电话时,电话号码就相当于“地址”

中手游上半年扭亏为盈,仙剑IP魅力不减?

你也曾有过江湖梦吗?你也曾因“为国为民、为友为邻”的侠者心无处可安而苦恼吗?那么,“仙剑”系列游戏或许可以成为你的灵魂寄托之所。而能让侠者的江湖梦具象化的幕后厂商,便是中手游。两年前,中手游斥巨资买下了仙剑IP的大陆地区权益,两年内,中手游不断推出仙剑系列游戏新作。其中,公司于今年6月上线的《新仙剑奇侠传之挥剑问情》,

TCP特性的滑动窗口,流量控制

目录一、TCP特性滑动窗口二、TCP特性流量控制(作为滑动窗口的补充)一、TCP特性滑动窗口提高传输效率(更准确的说,让TCP在可靠传输的前提下,效率不太拉跨)💛当然你要是想让TCP媲美UDP,也是痴人说梦,只能说减小差距。一次性发一组数据,发数据的过程中,不需要等待ACK,就直接往前发,此时相当于“一份等待时间”等

TCP socket && UDP && TCP协议 && IP协议 && 以太网等

第1题(编程题)题目名称:编写TCP版本的echoserver和echoclient题目内容:编写TCP版本的echoserver和echoclient第2题(编程题)题目名称:编写TCP版本的字典客户端和字典服务器题目内容:编写TCP版本的字典客户端和字典服务器第3题(编程题)题目名称:编写TCP版本的多线程服务器题

02_Bootstrap基础组件02

4排版使用Bootstrap的排版特性,您可以创建标题、段落、列表及其他内联元素,实际上它是把大部分在HTML的基本标签加了样式。所以这部分相对比较简单。4.1标题h1-h6重新定义样式,HTML中的所有标题标签,<h1>到<h6>均可使用。增加了.h1到.h6类,为的是给内联(inline)属性的文本赋予标题的样式。

远程连接PostgreSQL:配置指南与安全建议

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🐅🐾猫头虎建议程序员必备技术栈一览表📖:🛠️全栈技术FullStack:📚MERN/MEAN/MEVNStack|🌐Jamstack|🌍GraphQL|🔁RESTfulAPI|⚡WebSockets|🔄CI/CD|🌐Git&Versio

Linux安全加固:保护你的服务器

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

Cobra眼睛蛇-强大的Golang CLI框架,快速上手的脚手架搭建项目工具,详细安装和使用

Cobra眼睛蛇-强大的GolangCLI框架,快速上手的脚手架搭建项目工具,详细安装和使用。阅读过k8s源码的同学,应该都知道k8sScheduler、kubeadm、kubelet等核心组件的命令行交互全都是通过spf13写的Cobra库来实现。本文就来介绍下Cobra的相关概念及具体用法。关于Cobra是一个用于

MySQL常用配置详解

目录一、MySQL查看配置信息二、MySQL查看服务器当前运行状态的信息三、MySQL常用配置详解1、mysql(使用mysql命令登录数据库时的默认的设置)2、client(客户端默认设置内容)3、mysqld(服务端端配置)四、配置修改演示1、修改my.cnf配置文件(window系统修改my.ini配置文件)2、

二叉树经典OJ题——【数据结构】

W...Y的主页😊代码仓库分享💕今天我们来进行二叉树的OJ练习,就是利用二叉树的前序、中序、后续以及晨序遍历的特性进行OJ训练。话不多说,来看我们的第一道题。【leetcode965.单值二叉树】OJ链接如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回true;否则返

热文推荐