Unity3D Shader 渲染状态详解

Unity3D Shader 渲染状态详解。

Unity3D Shader 渲染状态详解

前言

很多刚学 Unity Shader 的同学,一开始最关注的都是:

  • vert 怎么写
  • frag 怎么写
  • 纹理怎么采样

但真正开始做效果后,你很快就会发现:

有时候问题根本不在代码逻辑,而在渲染状态。

例如:

  • 为什么物体被挡住了却还显示在前面?
  • 为什么透明物体看起来怪怪的?
  • 为什么描边会盖住本体?
  • 为什么同样的颜色混合结果完全不同?

这些问题,很多都和 Render State(渲染状态) 有关。

什么是渲染状态

渲染状态可以理解为:

GPU 在画这个 Pass 时,需要遵守的一组规则。

比如:

  • 要不要剔除背面
  • 要不要写入深度
  • 深度如何比较
  • 颜色如何混合

这些并不是写在 vert() / frag() 里的计算代码,
而是写在 Pass 外层的控制指令。

例如:

1
2
3
4
5
6
7
8
9
10
Pass
{
Cull Back
ZWrite On
ZTest LEqual

CGPROGRAM
...
ENDCG
}

这些 CullZWriteZTest 就是渲染状态。

为什么渲染状态这么重要

因为同样的 Shader 代码,只要渲染状态一改,结果可能完全不同。

例如你明明返回的是同样的颜色:

1
return fixed4(1, 0, 0, 0.5);

如果没有设置混合:

  • 它可能直接不透明地画上去

如果加上:

1
Blend SrcAlpha OneMinusSrcAlpha

它才会按 Alpha 做半透明混合。

所以:

渲染状态决定“怎么画”,Shader 代码决定“画什么”。

最常见的几个渲染状态

这一篇重点讲 5 个最常用的:

  • Cull
  • ZWrite
  • ZTest
  • Blend
  • ColorMask

最后再补充:

  • Queue
  • RenderType

Cull 面剔除

Cull 用来控制:

哪些面的三角形要被剔除,不参与渲染。

常见取值:

1
2
3
Cull Back
Cull Front
Cull Off

1 Cull Back

剔除背面。

这是最常见、也是默认的设置。

意思是:

  • 面朝摄像机的一侧绘制
  • 背向摄像机的一侧不画

适合大多数实体模型。

2 Cull Front

剔除正面,只画背面。

这在普通模型里不常用,
但在这些效果中非常关键:

  • 描边
  • 外扩壳层
  • 某些双层特效

例如你之前写的法线外扩描边,就是典型场景。

3 Cull Off

正反两面都绘制。

适合:

  • 纸片树叶
  • 布料
  • 一些双面面片特效

但要注意:

双面渲染通常会增加填充开销。

ZWrite 深度写入

ZWrite 控制的是:

当前物体渲染后,要不要把深度写进深度缓冲。

常见写法:

1
2
ZWrite On
ZWrite Off

ZWrite On

写入深度。

通常用于:

  • 不透明物体
  • 需要正确遮挡关系的物体

这也是默认行为。

ZWrite Off

不写入深度。

通常用于:

  • 透明物体
  • 粒子
  • 光效叠加

为什么透明物体常常要关掉 ZWrite

因为如果透明物体先把深度写进去,
后面的透明物体可能会被错误挡住。

ZTest 深度测试

ZTest 控制的是:

当前像素是否允许通过深度比较。

最常见写法:

1
ZTest LEqual

意思是:

当前像素深度 小于等于 深度缓冲中的值时,才允许绘制。

也就是说:

  • 更靠近摄像机的像素能画出来
  • 被挡在后面的像素画不出来

常见取值

1
2
3
ZTest LEqual
ZTest Greater
ZTest Always

ZTest LEqual

默认值,最常用。

ZTest Greater

只有当当前像素更“远”时才通过。

比较少见,但可以做一些特殊遮挡效果。

ZTest Always

永远通过深度测试。

适合:

  • 屏幕叠加特效
  • 永远显示在最上层的提示
  • 调试显示

但要谨慎使用,因为它会无视正常遮挡关系。

Blend 颜色混合

Blend 用来控制:

