URP 渲染实战 / 第 8 章 环境光、光照贴图与反射探针 / 案例 8.8
案例 8.8盒体投影:让地板的倒影“贴”住墙进阶
目标:搭一个 6 × 3 × 6 米的房间,墙上画网格和一条白色腰线,地板是半光滑的反射面,对比开关盒体投影的效果。
为了让对比严格可控,本案例没有用场景里的 ReflectionProbe 组件,而是把“探针”的三个参数(Cubemap、中心位置、盒子范围)直接放在材质上,Shader 里调用的仍然是上面那个 URP 函数 BoxProjectedCubemapDirection。房间中心的 Cubemap 用解析方式生成:从中心沿每个方向求与房间盒子的交点,按交点处的墙面图案着色——墙面 Shader 和 Cubemap 生成器用的是逐行对应的同一个图案函数(RoomPattern.hlsl 与 BoxProjectionDemo.cs),所以 Cubemap 里的墙与场景中的墙严格一致,倒影的任何错位都只能来自投影方式本身。
Assets/Cookbook/Ch08/BoxProjection.shader(节选:frag)
half4 frag(Varyings i) : SV_Target { half3 N = normalize(i.normalWS); half3 V = GetWorldSpaceNormalizeViewDir(i.positionWS); half3 R = reflect(-V, N); #if defined(_BOX_PROJECTION) // 第 4 个分量 w > 0 表示“这个探针启用了盒体投影”,与 URP 的 unity_SpecCube0_ProbePosition 约定一致 R = BoxProjectedCubemapDirection(R, i.positionWS, float4(_ProbePosition.xyz, 1), _BoxMin, _BoxMax); #endif half mip = PerceptualRoughnessToMipmapLevel(_Roughness); half3 refl = SAMPLE_TEXTURECUBE_LOD(_Cube, sampler_Cube, R, mip).rgb; // 简化的菲涅尔:掠射角反射更强 half NoV = saturate(dot(N, V)); half F = _Reflectivity + (1 - _Reflectivity) * Pow4(1 - NoV) * 0.5; half3 diffuse = _BaseColor.rgb * SampleSH(N); return half4(lerp(diffuse, refl, F), 1); }
void main() { vec3 N = normalize(normalWS); vec3 V = GetWorldSpaceNormalizeViewDir(positionWS); vec3 R = reflect(-V, N); #if defined(_BOX_PROJECTION) // 第 4 个分量 w > 0 表示“这个探针启用了盒体投影”,与 URP 的 unity_SpecCube0_ProbePosition 约定一致 R = BoxProjectedCubemapDirection(R, positionWS, vec4(_ProbePosition.xyz, 1.0), _BoxMin, _BoxMax); #endif float mip = PerceptualRoughnessToMipmapLevel(_Roughness); vec3 refl = textureLod(_Cube, R, mip).rgb; // 简化的菲涅尔:掠射角反射更强 float NoV = saturate(dot(N, V)); float F = _Reflectivity + (1.0 - _Reflectivity) * Pow4(1.0 - NoV) * 0.5; vec3 diffuse = _BaseColor.rgb * SampleSH(N); fragColor = vec4(mix(diffuse, refl, F), 1.0); }

盒体投影只在“环境近似是一个盒子”时准确。房间中间放着的家具、柱子不在盒子的面上,它们的倒影仍然会错位;圆形或不规则的空间也只能近似。另外,盒体投影要求探针的盒子与房间的墙对齐,盒子大了倒影会“缩”、小了会“胀”。在室外开阔场景中,应关掉探针的 Box Projection,因为环境确实接近无限远。
说明在本书的批处理拍摄流程里,脚本新建的 ReflectionProbe 组件不会被引擎即时登记进剔除结果,探针不生效,所以本案例改为由材质提供探针参数。在编辑器和运行时里正常摆放的反射探针不受此影响,GILit 等使用
GlossyEnvironmentReflection 的 Shader 会自动获得探针的盒体投影与混合。本案例出自《URP 渲染实战》第 8 章「环境光、光照贴图与反射探针」。在章节中阅读上下文 →