《Unity Shader入门精要》读书笔记07
第 8 章 透明效果
- 透明通道(Alpha Channel)
- 实现透明效果的两种方法:透明度测试(Alpha Test);透明度混合(Alpha Blending)。
- 透明度测试:简单,根据透明度舍弃片元,但是效果极端。
- 透明度混合:真正的半透明效果。
渲染顺序很重要
前面说到,对于透明度混合技术,需要关闭深度写入,此时我们就需要小心处理透明物体的渲染顺序。那么,我们为什么要关闭深度写入呢?如果不关闭深度写入,一个半透明表面背后的表面本来是可以透过它被我们看到的,但由于深度测试时判断结果是该半透明表面距离摄像机更近,导致后面的表面将会被剔除,我们也就无法透过半透明表面看到后面的物体了。但是,我们由此就破坏了深度缓冲的工作机制,而这是一个非常非常非常(重要的事情要讲3遍)糟糕的事情,尽管我们不得不这样做。关闭深度写入导致渲染顺序将变得非常重要。
半透明和不透明物体之间,半透明物体之间的渲染顺序都很重要。
为什么半透明物体之间也要考虑顺序?
假设有一个红色玻璃(透明度0.5)在一个蓝色玻璃(透明度0.5)后面。让我们看看两种渲染顺序的区别:
| 渲染顺序 | 步骤1:先画蓝色 | 步骤2:再画红色 | 最终结果(数学计算) |
|---|---|---|---|
| 先蓝后红 | 缓冲区初始为黑色(0,0,0) 绘制蓝色:(0,0,0.5) 计算: (0,0,1)*0.5 + (0,0,0)*0.5 = (0,0,0.5) | 在蓝色(0,0,0.5)上画红色(0.5,0,0) 计算: (1,0,0)*0.5 + (0,0,0.5)*0.5 = (0.5,0,0.25) | (0.5, 0, 0.25) |
| 先红后蓝 | 缓冲区初始为黑色(0,0,0) 绘制红色:(0.5,0,0) 计算: (1,0,0)*0.5 + (0,0,0)*0.5 = (0.5,0,0) | 在红色(0.5,0,0)上画蓝色(0,0,0.5) 计算: (0,0,1)*0.5 + (0.5,0,0)*0.5 = (0.25,0,0.5) | (0.25, 0, 0.5) |
由DeepSeek生成
渲染引擎一般都会先对物体进行排序,再渲染:
(1)先渲染所以不透明物体,并开启透明的深度测试和深度写入。
(2)把半透明的物体按照他们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,但是关闭深度写入。
无论选择哪种判断物体深度值的方法,某些情况下都会出现错误的遮挡关系。
常见的解决方法就是分割网格。还可以尽可能让模型是凸面体,将复杂的模型拆成可以独立排序的多个子模型;试着让透明通道更加柔和,使穿插看起来并不是那么明显;使用开启了透明深度写入的半透明效果,来近似模拟物体的半透明。
Unity Shader 的渲染顺序
使用SubShader 的 Queue 标签来决定模型归于哪个渲染队列(render queue)。
-> Background :背景
-> Geometry :大多数物体使用;不透明物体使用
-> AlphaTest :需要透明度测试的物体
-> Transparent :从后往前渲染,使用了透明度混合的物体使用
-> Overlay : 叠加效果;最后渲染的物体
代码:
1 | SubShader { |
实践:透明度测试
在片元着色器中使用 clip 函数进行透明度测试。
实践
在 Unity 中实现透明度测试的效果。
我们需要把Queue标签设置为AlphaTest。而RenderType标签可以让Unity把这个Shader归入到提前定义的组(这里就是TransparentCutout组)中,以指明该Shader是一个使用了透明度测试的Shader。RenderType标签通常被用于着色器替换功能。我们还把IgnoreProjector设置为True,这意味着这个Shader不会受到投影器(Projectors)的影响。通常,使用了透明度测试的Shader都应该在SubShader中设置这三个标签。
1 | // Alpha test |
实践:透明度测试
真正的半透明效果。
实践
在 Unity 中实现透明度测试的效果。
混合命令——Blend
Blend Off 关闭混合;
Blend SrcFactor DstFactor 开启混合,并设置混合因子;
Blend SrcFactor DstFactor, SrcFactorA DstFactorA 如上,另外控制透明度的混合
BlendOp BlendOperation 使用 BlendOperation 进行其他操作
开启深度写入的半透明效果
由于关闭深度写入而造成的错误排序,一种解决方法是:使用两个Pass渲染模型。
第一个Pass开启深度写入,但不输出颜色;第二个 Pass 按照像素级别的深度排序结果进行透明渲染。
实践
在 Unity 中实现开启深度写入的半透明效果。
在原来的 Pass 前新增一个 Pass
1 | Pass { |
这个 Pass 只把模型的深度信息写入深度缓冲,从而剔除模型中被自身遮挡的片元。
ColorMask 用于设置颜色通道的写掩码(write mask)
1 | ColorMask RGB | A | 0 | 其他任何 R G B A 的组合 |
ShaderLab的混合命令
总之就是控制混合的。用到再查。
双面渲染的透明效果
实践
在 Unity 中实现透明度测试的双面渲染。
加一行 Cull Off 来关闭背面剔除即可
1 | Cull Back | Front | Off // 默认为Back,即背面剔除 |
透明度混合的双面渲染
注意
由于关闭了深度写入,如果只是关闭剔除,那么可能出现正面和背面渲染顺序错乱的情况。
所以我们用两个Pass,先渲染背面,再渲染正面。在原有代码上修改:
(1)复制原Pass的代码,得到另一个Pass。
(2)在两个 Pass 中分别使用 Cull 指令剔除不同朝向的渲染图元。
实践
在 Unity 中实现透明度混合的双面渲染。
- 标题: 《Unity Shader入门精要》读书笔记07
- 作者: 铁名_IronName
- 创建于 : 2026-01-18 10:43:08
- 更新于 : 2026-01-19 14:42:52
- 链接: https://blog.ironname.top/2026/01/18/《Unity-Shader入门精要》读书笔记07/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。