透明度测试与透明度混合(Blend)互斥,需根据需求选择其一!
【从UnityURP开始探索游戏渲染】专栏-直达
透明度测试(Alpha Test)是一种通过阈值筛选片元的硬性透明方案,其核心逻辑是通过clip()
函数比较片元Alpha值与预设阈值_Cutoff
:当Alpha低于阈值时直接丢弃片元,反之则完整渲染。
- 二元判定:呈现"全有或全无"的视觉效果,适用于栅栏、树叶等需要锐利边缘的物体
- 性能优势:无需混合计算,在移动端和低配设备上表现优异
核心应用场景
- 游戏美术优化
- 植被系统:实现树叶镂空效果(性能较Alpha Blend提升40%)
- 建筑遮罩:快速创建栅栏、铁丝网等规则镂空结构
- 特效制作
- 粒子消融:配合噪声图实现燃烧/腐蚀动画
- UI遮罩:用于异形界面元素裁剪
- 技术美术方案
- 低成本半透模拟:通过抖动阈值(dithering)实现伪半透效果
- 遮挡剔除辅助:标记透明区域实现自定义遮挡逻辑
历史简述
Built-in管线阶段(2018年前)
- 早期Unity内置管线通过
Queue="AlphaTest"
标签实现基础功能,但存在:- 着色器代码冗余,需手动处理光照模型兼容性
- 与延迟渲染路径存在兼容性问题
URP标准化阶段(2019-2022)
- URP 7.x版本引入关键改进:
- Shader Graph集成 :可视化配置
Alpha Clip Threshold
属性 - 渲染队列优化:自动处理AlphaTest物体在3000-3500队列的排序逻辑
- 跨平台一致性:在OpenGL ES 3.0与Metal API中实现相同裁剪行为
- Shader Graph集成 :可视化配置
现代URP增强(2023-2025)
- 最新URP 14+版本新增特性:
- 多重裁剪通道:支持基于R/G/B通道的复合测试条件
- GPU实例化支持:透明测试物体可参与实例化渲染批次
- VFX Graph兼容:粒子系统可直接引用透明度测试材质
如果启用了AlphaTest 那么Early-Z则被弃用
- 因为AlphaTest的clip()操作是在片元中,而Early-Z是在光栅化和片元之前做的测试,如果在片元着色中主动抛弃了片元,那么被遮挡的片元就可见了,但是Early-Z中已经因为提前计算不可见给重新可见的片元丢弃了,这样就无法正常进行计算。那么GPU在优化算法时,如果检查到片元着色器中存在抛弃片元和改写片元深度的操作时,放弃Early-Z的操作。
- Early-Z由GPU自动实现,涉及两个pass,第一个Z-pre-pass,对于所有写入深度数据的物体先用一个超级简单的pass写入深度缓存。第二个pass关闭深度写入,开启深度测试,正常渲染流程渲染。
使用注意
- AlphaTest 物体建议标记为
"Queue"="AlphaTest"
(值2450),确保在透明物体前渲染 - 使用
Always
/Never
可完全绕过测试,减少GPU分支判断 - 复杂比较函数(如
NotEqual
)可能增加片元着色器指令数 - 根据alpha值阈值决定片元保留/丢弃
- 常用于植被、镂空材质等效果实现
Unity 中的透明度测试(AlphaTest)具体过程
SubShader 与 Pass 设置
- 配置渲染通道(Pass)启用 AlphaTest,指定比较函数(如 Greater 或 Less)
比较函数列表
函数指令 | 逻辑条件 | 典型应用场景 |
---|---|---|
Greater |
alpha > 阈值 (_Cutoff ) |
硬边遮罩(如树叶镂空) |
GEqual |
alpha ≥ 阈值 | 半透明边缘抗锯齿优化 |
Less |
alpha < 阈值 | 反向遮罩(如洞孔效果) |
LEqual |
alpha ≤ 阈值 | 透明渐变剔除 |
Equal |
alpha == 阈值 | 精确匹配特定透明度 |
NotEqual |
alpha != 阈值 | 排除特定透明值 |
Always |
始终通过测试 | 强制禁用透明度测试 |
Never |
始终丢弃片元 | 完全隐藏物体 |
配置示例
- 在 SubShader 的 Pass 中声明比较函数与阈值:
c
SubShader {
Pass {
// 启用AlphaTest并设置比较模式
AlphaTest Greater 0.5 // 仅保留alpha>0.5的片元
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
uniform float _Cutoff; // 阈值变量
fixed4 frag (v2f i) : SV_Target {
fixed4 col = tex2D(_MainTex, i.uv);
clip(col.a - _Cutoff); // 等效于AlphaTest Greater
return col;
}
ENDCG
}
}
注:clip() 函数在片元着色器中可直接实现阈值比较,与 AlphaTest 指令效果等价
自定义shader中片元着色器中剔除或混合
Shader 属性定义
- 在 Shader 代码中声明阈值属性(如
_Cutoff
),用于控制 alpha 的临界值
片元着色器处理
- 在片元着色器中,计算片元 alpha 值并与
_Cutoff
比较;若未达标,则使用clip()
或discard
指令丢弃片元,阻止其进入后续测试
渲染输出
- 通过测试的片元参与颜色混合等后续流程,否则被剔除
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)