在 ShaderLab 中, 标签(Tags) 是定义子着色器(SubShader)行为的关键键值对,用于控制渲染顺序、管线兼容性、阴影投射等核心功能。Unity 通过预定义标签识别 SubShader 的适用场景,开发者也可自定义标签扩展功能。以下是标签的核心用法、管线适配及实践示例:
一、标签的核心作用与分类
标签通过键值对告诉 Unity 如何处理 SubShader,主要分为以下几类:
- 渲染管线兼容性:如
RenderPipeline
标签指定适用管线(URP/HDRP)。 - 渲染顺序控制:如
Queue
标签定义渲染队列,确保透明物体正确排序。 - 功能开关:如
ForceNoShadowCasting
禁用阴影投射,DisableBatching
关闭动态合批。 - 编辑器预览:如
PreviewType
控制材质面板的预览形状(球体 / 平面 / 天空盒)。
二、关键标签详解
1. 渲染管线兼容性:RenderPipeline
- 作用:明确 SubShader 兼容的渲染管线,避免跨管线误用。
- 取值:
UniversalRenderPipeline
:仅 URP 可用。HighDefinitionRenderPipeline
:仅 HDRP 可用。- 未声明或其他值:仅内置管线或自定义 SRP 使用。
- 示例:
hlsl
SubShader { Tags { "RenderPipeline" = "UniversalRenderPipeline" } // URP 专属渲染逻辑 }
2. 渲染队列:Queue
- 作用:控制物体渲染顺序(数值越小越先渲染)。
- 预定义队列:
队列名称 数值范围 用途 Background 1000 背景物体(如天空盒) Geometry 2000 不透明物体(默认) AlphaTest 2450 透明度测试物体(如植被) Transparent 3000 透明物体(需混合) Overlay 4000 叠加效果(如镜头光晕) - 偏移值用法:
Queue = "Geometry+1"
表示在 Geometry 队列之后 1 位渲染,用于插队渲染(如透明水体需在不透明物体之后、其他透明物体之前)。
3. 渲染类型:RenderType
- 作用:
- 内置管线中用于着色器替换(Shader Replacement),如渲染深度纹理时匹配
RenderType="Opaque"
。 - SRP 中用于自定义渲染状态匹配(如通过
RenderStateBlock
覆盖特定类型物体的设置)。
- 内置管线中用于着色器替换(Shader Replacement),如渲染深度纹理时匹配
- 示例:
hlsl
SubShader { Tags { "RenderType" = "TransparentCutout" } // 透明裁剪材质(如带 Alpha 裁剪的树叶) }
4. 阴影控制:ForceNoShadowCasting
- 作用:禁用阴影投射,甚至在部分管线中禁用阴影接收。
- 取值:
True
:禁止投射阴影(HDRP 中不影响接触阴影),内置管线中同时禁止接收阴影。False
:默认值,允许投射和接收阴影。
- 场景:粒子特效或 UI 元素无需阴影时,减少渲染开销。
5. 动态合批控制:DisableBatching
- 作用:禁止 Unity 对使用该 SubShader 的物体进行动态合批。
- 适用场景:
- 着色器使用物体空间坐标(如顶点动画依赖
v.vertex
)。 - 材质参数每物体不同(动态合批要求材质完全一致)。
- 着色器使用物体空间坐标(如顶点动画依赖
- 示例:
hlsl
SubShader { Tags { "DisableBatching" = "True" } // 含物体空间操作的顶点着色器 }
6. 编辑器预览类型:PreviewType
- 作用:设置材质面板预览形状,提升可视化准确性。
- 取值:
Sphere
:球体(默认),适合通用材质。Plane
:平面,适合地表或 UI 材质。Skybox
:天空盒,适合环境材质。
- 示例:
hlsl
SubShader { Tags { "PreviewType" = "Plane" } // 地面材质预览为平面 }
三、跨渲染管线的标签适配
标签 | 内置管线 | URP | HDRP | 自定义 SRP |
---|---|---|---|---|
RenderPipeline | 不适用 | 必须声明 | 必须声明 | 自定义标签或忽略 |
Queue | 有效 | 有效(兼容内置规则) | 有效(兼容内置规则) | 可选(自定义排序逻辑) |
RenderType | 关键(着色器替换) | 有效(SRP 状态匹配) | 有效(SRP 状态匹配) | 有效 |
ForceNoShadowCasting | 有效 | 有效(不影响接触阴影) | 有效(不影响接触阴影) | 自定义逻辑 |
DisableBatching | 有效 | 有效 | 有效 | 有效 |
URP/HDRP 特殊注意事项:
- URP/HDRP 要求 SubShader 必须声明
RenderPipeline
标签,否则可能被忽略。 - HDRP 中
Queue
标签需配合RenderType
使用,例如透明物体需同时设置Queue=Transparent
和RenderType=Transparent
。
四、自定义标签与脚本交互
-
自定义标签
可定义任意键值对标签(如Tags { "MyCustomTag" = "HighQuality" }
),通过 C# 脚本读取:csharp
string customValue = material.GetTag("MyCustomTag", true, "DefaultValue");
-
内置标签的脚本控制
- 获取当前材质的渲染队列:
csharp
int renderQueue = material.renderQueue;
- 动态覆盖队列(优先级高于标签):
csharp
material.renderQueue = (int)RenderQueue.Transparent;
- 获取当前材质的渲染队列:
五、最佳实践与示例
1. 透明材质的正确排序
hlsl
SubShader {
Tags {
"Queue" = "Transparent" // 透明队列(3000)
"RenderType" = "Transparent"
"IgnoreProjector" = "True" // 避免投影器导致显示错误
}
Blend SrcAlpha OneMinusSrcAlpha
Pass {
// 透明混合渲染逻辑
}
}
2. URP 专用 SubShader
hlsl
SubShader {
Tags {
"RenderPipeline" = "UniversalRenderPipeline"
"LightMode" = "UniversalForward" // URP 正向渲染标签
"RenderType" = "Opaque"
}
LOD 200
Pass {
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// URP 光照计算
ENDCG
}
}
3. 禁用阴影的粒子特效
hlsl
SubShader {
Tags {
"ForceNoShadowCasting" = "True" // 禁止投射阴影
"DisableBatching" = "True" // 粒子通常使用不同材质实例
"RenderType" = "Transparent"
}
// 粒子着色逻辑(如 Billboard 渲染)
}
4. 材质预览优化
hlsl
SubShader {
Tags {
"PreviewType" = "Plane" // 地形材质预览为平面
"CanUseSpriteAtlas" = "False" // 禁止打包到精灵图集(若使用自定义 UV)
}
// 地形材质逻辑
}
六、常见问题与调试
-
标签冲突导致渲染异常
- 现象:URP 项目中材质显示为粉色(错误材质)。
- 原因:未声明
RenderPipeline="UniversalRenderPipeline"
标签,URP 忽略该 SubShader。 - 解决:添加正确标签并确保 HLSL 引用 URP 库。
-
渲染顺序错误
- 现象:透明物体遮挡不透明物体。
- 原因:
Queue
标签设置错误(如透明物体使用Queue=Geometry
)。 - 解决:设置
Queue=Transparent
或自定义偏移值(如Queue=Geometry+1
)。
-
动态合批失效
- 现象:大量相同材质物体渲染卡顿。
- 原因:SubShader 包含
DisableBatching="True"
或着色器使用物体空间坐标。 - 解决:移除标签或重构着色器使用世界空间坐标。
七、总结
SubShader 标签是 Unity 渲染流程的 “指挥中心”,通过合理配置可精准控制渲染行为、适配不同管线,并优化编辑器体验。在实际开发中,需根据项目的管线类型(内置 / SRP)和功能需求(如阴影、合批)选择标签组合,同时利用自定义标签扩展脚本交互能力。掌握标签的核心规则,是实现高性能、高兼容性着色器的必要条件。