GameTech/URP 渲染实战

案例 8.6粗糙度与 mip:两种映射的对比入门

目标:写一个只输出间接高光的 Shader,分别用 URP 的曲线和线性映射对同一个环境做粗糙度扫描。

Assets/Cookbook/Ch08/EnvReflection.shader(节选:manual)
// 手动版:全局环境反射(Lighting 窗口里的 Environment Reflections)由 URP 设置为
// _GlossyEnvironmentCubeMap,它的 mip 链是按粗糙度预过滤过的
half3 SampleEnvManual(half3 R, half perceptualRoughness, bool urpCurve)
{
    half mip = urpCurve
        ? PerceptualRoughnessToMipmapLevel(perceptualRoughness)   // r·(1.7-0.7r)·6
        : perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;          // 线性:r·6
    half4 encoded = SAMPLE_TEXTURECUBE_LOD(_GlossyEnvironmentCubeMap, sampler_GlossyEnvironmentCubeMap, R, mip);
    // HDR 解码:RGBM/dLDR 编码的 cubemap 需要 _HDR 参数还原,浮点格式时它只是乘一个强度
    return DecodeHDREnvironment(encoded, _GlossyEnvironmentCubeMap_HDR);
}
// 手动版:全局环境反射(Lighting 窗口里的 Environment Reflections)由 URP 设置为
// _GlossyEnvironmentCubeMap,它的 mip 链是按粗糙度预过滤过的
vec3 SampleEnvManual(vec3 R, float perceptualRoughness, bool urpCurve)
{
    float mip = urpCurve
        ? PerceptualRoughnessToMipmapLevel(perceptualRoughness)   // r·(1.7-0.7r)·6
        : perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;          // 线性:r·6
    vec4 encoded = textureLod(_GlossyEnvironmentCubeMap, R, mip);
    // HDR 解码:RGBM/dLDR 编码的 cubemap 需要 _HDR 参数还原,浮点格式时它只是乘一个强度
    return DecodeHDREnvironment(encoded, _GlossyEnvironmentCubeMap_HDR);
}
图 8-10感知粗糙度从左到右为 0、0.2、0.4、0.6、0.8、1.0,环境为“摄影棚”Cubemap。上排:URP 的映射 PerceptualRoughnessToMipmapLevel;下排:线性映射 r × 6。两排在两端相同,中间几列上排明显更模糊。

如果你在自写 PBR 里随手用了线性映射,同一个粗糙度值的材质会比 URP Lit 显得更光滑——这是自写 Shader 与官方 Shader “对不上”的常见原因之一。与 URP 保持一致,就用它提供的函数。