Unity Shader 什么是球谐光照 原理是什么

球谐光照(Spherical Harmonics Lighting,简称SH光照)是Unity中一种高效编码低频环境光照 的技术,主要用于Light Probe(光照探针)Skybox环境光 的漫反射计算。它的核心价值在于:用极少的参数(通常9个浮点数)就能近似表达一个物体周围360°的入射光照分布,并在Shader中快速计算出物体表面接收到的漫反射光。

下面从"为什么需要"、"数学原理"、"Unity中的具体应用"三个层面来解释。

一、为什么需要球谐光照?

在实时渲染中,如果要精确计算物体表面某点接收到的间接漫反射光(比如蓝色墙壁反射到红色地毯上的光),理论上需要对该点上半球所有方向的入射光进行积分,这在运行时是不可能完成的。

传统做法:

  • 预计算辐照度贴图:对空间每个点存储一个cubemap → 内存爆炸。

  • 实时Ray Tracing:性能无法满足游戏需求。

球谐光照提供了一个折衷方案

  • 离线预计算:将场景中每个Light Probe位置周围的入射光照,投影到球谐基函数上,存储少量系数(例如27个float,RGB各9个)。

  • 运行时还原:Shader中只需用表面法线点乘这些系数,就能快速得到该点接收到的漫反射光强度。

这样就实现了"用较低的存储和计算成本,获得非常平滑、无方向细节但整体正确的间接漫反射效果"。

二、球谐光照的数学原理(通俗版)

1. 球谐函数------球面上的傅里叶级数

傅里叶级数可以用正弦余弦函数的叠加来逼近任意周期性波形。类似地,球谐函数是定义在球面上的一组正交基函数,可以用它们的加权和来逼近任意定义在球面上的函数(比如从某个点看向各个方向的光照强度)。

球谐函数有很多阶(Order):

  • 0阶:1个基函数(常数项),代表平均亮度。

  • 1阶:3个基函数(线性项),能表示方向性(如上下比左右亮)。

  • 2阶:5个基函数(二次项),能表示更复杂的分布(例如两极性)。

  • 3阶:7个基函数......阶数越高,能重现的细节越丰富。

实际应用中,渲染漫反射(低频)只需前3阶(共1+3+5=9个系数),因为漫反射光照相当于对原始光照进行了低通滤波,高频细节被抹除。

2. 渲染方程中的漫反射简化

在一点p,漫反射颜色公式为:

其中 Li(p,ωi)Li​(p,ωi​) 是该点从方向 ωiωi​ 入射的光照。

如果我们将 Li(p,ωi)Li​(p,ωi​) 投影到球谐基函数上,得到系数 cl,mcl,m​,同时将漫反射的传输函数 (即 max⁡(0,n⋅ωi)max(0,n⋅ωi​))也投影到同一组基上,那么积分结果就等于两组系数的点积。最终化简为

其中 klkl​ 是预先算好的常数(与球谐阶数相关),Yl,m(n)Yl,m​(n) 是球谐基函数在法线方向n上的取值。

在Shader中,这部分计算被合并为一个法线方向的九次多项式

复制代码
// Unity内置的球谐光照计算(简化逻辑)
half3 SHLighting (half3 normal) {
    half4 SHAr = unity_SHAr;
    half4 SHAg = unity_SHAg;
    half4 SHAb = unity_SHAb;
    half4 SHBr = unity_SHBr;
    half4 SHBg = unity_SHBg;
    half4 SHBb = unity_SHBb;
    half4 SHC = unity_SHC;
    
    half3 res = SHEvalLinearL0L1(normal, SHAr, SHAg, SHAb);
    res += SHEvalLinearL2(normal, SHBr, SHBg, SHBb, SHC);
    return res;
}

三、Unity中球谐光照的具体应用

1. 主要载体:Light Probe

  • Light Probe Group 组件可以在场景中放置多个光照探针。

  • Unity在烘焙时,为每个探针位置计算该点的入射光照立方贴图 ,然后投影到3阶球谐函数 ,得到RGB三组9个系数(共27个float),存储在光照数据中。

  • 运行时,物体使用距离最近的几个探针,通过插值获取当前点的球谐系数。

2. Shader中的使用方式

对于受Light Probe影响的物体(通常是静态或动态物体),Unity会自动将插值后的球谐系数通过 unity_SHArunity_SHAg 等内置变量传递给Shader。

获取球谐漫反射光照的标准代码

复制代码
// 在世界空间法线方向计算球谐光照
half3 ambient = ShadeSH9(float4(worldNormal, 1.0));

或者手动调用内置函数:

复制代码
half3 indirectDiffuse = SampleSH(worldNormal);

3. 与传统环境光的区别

特性 传统 Cubemap 环境光 球谐光照 (SH)
存储量 高(6张纹理) 极低(27个float)
精度 高(可表现细节) 低(只有低频信息)
计算开销 高(需要采样立方体贴图) 极低(几个点积和多项式)
适用场景 静态背景反射、高光环境 动态物体间接漫反射、移动端全局光照

四、局限性

  1. 只能表示低频光照

    球谐无法表现尖锐的光影变化,例如点光源直接照明、阴影边缘。因此它只适合做间接光/环境光

  2. 无法用于高光反射

    镜面反射需要高频的环境信息(如清晰的窗户倒影),球谐阶数不够。镜面反射仍需使用反射探针(Reflection Probe)的Cubemap。

  3. 仅适用于漫反射

    球谐光照的传输函数是低通的,与漫反射BRDF匹配,不适合光泽或镜面材质。

    总结一句话

    球谐光照是一种将周围环境光照"压缩"成9个系数的数学技巧,在Shader中通过法线方向快速恢复出物体表面接收到的平滑漫反射光,是Unity实现Light Probe和轻量级全局光照的核心技术。

相关推荐
叶帆9 天前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
久数君10 天前
AI三维建模工具“造形家”:地理场景三维化的高效解决方案
unity·glb·ai算法·ai三维建模工具·地图框选·造形家·城市建筑模型
会思考的猴子10 天前
Unity VFX 属性 Postion 和 TargetPostion
unity
hai31524754310 天前
九章编程法 · 猜数字游戏 (GW-BASIC 重构版) *
人工智能·microsoft·游戏引擎·游戏程序
心前阳光10 天前
Unity资源导入之自动化资源导入
unity·自动化·游戏引擎
心前阳光10 天前
Unity之2021.3.45f2c1发布安卓程序遇到的问题
android·unity·游戏引擎
纪纯10 天前
PicoVR Unity Integration SDK 3.4 常用交互API
unity·游戏引擎·vr·pico
龙智DevSecOps解决方案10 天前
3A 游戏优化技术栈:如何打通引擎级分析工具与 DevOps 持续集成管线?
unity·性能优化·游戏开发·技术美术·perforce·unrealengine
葛兰岱尔10 天前
从 SolidWorks 到 Three.js,从 Inventor 到 Unity——制造业CAD模型“几何-语义一体化“转换,不再是天方夜谭!
开发语言·javascript·unity
鼎艺创新科技10 天前
三维电子沙盘中OSGB倾斜摄影数据的加载与渲染
游戏引擎·cocos2d