转载自 Unity3D ShaderLab 之 BoxProjectedCubemapDirection解读
Unity 的反射,依赖于布置在场景中的Reflection Probe(当然,会有一个全场景默认的)
而这个组件上有一个开关“Box Projection”
Box Projection开关与否的区别请参见 官方文档
这里简要的说明一下
反射实现本质上就是Cubemap采样,和天空盒一个原理。
Box Projection Off/On 区别简述- 当Box Projection Off时,和天空盒就更像了,把Cubemap想象成一个大盒子,你处在盒子的正中心,你在世界里移动的时候,这个大盒子会跟着你一起动,造成的结果就是无论你往哪个方向看,结果并不会随你在世界中的位置变化而变化——对于确定的观察方向,确定的采样结果,与位置无关。
- 当Box Projection On时,好比这个大盒子在世界中就固定下来了,你往特定方向观察到的结果会随着你在世界中跑动而变化。
Unity的CGIncludes中已经给出了答案,我们可以先看 UnityGI_IndirectSpecular 函数。这个函数中还处理了两个Reflection Probe混合的情况,这不是我们关心的重点,简化之后代码如下:
inline half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
{
half3 specular;
#ifdef UNITY_SPECCUBE_BOX_PROJECTION
// we will tweak reflUVW in glossIn directly (as we pass it to Unity_GlossyEnvironment twice for probe0 and probe1), so keep original to pass into BoxProjectedCubemapDirection
half3 originalReflUVW = glossIn.reflUVW;
glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
#endif
half3 env0 = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
specular = env0;
return specular * occlusion;
}
简化后的代码非常清晰,从上往下看,
首先定义了half3 specular存储返回结果。 然后是预定义宏UNITY_SPECCUBE_BOX_PROJECTION,代表了Tier Settings中是否启用了Box Projection 如果启用了Box Projection,则通过BoxProjectedCubemapDirection计算变换后的方向 通过调用Unity_GlossyEnvironment采样Reflection Cube,计算HDR。 结果乘以材质上传递过来的遮蔽值,返回
BoxProjectedCubemapDirection一探究竟