当前位置: 首页 > news >正文

Unity中Shader实现模板测试Stencil

文章目录

  • 前言
  • 一、UI中的遮罩
    • 1、Mask ——> 模板测试
    • 2、RectMask2D ——> UNITY_UI_CLIP_RECT
  • 二、模板缓冲区Stencil一般是和Pass平行的部分,Pass部分写的是颜色缓冲区
    • Stencil:
    • Comp(比较操作)
    • Pass(模版缓冲区的更新)
  • 三、实际使用
    • 1、在使用模板缓冲区前,需要如下图设置一个遮罩图层
    • 2、设置完后,在内层的Image使用的材质的Shader中添加如下代码,即可实现只在有遮罩的部分,渲染后渲染的部分
  • 四、让实现的模板测试更加方便自定义
    • 1、在属性面板暴露一个int类型,提供给 Ref 使用
    • 2、在属性面板暴露一个int类型,提供给 Comp 使用,并且设置成Unity内置的几个枚举类型[Enum(UnityEngine.Rendering.CompareFunction)]
    • 3、在属性面板暴露一个int类型,提供给 Pass 使用,并且设置成Unity内置的几个枚举类型[Enum(UnityEngine.Rendering.StencilOp)]
    • 4、最终测试代码


前言

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 OneMinusSrcAlphaStencil{Ref 1//ReadMask [_StencilReadMask]//WriteMask [_StencilWriteMask]Comp EqualPass 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 OneMinusSrcAlphaStencil{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}}
}

效果:
请添加图片描述

相关文章:

Unity中Shader实现模板测试Stencil

文章目录 前言一、UI中的遮罩1、Mask ——> 模板测试2、RectMask2D ——> UNITY_UI_CLIP_RECT 二、模板缓冲区Stencil一般是和Pass平行的部分&#xff0c;Pass部分写的是颜色缓冲区Stencil:Comp&#xff08;比较操作&#xff09;Pass(模版缓冲区的更新) 三、实际使用1、在…...

多线程与并发

多线程与高并发 线程的创建方式1.继承Thread类 重写run方法2.实现Runnable接口 重写run方法3. 实现Callable 重写call方法&#xff0c;配合FutureTask 线程的使用1.线程的状态1.1. 传统操作系统层面5种状态1.2.Java中给线程准备的6种状态 2.线程的常用方法2.1 获取当前线程2.2 …...

手写call方法

