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

Unity3D Shader系列之模板测试

一、 模板测试原理

模板测试位于GPU渲染流水线的逐片元操作阶段,片元着色器完成之后就会进入模板测试,模板测试通过后再进入深度测试。我们的GPU中有一个模板缓冲区(Stencil Buffer)(Stencil即是模板的意思),其大小为整个屏幕大小*8位,即屏幕上的每一个像素点都存储有一个模板值,该模板值是8位的,所以其值范围为0~255。举个例子,如果我们屏幕的大小是1920×1080的,那么模板缓冲区的大小就为1920×1080×8位。

模板测试的原理很简单:如果我们在Shader中开启了模板测试,要渲染某个像素的时候,就会读取读取Shader中设置的参考值Ref(我们按需求设置),同时模板缓冲区中该像素对应的模板值StencilValueInBuffer,如果参考值Ref与模板缓冲区中的值StencilValueInBuffer满足某个条件(此条件是我们在Shader中按我们的需求指定的),则测试通过,该像素可以渲染;如果不满足,则该像素不可以渲染。无论深度测试是否通过,Shader中都有权利向模板缓冲区写入模板值(前提是开启了模板测试)。

二、 模板测试示例

如果Shader中模板测试关闭,即不进行模板测试,那么该Shader是没有权利写入模板缓冲区的。

下面来看看一个具体的例子,方便我们来理解模板测试的作用。

场景中,我们想要渲染两个物体Plane和Cube,我想要实现的效果是只有通过Plane才能够看到Cube,但是Plane本身是不可见的,相当于把Plane当作透视镜样。

场景如下图。

我们想要的结果如下。

想要的结果再具体点就是我们只想展示Cube被Plane挡住的部分,如下面的蓝色框部分,Plane也不显示。

要实现这一效果,就需要用到模板测试了。

①首先,我们需要先渲染Plane,再渲染Cube。注意这一点很重要,如果先渲染的是Cube,再渲染的Plane使用模板测试是不能实现这种效果的。如何保证一定是先渲染Plane再渲染Cube呢,很简单,将Plane的渲染队列(Render Queue)设置得比Cube的渲染队列小即可。关于渲染队列的知识点,我们在《Unity3D Shader系列之透视效果XRay》中专门有一节说明,这里不再赘述。

②然后,Plane的Shader关闭深度写入(ZWrite off)同时不输出颜色(ColorMask 0),开启模板测试,并一直测试通过,同时向模板缓冲区中写入值1。

解释一下上面这句话中各个指令的作用:

– 关闭深度写入(ZWrite off)

来保证后渲染的Cube总能通过深度测试。如果Plane开启了深度写入,那么后渲染的Cube中被Plane挡住的部分将永远不能通过深度测试,那部分也就永远不会绘制在屏幕上了,而我们想要的是刚好只显示这部分。

– 不输出颜色(ColorMask 0)

就是渲染Plane时,Plane的任何颜色都不写入颜色缓冲区,就相当于Plane看不见样(虽然Plane的确渲染了,只是看不到)

– 开启模板测试,并一直测试通过,同时向模板缓冲区中写入值1

GPU绘制完Plane后,模板缓冲区的值如下图。即Plane的部分值为1,模板缓冲区的其他部分仍为0。

③最后,我们渲染Cube,Cube中开启深度测试,模板测试参考值设置为1,只有当模板缓冲区中的值为1时,才能通过模板测试,从而实现我们想要的效果。

我们正常渲染Cube的范围是下面的白色框,但是由于只有蓝色框部分模板缓冲区中的值才是1,所以只有蓝色框部分能通过模板测试,左边的红色部分由于模板缓冲区中的值为0,所以不能通过模板测试,也就不能够渲染出来。

2.3 Unity3D中使用模板测试

Unity的Shader中使用模板测试很简单,在Shader中添加上Stencil代码块即可。如果没有Stencil代码块,就认为是关闭模板测试的。

Stencil
{}

从2.1节讲到的模板测试原理我们可以知道,模板测试并不是完全可编程的,我们只能去简单配置几个指令。模板测试的配置项包括如下几个

– 参考值 Ref

– 比较函数 Comp

– 若模板测试通过写入方式 Pass

– 若模板测试不通过写入方式 Fail

– 若模板测试通过但深度测试不通过模板缓冲区写入方式 ZFail

– 读掩码ReadMask和写掩码WriteMask

可参考官方文档。

2.3.1 参考值

语法如下,Ref后面即参考值,值范围为0~255。

Stencil
{Ref 0}

当然很多时候我们想通过编辑器面板更改参考值,不想在Shader中直接写死,我们可以如下操作。