当前像素颜色,如何与屏幕上已有颜色混合。

最常见的透明混合:

1
Blend SrcAlpha OneMinusSrcAlpha

它的效果就是我们常说的:

标准 Alpha 混合。

几种常见混合模式

1 普通透明

1
Blend SrcAlpha OneMinusSrcAlpha

适合:

  • 玻璃
  • UI 半透明
  • 常规透明材质

2 纯加法混合

1
Blend One One

特点:

  • 越叠越亮
  • 没有“遮住后面”的感觉

适合:

  • 火焰
  • 魔法光效
  • 能量特效

3 Alpha 加法

1
Blend SrcAlpha One

比纯加法更容易控制亮度。

适合很多特效场景。

ColorMask 颜色通道写入控制

ColorMask 用来控制:

当前 Pass 允许写入哪些颜色通道。

例如:

1
ColorMask RGB

表示只写 RGB,不写 Alpha。

再比如:

1
ColorMask 0

表示不写任何颜色。

这有什么用?

一个典型用途是:

  • 只写深度
  • 不输出可见颜色

常见于:

  • 特殊遮挡处理
  • 预写深度
  • 某些后处理辅助 Pass

Queue 渲染队列

Queue 决定的是:

这个物体大致在什么时候渲染。

常见写法:

1
Tags { "Queue"="Geometry" }

常见队列:

Queue 数值 用途
Background 1000 背景
Geometry 2000 不透明物体
AlphaTest 2450 裁剪物体
Transparent 3000 半透明物体
Overlay 4000 叠加层

一般来说:

  • 不透明 → Geometry
  • 裁剪 → AlphaTest
  • 半透明 → Transparent

RenderType 材质分类标签

例如:

1
Tags { "RenderType"="Opaque" }

它主要是告诉 Unity:

这个 Shader 属于哪一类渲染材质。

常见值:

  • Opaque
  • Transparent
  • TransparentCutout

它常用于:

  • 替换 Shader
  • 渲染分类
  • 某些内置流程判断

一个简单的渲染状态示例

下面这个 Pass 同时设置了几个常见状态:

1
2
3
4
5
6
7
8
9
10
11
12
Pass
{
Cull Off
ZWrite Off
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}

这段配置表示:

  • 双面都画
  • 不写深度
  • 仍然参与正常深度测试
  • 按 Alpha 做半透明混合

这就是很多透明面片特效的典型配置。

常见组合方案

1 不透明物体

1
2
3
4
5
Cull Back
ZWrite On
ZTest LEqual
Blend Off
Tags { "Queue"="Geometry" "RenderType"="Opaque" }

2 透明裁剪物体

1
2
3
4
5
Cull Back
ZWrite On
ZTest LEqual
Blend Off
Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" }

3 半透明物体

1
2
3
4
5
Cull Back
ZWrite Off
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
Tags { "Queue"="Transparent" "RenderType"="Transparent" }

4 加法特效

1
2
3
4
5
Cull Off
ZWrite Off
ZTest LEqual
Blend One One
Tags { "Queue"="Transparent" "RenderType"="Transparent" }

常见坑

1 透明物体忘记关 ZWrite

结果往往是:

  • 前后透明物体互相遮挡异常
  • 看起来“缺一块”

2 写了半透明颜色却没开 Blend

例如:

1
return fixed4(1,1,1,0.5);

如果没写 Blend,它并不会自动帮你变成半透明。

3 双面渲染滥用 Cull Off

有些模型本来应该有厚度,却直接开双面,
容易导致:

  • 性能浪费
  • 视觉不合理

4 ZTest Always 用过头

虽然看起来方便,
但它经常会让特效无视遮挡,显得很“飘”。

总结

渲染状态决定这个 Pass 以什么规则被画出来。

最常见的几个状态作用如下:

状态 作用
Cull 控制剔除哪一面
ZWrite 是否写入深度
ZTest 如何进行深度比较
Blend 如何与背景颜色混合
ColorMask 写入哪些颜色通道
Queue 大致渲染顺序
RenderType 材质分类标签

Unity3D Shader 渲染状态详解
http://weikunou.github.io/2026/05/24/unity-shader-render-state/
作者
Awake
发布于
2026年5月24日
许可协议