【渲染流水线】[逐片元阶段]-[模版测试]以UnityURP为例
- 用于精确控制像素丢弃的逐片元操作,通过模板缓冲区(8位整数/像素)实现复杂遮罩效果。
- 支持8种比较函数和6种缓冲操作
- 当前模版操作,只能在Shader文件中书写操作,ShaderGraph中无法直接使用模版指令。
【从UnityURP开始探索游戏渲染】专栏-直达
核心配置预览
- 核心配置所有配置列出(非全必要):
Stencil {
Ref 2 // 必要模版数值
ReadMask 255
WriteMask 255
Comp Greater // 必要比较操作符
Pass Replace // 必要通过后的操作
Fail Keep
ZFail DecrSat
}
1. 核心配置命令
Ref:设置参考值(0-255整数),用于与模板缓冲区比较ReadMask:读取掩码(0-255),按位与操作后比较(默认255)WriteMask:写入掩码(0-255),控制可修改的缓冲区位(默认255)
2. 比较函数命令
Comp支持以下枚举值:
Always/Never:始终通过/拒绝Less/Greater:小于/大于时通过Equal/NotEqual:等于/不等于时通过LessEqual/GreaterEqual:小于等于/大于等于时通过
3. 操作命令
Pass/Fail/ZFail支持的操作:
Keep:保持原值Zero:置零Replace:用Ref值替换IncrSat/DecrSat:饱和增减(0/255边界)IncrWrap/DecrWrap:循环增减Invert:按位取反
模板测试具体过程
缓冲区初始化
- 清除模板缓冲:
GL.Clear(ClearBufferMask.StencilBufferBit) - 设置初始值:
GL.StencilMask(0xFF)(默认全255)
- 清除模板缓冲:
测试阶段-逐片元
plaintext
if (片元模板值 [比较函数] 参考值) {
执行通过操作(如保留像素)
} else {
执行失败操作(如丢弃像素)
}
缓冲更新
- 根据测试结果修改模板缓冲值(可选)
比较函数(StencilFunc)
| 函数 | 含义 | OpenGL常量 |
|---|---|---|
Never |
永远不通过 | GL_NEVER |
Always |
永远通过 | GL_ALWAYS |
Less |
模板值 < 参考值 | GL_LESS |
LEqual |
模板值 ≤ 参考值 | GL_LEQUAL |
Greater |
模板值 > 参考值 | GL_GREATER |
GEqual |
模板值 ≥ 参考值 | GL_GEQUAL |
Equal |
模板值 == 参考值 | GL_EQUAL |
NotEqual |
模板值 != 参考值 | GL_NOTEQUAL |
缓冲操作(StencilOp)
| 操作组合 | 含义 |
|---|---|
Keep |
保持当前模板值不变(默认) |
Zero |
将模板值设为0 |
Replace |
用参考值替换模板值 |
Incr/IncrWrap |
模板值+1(超过255时,前者截断后者循环) |
Decr/DecrWrap |
模板值-1(低于0时,前者截断后者循环) |
Invert |
按位取反(~操作) |
示例1
- 遮罩区域shader
Shader "Custom/StencilMask" {
SubShader {
Tags { "Queue"="Geometry-1" } // 优先渲染
ColorMask 0 // 不写入颜色
ZWrite Off
Stencil {
Ref 1
Comp Always
Pass Replace // 将模板值设为1
}
Pass {} // 空Pass仅用于写入模板
}
}
- 物体模版测试shader,该Shader仅在模板值为1的区域内渲染物体。
Shader "Custom/StencilObject" {
SubShader {
Stencil {
Ref 1
Comp Equal // 仅渲染模板值=1的区域
Pass Keep
}
Pass {
// 正常着色代码...
}
}
}
示例2 外轮廓描边
Shader "Custom/StencilOutline" {
Properties {
_MainTex ("Base Texture", 2D) = "white" {}
_OutlineColor ("Outline Color", Color) = (1,0,0,1)
_OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.05
}
SubShader {
Tags {
"RenderPipeline"="UniversalRenderPipeline"
"RenderType"="Opaque"
}
// Pass 1: 正常渲染角色并写入模板
Pass {
Name "Character"
Tags
{
"LightMode" = "UniversalForward"
}
Stencil {
Ref 1
Comp Always
Pass Replace
ZFail Keep
}
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes {
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings {
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
Varyings vert(Attributes IN) {
Varyings OUT;
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.uv = IN.uv;
return OUT;
}
half4 frag(Varyings IN) : SV_Target {
return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv);
}
ENDHLSL
}
// Pass 2: 渲染轮廓
Pass {
Name "Outline"
Cull Front
Stencil {
Ref 1
Comp NotEqual
Pass Keep
}
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes {
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
};
struct Varyings {
float4 positionCS : SV_POSITION;
};
CBUFFER_START(UnityPerMaterial)
float4 _OutlineColor;
float _OutlineWidth;
CBUFFER_END
Varyings vert(Attributes IN) {
Varyings OUT;
float3 posWS = TransformObjectToWorld(IN.positionOS.xyz * (1 + _OutlineWidth));
float3 normalWS = TransformObjectToWorldNormal(IN.normalOS);
// posWS += normalWS * _OutlineWidth; // 沿法线方向扩展
OUT.positionCS = TransformWorldToHClip(posWS);
return OUT;
}
half4 frag(Varyings IN) : SV_Target {
return _OutlineColor;
}
ENDHLSL
}
}
}
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,)
【渲染流水线】[逐片元阶段]-[模版测试]以UnityURP为例的更多相关文章
- Shader 入门笔记(二) CPU和GPU之间的通信,渲染流水线
渲染流水线 1)应用阶段(CPU处理) 首先,准备好场景数据(摄像机位置,视锥体,模型和光源等) 接着,做粗粒度剔除工作. 最后,设置好每个模型的渲染状态(使用的材质,纹理,shader等) 这一阶段 ...
- Unity Shader 之 渲染流水线
Unity Shader 之渲染流水线 什么是渲染流水线 一个渲染流程分成3个步骤: 应用阶段(Application stage) 几何阶段(Geometry stage) 光栅化阶段(Raster ...
- GPU渲染流水线的简单概括
GPU流水线 主要分为两个阶段:几何阶段和光栅化阶段 几何阶段 顶点着色器 --> 曲面细分着色器(可选)----->几何着色器(可选)----->裁剪-->屏幕 ...
- 《UnityShader入门精要》学习笔记之渲染流水线
第一种分类方式: 图形管道(如下7步): 顶点数据 : 由3D模型传递的三角形网格 顶点着色 : 编写CG程序对各个顶点进行着色 生成几何图元 : 连接特定的顶点生成几何图元,例如连接三个顶点生成一个 ...
- Unity Shader入门精要学习笔记 - 第2章 渲染流水线
来源作者:candycat http://blog.csdn.net/candycat1992/article/ 2.1 综述 渲染流水线的最终目的在于生成或者说是渲染一张二维纹理,即我们在电脑屏 ...
- Unity 渲染流水线 :CPU与GPU合作创造的艺术wfd
前言 对于Unity渲染流程的理解可以帮助我们更好对Unity场景进行性能消耗的分析,进而更好的提升场景渲染的效率,最后提升游戏整体的性能表现 Unity的游戏画面的最终的呈现是由CPU与GPU相互配 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线 学习目标 了解几个用以表达真实场景的标志和2D图像 ...
- Unity3D Shader Stencil模版测试学习
官方文档地址: https://docs.unity3d.com/Manual/SL-Stencil.html 参考博客: http://blog.csdn.net/onafioo/article/d ...
- [Unity Shader] 逐顶点光照和逐片元漫反射光照
书中的6.4节讲的是漫反射的逐顶点光照和逐片元光照. 前一种算法是根据漫反射公式计算顶点颜色(顶点着色器),对颜色插值(光栅化过程)返回每个像素的颜色值(片元着色器). 第二种算法是获得顶点的法线(顶 ...
- 移动端 像素渲染流水线与GPU Hack
什么是 像素渲染流水线 web页面你所写的页面代码是如何被转换成屏幕上显示的像素的.这个转换过程可以归纳为这样的一个流水线,包含五个关键步骤: 1.JavaScript:一般来说,我们会使用JavaS ...
随机推荐
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Account Kit(5)
1.问题描述: 集成华为一键登录的LoginWithHuaweiIDButton, 但是Button默认名字叫 "华为账号一键登录",太长无法显示,能否简写成"一键登录& ...
- Vue 学习笔记 [Part 1]
作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 最近项目上需要用到Vue,又重新学习了一遍.期望10天左右完全掌握并能用于生产吧. 好记性不如烂笔头 目录 一. 邂逅Vuejs 1.1. 认识Vu ...
- Mysql 一些函数的使用
Mysql 一些函数的使用 if函数 SELECT IF(500<1000, "YES", "NO"); SELECT IF(500<1000,1, ...
- 开源DeepWiki 企业老项目救星:自动生成文档+AI问答,告别遗留代码维护噩梦
企业痛点一击即中 你是否还在为这些问题头疼: 核心业务系统缺乏文档,新人上手困难 老员工离职带走关键代码知识 系统升级维护成本居高不下 业务逻辑复杂,代码理解困难 OpenDeepWiki最新版本专为 ...
- 层次分析法的Python实现--数学建模学习日志
数学建模比赛即将到来,大家应该都投身于学习当中了,b站上比较热门的一个课程是 b站数学建模学习视频 在这里讲解了数学建模常见的方法和写论文的要点,同时up主贴心地有所有方法的源码实现,但是全部都是ma ...
- C# 遍历Enum( 枚举)
Type enumType = typeof(Domain.Models.Entitys.PermissionEntity.PermissionTypeEnum); ...
- 一款开源免费、通用的 WPF 主题控件包
前言 今天大姚给大家分享一款开源免费(MIT License).通用的 WPF 主题控件包:Rubyer WPF. WPF介绍 WPF是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的 Wind ...
- Spring AI 对话记忆大揭秘:服务器重启,聊天记录不再丢失!
还在为 Spring AI 应用重启后对话上下文丢失而烦恼吗?本文将带你深入 Spring AI 的对话记忆机制,并手把手教你实现一个基于文件的持久化方案,让你的 AI 应用拥有 "过目不忘 ...
- qt 显示中文
参考链接 CSDN Tips 直接使用第三种方法 也可以使用 QString::fromLocal8Bit("打开文档文件") 这种方式
- iga 入门之 总体合成
简介 摘自 流体力学数值方法 概括地说,总体合成就是将所有单元的\(A_{ij}^{(e)}.f_i^{(e)}\)进行累加,最终形成\(A_{nm}.f_n\),从而产生总体有限元方程 \[A_{n ...