– 在Shader的Properties定义一个Int值_Ref

[_IntRange]用于限定编辑器面板中只能调节为整数值(ps:[_IntRange]是MaterialPropertyDrawer中的一种,可参考官方文档)

Properties
{[IntRange]_Ref("Ref",Range(0,255))=0}
  • 然后将Ref 0改为Ref [_Ref]即可

Stencil
{Ref [_Ref]}

2.3.2 比较函数

语法如下,Comp后面跟的就是比较函数,默认值为Always,即模板测试一直通过。

Stencil
{Comp Always
}

可设置为以下函数。

2.3.3 模板操作

模板操作包括Pass、Fail、 ZFail。

Pass用来指定模板测试通过时写入什么值到模板缓冲区中;

Fail用来指定模板测试不通过时写入什么值到模板缓冲区中;

Pass用来指定板测试通过但深度测试不通过时写入什么值到模板缓冲区中。

Stencil
{PassReplaceFailKeepZFail Keep
}

可设置的值如下。三者默认值均为Keep。

2.3.4 读写掩码

读写掩码默认值均为255。

在进行比较时,是使用参考值&(按位与)读掩码来作为实际比较的参考值。

在进行模板操作时,是使用想写入的值&(按位与)写掩码来作为实际写入的值。

由于默认值都是255,任何8bit的值与255按位与&都等于原值,所以我们没明确指定读写掩码时,在进行比较时,使用的就是我们的参考值;在进行写入时,使用的就是我们的原始写入值。

Stencil
{ReadMask 255WriteMask 255}

3 示例代码

Plane用到的Shader。

