关于光照探针的实验和疑问
光照探针主要用途在为场景中的移动对象提供高质量光照(包括间接反射)。
与光照贴图不同的是,探针是捕获并使用穿过场景空白空间的光线。
与光照贴图类似,存储了场景里光照的烘焙信息,也需要事先烘焙。但是贴图存的是照到表面的信息,而探针存的是空白空间的信息。而且探针还会采集相邻的其它探针存储的光照信息,把所有采样到的信息插值,以此得到任意位置的光照信息。
动态物体用光照探针,静态物体用静态贴图。对于小型物体来说也是探针更合适,因为探针的计算快太多了,空间占用也小。实际烘焙一下就知道了,光照探针瞬间完成,光照贴图这个慢呐。。。
探针在运行前的预计算阶段采样,通过球谐函数编码打包存储。运行期间通过着色器还原成光照原始信息。而光照贴图是直接存储的颜色。
球谐函数的主要作用是用简单的系数来表示复杂的球面。
球谐光照就是将周围的环境光采样成几个系数,运行时用这些系数对光照进行还原,可以看做是对周围环境光的简化。
球谐函数有阶数,L1、L2之类的,如果要处理光的高频信息就需要更高的阶数。通常在光照中取3阶,也就是9个球谐系数,看内置的着色器里函数都是SH9。
在shader里实现采样
1、片元输入结构体里加入顶点SH的声明。可以借助Lighting.hlsl里的宏定义。
DECLARE_LIGHTMAP_OR_SH(staticLightmapUV, vertexSH, 7);
声明的TEXCOORD变量应该到几了参数里就写几,上面写的7就是。
2 、因为SH是顶点级别的光照数据,所以在顶点函数里获取。有现成的方法SampleSHVertex在GlobalIllumination.hlsl里。或者引入了Lighting.hlsl也行,宏定义OUTPUT_SH映射到了那个方法上。输入世界空间的法线,返回顶点SH数据。
OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
这个函数也会把环境光算进去。
3 、在片元函数里把SH数据还原为表面数据,同样有有现成的方法SampleSHPixel在GlobalIllumination.hlsl里。可以用宏定义SAMPLE_GI,兼容了光照贴图的情况,映射到SampleLightmap方法。
inputData.bakedGI = SAMPLE_GI(input.staticLightmapUV, input.vertexSH, inputData.normalWS);
到这其实就已经可以把bakedGI 乘以albedo了。不过为了兼容更多的关键字,后面直接交给Lighting.hlsl里的UniversalFragmentBlinnPhong方法。
光照探针里也包含阴影数据,但是是低分辨率阴影。
静态物体在烘焙光照贴图会默认贡献全局光照,这同样也会贡献到光照探针里。下面2张图是烘焙完光照贴图和光照探针后,右侧的物体关闭和开启接收光照探针的差分(此时已经没有实时光和环境光)。


探针的结果存在哪了?
一不像光照贴图那样有实体资源,二也不在节点里因为禁用了还生效。
应该是直接存在了场景文件里,就像环境光的参数一样。而且巧妙的一点是光照探针和environment环境光都是通过SampleSH方法来采样的。
但在.unity文件里显示为乱码,看不出来。
为什么光照探针不适用与大型平面或凹面?
因为物体边界的顶点属于不同四面体,插值依赖的探针组不同,光照差异会更明显。
来一个明显的例子:
中间一个不透明面片、下方一个红色点光源、右侧一个动态的长方体

将长方体向下移动一点点

呦呵,突然整个由黑变红了。
因为采样的光照探针由全在上方变成了有在下方的。
为什么会照亮物体的背面?
因为光照探针没有方向。它只是存储了场景中某一点的光照总和。而物体在进行探针采样时也只取决于顶点的位置,完全不考虑法线。
光照探针有范围么?
遗憾的是,直接用光照探针组件时没有范围,是无穷远的。
物体设置接收光照探针后会从最近的探针接收光照,即使物体和探针隔了十万里也一样。而且根本没有衰减。

当物体接收光照探针时,就不会接收来自天空的环境光。但是光照探针在烘焙时是接收了来自天空的环境光的所以按理说没问题。
问题是,光照探针没有范围,因此但凡场景中存在光照探针组,那么天空环境光就再也无法生效,即使你本来只是想在室内用探针。
其实这一点对于反射探针也是一样的,反射探针会覆盖来自天空的反射。但是人家反射探针是自带区域的所以很好用。而光照探针是无限的。即使是那个代理体LPPV,也并没有特别好用。
有地方说光照探针并不是无限的,编辑器窗口仅仅是用来给开发者方便看的,当物体距离探针过远时探针会降级或失效。
但是实测这个说法并不对,从上面的图就能看出来,即使我拉的再远,而且在运行模式中,开启、关闭物体的接收光照探针选项,也是有颜色差异的。
我们知道物体在探针组范围内将会采样最近4个探针,它们会构成四面体。那为什么物体超出光照探针组的范围之后,编辑器会显示与最近的3个探针连线?


当物体超出有效区域后,会显示出最近的3个探针组成的三角形平面。此时会用平面插值来计算光照。但是探针的影响确实是无法消除的。