Function.prototype.myCallfunction (context,args) {console.log(arguments)//context 表示call里面的第一个参数也就是需要改变this指向的那个对象。//this表示这个方法//把这个方法挂到需要改变指向的对象身上调用&#xff0c;相当于把this指向了这个对象身上&#xff0c;从…...

基于FPGA的图像直方图统计实现,包括tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、图像数据传输 4.2、直方图统计算法 4.3、时序控制和电路设计 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescal…...

数据库:Hive转Presto(一)

本人因为工作原因&#xff0c;经常使用hive以及presto&#xff0c;一般是编写hive完成工作&#xff0c;服务器原因&#xff0c;presto会跑的更快一些&#xff0c;所以工作的时候会使用presto验证结果&#xff0c;所以就要频繁hive转presto&#xff0c;为了方便&#xff0c;我用…...

Responder

环境准备 操作系统:Kali Linux工具:responder,john,evil-winrm PS:输入以下命令解决靶场环境无法打开问题 #echo "<靶机IP> unika.htb">>/etc/hostsresponder工具 [Kali 官网] 手册地址:https://www.kali.org/tools/responder/ 摘要: This package c…...

基于下垂控制的并网逆变器控制MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 主要模块&#xff1a; 建议使用MATLAB2021b及以上版本打开&#xff01; 功率计算模块、下垂控制模块、电压电流双环控制模块、虚拟阻抗压降模块 扰动设置&#xff1a; 在0.5秒到2秒始端设置0.25Hz的电网频…...

android获取RAM、CPU频率、系统版本、CPU核数

参考链接&#xff1a; https://www.jianshu.com/p/76d68d13c475 https://github.com/matthewYang92/Themis 获取CPU频率、核数的逻辑&#xff0c;是通过文件操作实现的&#xff0c;Android是基于Linux系统的&#xff0c;所以该方式针对不同的手机都是可靠的操作方式。 RAM&am…...

微信小程序python+nodejs+php+springboot+vue 讲座预约系统

讲座预约管理系统的用户是系统最根本使用者&#xff0c;按需要分析系统包括用户&#xff1a;学生、管理员。 管理员通过后台的登录页面&#xff0c;选择管理员权限后进行登录&#xff0c;管理员的权限包括学生信息管理和文章公告管理。讲座公告管理&#xff0c;添加讲座公告信息…...

嵌入式开发笔记:STM32的外设GPIO知识学习

GPIO简介&#xff1a; • GPIO &#xff08; General Purpose Input Output &#xff09;通用输入输出口 • 可配置为 8 种输入输出模式 • 引脚电平&#xff1a; 0V~3.3V &#xff0c;部分引脚可容忍 5V &#xff08;如舵机和驱动直流电机&#xff09; • 输出模式下可控制端口…...

单片机论文参考:2、基于单片机的病床呼叫系统设计

任务要求 设计病床呼叫系统&#xff0c;使用3X8矩阵开关分别模拟医院病房与病床位数&#xff0c;当某开关按下时&#xff0c;系统显示呼叫的病房与病床、呼叫的时间。处理完毕可清除该呼叫显示记录。同时有数个病床呼叫时&#xff0c;可以循环呼叫记录显示。 摘要 病房呼叫系统…...

【C语言】结构体实现位段!位段有何作用?

本篇文章目录 1. 声明位段2. 位段的内存分配3. 位段的跨平台问题4.位段的应用5. 如何解决位段的跨平台问题&#xff1f; 1. 声明位段 位段的声明和结构是类似的&#xff0c;有两个不同&#xff1a; 位段的成员必须是 int、unsigned int 或 char。位段的成员名后边有一个冒号和…...

msvcp140为什么会丢失?msvcp140.dll丢失的解决方法

msvcp140.dll 是一个动态链接库文件&#xff0c;它包含了 C 运行时库的一些函数和类&#xff0c;例如全局对象、异常处理、内存管理、文件操作等。它是 Visual Studio 2015 及以上版本中的一部分&#xff0c;用于支持 C 应用程序的运行。如果 msvcp140.dll 丢失或损坏&#xff…...

Ingress Controller

什么是 Ingress Controller &#xff1f; 在云原生生态中&#xff0c;通常来讲&#xff0c;入口控制器( Ingress Controller )是 Kubernetes 中的一个关键组件&#xff0c;用于管理入口资源对象。 Ingress 资源对象用于定义来自外网的 HTTP 和 HTTPS 规则&#xff0c;以控制进…...

离线安装 K3S

一、前言 简要记录一下离线环境下 K3S 的搭建&#xff0c;版本为 v1.23.17k3s1&#xff0c;使用外部数据库 MySQL 作元数据存储&#xff0c;禁用默认组件&#xff08;coredns、servicelb、traefik、local-storage、metrics-server&#xff09;并使用 Helm 单独安装&#xff08…...

Error系列-常见异常问题解决方案以及系统指令总结

前情提要 作为一名开发&#xff0c;日常工作中会遇到很多报错的情况&#xff0c;希望我的总结可以帮助到小伙伴们~日常工作中也会遇到需要部署项目或者登陆linux系统操作的情况&#xff0c;很多时候需要查找一些命令&#xff0c;于是我决定&#xff0c;要把我日常经常用到的一…...

c 各种例子

1. struct{ int code; float cost; }item,*ptrst; ptrst&item; prtst->code3451 // ptrst->codeitem.code(*ptrst).code 结构与union 的运算符相同&#xff0c;不同的是union 在同一时间内只能存储成员中的一种&#xff0c;其他的成员不真实。 2. c的修饰符声…...

Flowable主要子流程介绍

1. 内嵌子流程 &#xff08;1&#xff09;说明 内嵌子流程又叫嵌入式子流程&#xff0c;它是一个可以包含其它活动、分支、事件&#xff0c;等的活动。我们通常意义上说的子流程通常就是指的内嵌子流程&#xff0c;它表现为将一个流程&#xff08;子流程&#xff09;定…...

通过插件去除Kotlin混淆去除 @Metadata标记

在Kotlin中&#xff0c;Metadata是指描述Kotlin类的元数据。它包含了关于类的属性、函数、注解和其他信息的描述。Metadata的作用主要有以下几个方面&#xff1a; 反射&#xff1a;Metadata可以用于在运行时获取类的信息&#xff0c;包括类的名称、属性、函数等。通过反射&…...

【docker】容器跟宿主机、其他容器通信

说明 容器跟宿主机、其他容器通信的关键在于它们要在同一个网络&#xff0c;或者通过修改路由信息来可以让它们互相之间能够找得到对方的 IP。本文主要介绍让它们在同一个网络的方法。 Docker 自定义网络模式介绍 Docker容器可以通过自定义网络来与宿主机或其他容器进行通信…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...