Unity间接光 ibl(基于图像的渲染)和SH(球谐光照)

博客介绍了间接光的实现与ibl和SH相关,基于环境贴图cubemap渲染及球谐光照简化环境光。间接光用BRDF方程需解积分,还给出间接光漫反射公式。普遍将cubemap预处理成贴图,Unity已处理好并存储相关参数,可调用函数计算,最后得出间接光漫反射结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://zhuanlan.zhihu.com/p/68025039

 

间接光

间接光的实现与ibl(基于图像的渲染)和SH(球谐光照)这两个名词分不开。基于图像的渲染已经是很大的一个体系了,在这里特指基于环境贴图cubemap对表面进行渲染。球谐光照实际上就是将周围的环境光采样成几个系数,然后渲染的时候用这几个系数来对光照进行还原,这种过程可以看做是对周围环境光的简化。这两者在后面的实验中都会被用到。

间接光部分使用的也是和直接光相同的BRDF方程,不同之处在于BRDF加一加就好,而这里真的要解积分。。。总的公式如下:

间接光漫反射

拆分出的间接光漫反射公式如下:

后面那个积分看起来很吓人,想看解法的话《 Real-time Rendering》上有,我这里只谈实现。在Shader里每帧做积分显然是不现实的,普遍的做法是把采样得到的cubemap预处理成一张贴图,就像下图这样:

预处理过程如果想手写的话可以看OpenGL的实现,而作为一个成熟的引擎Unity已经帮我们把cubemap处理好存起来了。Unity里有这么一组变量:

// SH lighting environment
    half4 unity_SHAr;
    half4 unity_SHAg;
    half4 unity_SHAb;
    half4 unity_SHBr;
    half4 unity_SHBg;
    half4 unity_SHBb;
    half4 unity_SHC;

这里存的是积分后用球谐函数编码的全局光照。即Unity做的事情为:先将环境贴图cubemap积分成模糊的全局光照贴图,再将全局光照贴图投影到球谐光照的基函数上存储,这里的七个参数即为存储的基函数的系数。Unity用的基函数叫三阶的伴随勒让德多项式,式子的参数如下所示:

unity_SHA的三个系数存储的是l=1时的参数,unity_SHB存储的是l=2时的第1,2,4个参数,unity_SHC单独存储(m=2,l=2)时的最后一个参数。(l=0,m=0)和(l=2,m=0)的系数代表的光照数据影响太小被Unity舍弃掉了。

公式挺吓人,但实际上每个参数表示的都是球面上某一部分的光照,如图:

具体的计算代码见UnityCG.cginc,在这里直接调用其中的ShadeSH9函数。此函数传入归一化的法线,返回的即为重建的积过分的环境光照信息。

half3 ambient_contrib = ShadeSH9(float4(i.normal, 1));

float3 ambient = 0.03 * Albedo;

float3 iblDiffuse = max(half3(0, 0, 0), ambient.rgb + ambient_contrib);

float kdLast = 1;

float3 iblDiffuseResult = iblDiffuse * kdLast * Albedo;

第二行往后的代码都很容易理解。ambient是环境光影响不大,随便设个很暗的值就行。这样得到的iblDiffuse就是方程中积分部分的值,乘上kd乘上Albedo即为间接光漫反射的结果,此处的kd和上面的kd不一样需要重新计算,先设成1。注意这里和直接光部分一样没有对颜色除PI。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值