GameTech/URP 渲染实战

案例 8.3每一阶 SH 贡献了什么进阶

目标:用一个色彩强烈的环境(上方暖白、左侧红、右侧蓝、下方偏绿),分别只用 L0、L0+L1、完整三阶来渲染,看清每一阶的作用。

Assets/Cookbook/Ch08/AmbientSH.shader(节选:bands)
// unity_SHAr/Ag/Ab:xyz = L1 三个系数,w = L0 系数“减去”L2 里 Y20 的常数部分;
// unity_SHBr/Bg/Bb:L2 中 xy、yz、zz、zx 四项;unity_SHC:L2 中 x²-y² 一项(rgb 三通道)。
// 这些系数已经乘上了“余弦卷积”因子并除以 π,所以直接算出来的就是 URP 约定下的间接漫反射。
half3 EvaluateSHBands(half3 N, int bands)
{
    // L2 在整个球面上积分为 0,但 zz 项的平均值是 1/3。Unity 把 Y20 的常数部分挪进了 w,
    // 想要“纯 L0”,就把 zz 项的平均值 SHB.z/3 加回去。
    half3 L0 = half3(unity_SHAr.w + unity_SHBr.z / 3.0,
                     unity_SHAg.w + unity_SHBg.z / 3.0,
                     unity_SHAb.w + unity_SHBb.z / 3.0);
    if (bands == 0) return L0;

    half3 L1 = half3(dot(unity_SHAr.xyz, N), dot(unity_SHAg.xyz, N), dot(unity_SHAb.xyz, N));
    if (bands == 1) return max(0, L0 + L1);

    // 完整三阶:与 URP 的 SampleSH(N) 完全相同(SHEvalLinearL0L1 + SHEvalLinearL2)
    return SampleSH(N);
}
// unity_SHAr/Ag/Ab:xyz = L1 三个系数,w = L0 系数“减去”L2 里 Y20 的常数部分;
// unity_SHBr/Bg/Bb:L2 中 xy、yz、zz、zx 四项;unity_SHC:L2 中 x²-y² 一项(rgb 三通道)。
// 这些系数已经乘上了“余弦卷积”因子并除以 π,所以直接算出来的就是 URP 约定下的间接漫反射。
vec3 EvaluateSHBands(vec3 N, int bands)
{
    // L2 在整个球面上积分为 0,但 zz 项的平均值是 1/3。Unity 把 Y20 的常数部分挪进了 w,
    // 想要“纯 L0”,就把 zz 项的平均值 SHB.z/3 加回去。
    vec3 L0 = vec3(unity_SHAr.w + unity_SHBr.z / 3.0,
                   unity_SHAg.w + unity_SHBg.z / 3.0,
                   unity_SHAb.w + unity_SHBb.z / 3.0);
    if (bands == 0) return L0;

    vec3 L1 = vec3(dot(unity_SHAr.xyz, N), dot(unity_SHAg.xyz, N), dot(unity_SHAb.xyz, N));
    if (bands == 1) return max(vec3(0.0), L0 + L1);

    // 完整三阶:与 URP 的 SampleSH(N) 完全相同(SHEvalLinearL0L1 + SHEvalLinearL2)
    return SampleSH(N);
}

“只要 L0”并不是简单地取 unity_SHAr.w:Unity 把 Y20 = c(3z² − 1) 中的常数项 −c 挪进了 w,所以 w 里混着一部分 L2。L2 整体在球面上积分为 0,而 zz 项在球面上的平均值是 1/3,所以把 SHBr.z / 3 加回去,就恢复出真正的 L0。这个小推导能帮你在需要“平均环境亮度”时取到正确的值(例如给粒子、头发卡片一个不随方向变化的环境光)。

图 8-5同一个彩色环境,从左到右:只用 L0(处处同色,没有任何方向信息)、L0 + L1(左红右蓝、上亮下暗,已经有了主要的方向感)、完整三阶(球体底部出现绿色、顶部更暖,色彩过渡更丰富)。

从 L0 到 L1 是质变,从 L1 到 L2 是改进。在极度受限的情况下(例如非常低端的设备、大量的植被实例),只用 L0+L1 也是可以接受的近似;URP 的混合模式也正是基于这样的判断——L1 必须在像素里算,L2 可以降到顶点。