Unity3D的内置宏 _ADDITIONAL_LIGHTS_VERTEX
Table of Contents
请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
在Unity URP中,_ADDITIONAL_LIGHTS_VERTEX
是一个与 附加光源处理方式 相关的内置变体关键字(Shader Variant Keyword)。它的核心作用是 控制附加光源的光照计算阶段,决定是在 顶点着色器 还是 片元着色器 中处理附加光源的贡献。
核心含义
1. 光源计算阶段选择
- 启用时(
_ADDITIONAL_LIGHTS_VERTEX
被定义):
附加光源的光照计算在 顶点着色器 阶段完成,计算结果通过顶点插值传递到片元着色器。 - 未启用时(默认或使用
_ADDITIONAL_LIGHTS
):
附加光源的光照计算在 片元着色器 阶段逐像素完成。
2. 性能与质量的权衡
模式 | 性能消耗 | 光照精度 | 适用场景 |
---|---|---|---|
_ADDITIONAL_LIGHTS_VERTEX |
较低 | 中等(顶点插值) | 移动端、低性能设备 |
_ADDITIONAL_LIGHTS |
较高 | 高(逐像素) | PC/主机、高质量渲染需求 |
触发条件
该宏的激活由以下因素决定:
-
URP Asset设置
- 在URP资源中启用 Additional Lights(附加光源)
- 设置 Per Object Light 类型为 Vertex 或 Fragment(对应不同模式)
-
Shader编译指令
在Shader中使用以下指令声明变体:#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
-
实际光源数量
当场景中存在 附加光源(点光源、聚光灯等) 且影响当前渲染对象时,Unity自动选择对应变体。
技术实现原理
顶点着色器阶段处理(_ADDITIONAL_LIGHTS_VERTEX
)
// 顶点着色器中计算附加光源
Varyings vert(Attributes input) {
Varyings output;
// ...
#ifdef _ADDITIONAL_LIGHTS_VERTEX
output.vertexLighting = CalculateVertexLights(input.positionWS);
#endif
return output;
}
片元着色器阶段处理(_ADDITIONAL_LIGHTS
)
// 片元着色器中计算附加光源
half4 frag(Varyings input) : SV_Target {
// ...
#ifdef _ADDITIONAL_LIGHTS
half3 additionalLights = CalculateFragmentLights(input.positionWS);
#endif
return color;
}
典型应用场景
1. 顶点着色器模式(优化性能)
- 代码特征:
在顶点输出结构体(Varyings
)中存储预计算的光照值:struct Varyings { float4 positionCS : SV_POSITION; #if defined(_ADDITIONAL_LIGHTS_VERTEX) half3 vertexLighting : TEXCOORD5; // 存储顶点光照结果 #endif };
- 视觉效果:
光照过渡呈现顶点插值的“块状”效果,适用于动态物体或低精度需求场景。
2. 片元着色器模式(追求质量)
- 代码特征:
在片元着色器中直接调用光照计算函数:half4 frag(Varyings input) : SV_Target { InputData lightingData = ...; #if defined(_ADDITIONAL_LIGHTS) additionalLights += GetAdditionalLights(lightingData); #endif }
- 视觉效果:
光照过渡平滑,适用于静态高精度场景(如角色面部、复杂材质)。
调试与手动控制
1. 强制指定模式(测试用)
在Shader顶部添加定义:
#define _ADDITIONAL_LIGHTS_VERTEX // 强制顶点模式
// #define _ADDITIONAL_LIGHTS // 强制片元模式
2. 查看当前激活模式
通过条件编译判断:
#if defined(_ADDITIONAL_LIGHTS_VERTEX)
// 当前为顶点光照模式
#elif defined(_ADDITIONAL_LIGHTS)
// 当前为片元光照模式
#endif
3. 性能分析工具
使用 Unity Profiler 或 Frame Debugger 观察:
- 顶点模式:
SRPBatcher
提交批次更多,但GPU负载更低 - 片元模式:Draw Call数量可能减少,但片元计算压力更大
常见问题与解决方案
问题 1:附加光源不生效
- 可能原因:
未正确声明变体或URP设置中附加光源被禁用。 - 解决方案:
- 检查Shader中的
#pragma multi_compile
指令 - 确认URP Asset中
Additional Lights > Mode
未设置为Not Enabled
- 检查Shader中的
问题 2:光照出现明显锯齿
- 现象:
使用顶点模式时,光源边缘呈现块状过渡。 - 优化方案:
- 切换为片元模式(
_ADDITIONAL_LIGHTS
) - 增加受影响物体的顶点密度
- 使用光照贴图烘焙静态光源
- 切换为片元模式(
问题 3:Shader变体爆炸
- 现象:
因multi_compile
组合过多导致构建时间过长。 - 优化方案:
- 使用
shader_feature
替代multi_compile
- 在URP Asset中限制最大附加光源数量:
// URP Asset设置路径 Graphics > URP Global Settings > Lighting > Additional Lights > Per Object Limit
- 使用
最佳实践建议
-
移动端优先策略
- 默认启用
_ADDITIONAL_LIGHTS_VERTEX
- 通过URP Asset设置
Per Object Limit = 1-4
- 使用LOD系统动态切换光源模式
- 默认启用
-
高质量场景配置
- 启用
_ADDITIONAL_LIGHTS
- 结合 Screen Space Shadows 和 Light Layers
- 使用 Compute Shader 处理复杂光源
- 启用
-
混合模式设计
在Shader中实现动态切换逻辑:half3 GetAdditionalLights(InputData input) { #if defined(_ADDITIONAL_LIGHTS_VERTEX) return input.vertexLighting; #elif defined(_ADDITIONAL_LIGHTS) return CalculatePerPixelLights(input); #endif }
通过合理使用 _ADDITIONAL_LIGHTS_VERTEX
,开发者可以在渲染质量和性能之间找到最佳平衡点,尤其对于需要支持多平台的Unity项目至关重要。