Shader "LaoWang/Unlit/Plane"{Properties{[IntRange]_Ref("Ref",Range(0,255))=0}SubShader{Tags {"RenderType"="Opaque"}LOD 100Pass{Stencil{Ref [_Ref]Comp AlwaysPass Replace}ZWrite OffColorMask 0CGPROGRAM#pragma vertex vert#pragma fragment frag#include"UnityCG.cginc"structappdata{float4 vertex : POSITION;};structv2f{float4 vertex : SV_POSITION;};fixed4 _Color;v2f vert (appdata v){v2f o;o.vertex =UnityObjectToClipPos(v.vertex);return o;}fixed4 frag (v2f i): SV_Target{returnfixed4(0,0,0,0);}ENDCG}}}

Cube用到的Shader。

Shader "LaoWang/Unlit/Cube"{Properties{_Color("Color", color)=(1.0,1.0,1.0,1.0)[IntRange]_Ref("Ref",Range(0,255))=0}SubShader{Tags {"RenderType"="Opaque"}LOD 100Pass{Stencil{Ref [_Ref]Comp EqualPass IncrSat}CGPROGRAM#pragma vertex vert#pragma fragment frag#include"UnityCG.cginc"structappdata{float4 vertex : POSITION;};structv2f{float4 vertex : SV_POSITION;};fixed4 _Color;v2f vert (appdata v){v2f o;o.vertex =UnityObjectToClipPos(v.vertex);return o;}fixed4 frag (v2f i): SV_Target{return _Color;}ENDCG}}}

工程下载

相关文章:

Unity3D Shader系列之模板测试

一、 模板测试原理模板测试位于GPU渲染流水线的逐片元操作阶段,片元着色器完成之后就会进入模板测试,模板测试通过后再进入深度测试。我们的GPU中有一个模板缓冲区(Stencil Buffer)(Stencil即是模板的意思),其大小为整个屏幕大小*8位&#xf…...

机器学习中的数学——精确率与召回率

在Yolov5训练完之后会有很多图片,它们的具体含义是什么呢? 通过这篇博客,你将清晰的明白什么是精确率、召回率。这个专栏名为白话机器学习中数学学习笔记,主要是用来分享一下我在 机器学习中的学习笔记及一些感悟,也希…...

Oracle启动数据库报ORA-01102解决办法

1.机器启动之后登录服务器使用sqlplus / as sysdba 登录数据库发现数据库并没有启动之前把数据库服务添加过开机自启动 2.使用startup命令启动数据库报错了 SYSorcl>startup; ORACLE 例程已经启动。 Total System Global Area 2471931904 bytes Fixed Size 2255752 byt…...

Go 语言面向对象编程及实践

面向对象编程是计算机科学中的一种重要的编程方法,它将数据和处理它的代码组合成对象,并将这些对象组合成更大的程序。在 Go 语言中,我们同样可以使用面向对象编程的方式进行开发。本篇文章将介绍 Go 语言面向对象编程的概念、特性、使用方法以及实践技巧。 面向对象编程概…...

0102 MySQL05

1.约束 1.约束(constraint):在创建表时,可以给表中的字段加上一些约束,保证表中数据的完整性,有效性 常见的约束? 非空约束:not null 唯一性约束:unique 主键约束&am…...

[深入理解SSD系列 闪存2.1.3] 固态硬盘闪存的物理学原理_NAND Flash 的读、写、擦工作原理

2.1.3.1 Flash 的物理学原理与发明历程 经典物理学认为 物体越过势垒,有一阈值能量;粒子能量小于此能量则不能越过,大于此能 量则可以越过。例如骑自行车过小坡,先用力骑,如果坡很低,不蹬自行车也能 靠惯性过去。如果坡很高,不蹬自行车,车到一半就停住,然后退回去。 …...

洗地机哪家强?洗地机排行榜

随着清洁行业电器的开展,越来越多的新颖工具和电器开端进入消费者的生活之中。众所周知,面对美不胜收的清洁电器产品,选购也是一大头疼事,应该怎样选购洗地机等清洁电器呢,实在的用户体验和清洁效率莫过于消费者最看重…...

【Java基础 下】 029 -- 多线程

目录 一、为什么要有多线程? 1、线程与进程 2、多线程的应用场景 3、小结 二、多线程中的两个概念(并发和并行) 1、并发 2、并行 3、小结 三、多线程的三种实现方式 1、继承Thread类的方式进行实现 2、实现Runnable接口的方式进行实现 3、利用…...

R语言生物群落(生态)数据统计分析与绘图

查看原文>>>R语言生物群落(生态)数据统计分析与绘图 R 语言作的开源、自由、免费等特点使其广泛应用于生物群落数据统计分析。生物群落数据多样而复杂,涉及众多统计分析方法。本课程以生物群落数据分析中的最常用的统计方法回归和混…...

浙江首场千人大会现场爆满!实在智能九哥专题演讲:企业数字化转型,从实在RPA开始!

为帮助众多电商商家探索数字时代下新赛道、新趋势、新方向,制定有目标、有节奏的全年生意规划,“未来电商高峰论坛暨电商生态赋能大会”于3月4日在杭州正式拉开序幕。本次大会旨在向品牌电商企业主、运营操盘手分享数字电商时代的黄金趋势及运营策略&…...

Windows 上 执行docker pull命令 提示:The system cannot find the file specified.

错误提示error during connect: This error may indicate that the docker daemon is not running.: Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/version": open //./pipe/docker_engine: The system cannot find the file specified.解决办法在cmd 窗口中执…...

查看 WiFi 密码的两种方法

查看 WiFi 密码的两种方法1. 概述2. 在控制面板中查看 WiFi 密码3. 使用 CMD 查看 WiFi 密码结束语1. 概述 突然忘记 WiFi 密码怎么办? 想连上某个使用过的 WiFi,但有不知道 WiFi 密码怎么办? 使用电脑如何查询 WiFi 密码? 以下是…...

逻辑优化基础-bi-decomposition

简介 bi-decomposition是逻辑综合中用于简化布尔函数的一种技术。其思想是将函数分成两个较小的函数,每个函数仅取决于所选变量的一个值。这些较小的函数可以使用简单的逻辑门(如AND、OR和NOT门)来实现,然后组合以获得原始函数的…...

Modbus转profinet网关连接1200PLC在博图组态与驱动器通讯程序案例

本案例给大家介绍由兴达易控modbus转profinet网关连接1200PLC在博图软件无需编程,实现1200Profinet转modbus与驱动器通讯的程序案例 硬件连接:1200PLC一台;英威腾DA180系列驱动器一台;兴达易控modbus转profinet网关一台 下面就是…...

Android ART虚拟机 启动和初始化

前言 之前整理了一系列Dalvik虚拟机的关于堆内存和GC的文章,轮到对ART内存进行分析优化了,继续整理输出一波,本篇为ART虚拟机系列的第一篇,介绍ART虚拟机的启动和初始化。 #mermaid-svg-8iNdLFTpOHLgRjHA {font-family:"tre…...

宇视科技一二三面

一面 1、自我介绍 2、堆和栈的区别,堆在数据结构中是如何表示的 3、有用过Linux吗?虚拟空间中用户态是3G,假如计算机的内存是4G,为什么计算机可以运行这些进程 4、虚拟地址到物理地址的映射过程 5、进程间的通信方式 6、共享内存…...

优思学院|盘点,精益生产25个工具!【必需收藏】

精益生产方法需要一种全面的方法才能有效实施。精益这个概念是每个接触产品供应链的人都要实践的,无论是在计划方面还是在分析方面。 精益生产工具有助于持续改进生产效率和产品或服务质量。精益工具是要减少 Muda (浪费),从生产过…...

Linux中将多块新硬盘合并成一个,挂载到/mysqldata目录下

需求: 将两块空硬盘合并为“一块”,挂载到指定目录(/data)下,达到在一个目录使用2块硬盘所有空间的效果。 使用 fdisk -l 命令查看当前系统中的硬盘,如下图: 系统中存在两块未分配的硬盘&#…...

Git的SSH密钥配置

Git的SSH密钥配置简记Githttps和ssh的区别基本需求SSH密钥类型ED25519 SSH 密钥RSA SSH 密钥查看您是否有现有的 SSH 密钥对设置流程设置user name和emailssh密钥配置检查是否存在ssh Key创建新的ssh key将ssh密钥添加到您的Git帐户验证您是否可以连接使用Git有一段时间了&…...

C++回顾(九)——多继承

9.1 多继承 9.1.1 概念 一个类有多个直接基类的继承关系称为多继承(多个父类)多继承声明语法 class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n {数据成员和成员函数声明 };类 C 可以根据访问控制同时…...

STM32F4 SPI DMA实战:用CubeMX和HAL库5分钟搞定高速数据传输(附避坑指南)

STM32F4 SPI DMA实战:CubeMXHAL库5分钟极速配置指南 在嵌入式开发中,SPIDMA的组合堪称数据传输的"黄金搭档"——既能享受SPI接口的高速特性,又能通过DMA解放CPU资源。但传统基于寄存器的手动配置方式,往往让开发者陷入繁…...

高速PCB设计实战:五种端接方案如何选型与优化

1. 高速PCB设计中的信号完整性问题 在高速PCB设计中,信号完整性(SI)问题就像城市交通拥堵一样常见。想象一下,当信号以GHz级别的频率在电路板上传输时,就像高峰期的高速公路上飞驰的跑车,任何一个小小的阻抗…...

终极Blender 3MF插件:如何快速实现3D打印文件的无缝转换

终极Blender 3MF插件:如何快速实现3D打印文件的无缝转换 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat Blender3mfFormat是一款专为Blender设计的开源插件&a…...

Windows Cleaner:彻底告别C盘爆红的免费开源解决方案

Windows Cleaner:彻底告别C盘爆红的免费开源解决方案 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 面对Windows系统使用过程中C盘空间不断告急的困扰…...

【网络安全】什么是漏洞扫描?有哪些功能?

【网络安全】什么是漏洞扫描?有哪些功能? 一、什么是漏洞扫描? 漏洞扫描是指基于CVE、CNVD、CNNVD 等漏洞数据库,通过专用工具扫描手段对指定的远程或者本地的网络设备、主机、数据库、操作系统、中间件、业务系统等进行脆弱性评估…...

为什么92%的数据分析师还没用上Gemini Sheets功能?—— 一份被谷歌官方忽略的AI分析落地清单

更多请点击: https://intelliparadigm.com 第一章:Gemini Sheets数据分析的现状与认知断层 Gemini Sheets 作为 Google Workspace 生态中新兴的 AI 增强型电子表格工具,正逐步替代传统 Sheets 的部分分析场景。然而,当前用户实践…...

Go 里什么时候可以“panic”?

“Don’t panic.” —— Go 谚语 但……如果我真的想 panic 呢?在 Go 的世界里,panic() 就像厨房里的灭火器:平时你不会用它炒菜,但如果油锅着火了,你肯定得拉它一把。今天我们就来聊聊:Go 里什么时候 pani…...

基于MCP协议实现AI助手个性化:Terminal Buddies项目实战解析

1. 项目概述:当你的终端伙伴遇见AI助手 如果你和我一样,每天有大量时间泡在终端和代码编辑器里,那么一个能带来些许乐趣和陪伴感的“数字伙伴”或许能点亮枯燥的编码时光。Terminal Buddies 正是这样一个巧妙结合了复古 ASCII 艺术、轻量级游…...

[具身智能-680]:ROS2 可视化与调试工具与示例

按日常开发必用分类,每条可直接复制运行,新手也能马上上手。一、3D 可视化工具1. rviz2(核心 3D 可视化)功能查看:机器人模型、激光雷达、点云、地图、TF 坐标、导航路径、相机图像、机械臂、代价地图等。启动bash运行…...

别只盯着SQL了!GaussDB健康度巡检,这5个‘外围’命令和日志文件更重要

别只盯着SQL了!GaussDB健康度巡检,这5个‘外围’命令和日志文件更重要 当数据库出现性能波动时,大多数DBA的第一反应是检查慢SQL或调整参数。但根据某金融客户的生产环境统计,超过60%的数据库故障其实源于日志溢出、网络闪断或备份…...