PBR PRT 球面谐波函数

1,247 阅读3分钟

SpiderGL - CubeMap with Spherical Harmonics (cnr.it)

Spherical Harmonics Array - PLAYCANVAS

Mike Lodato's Blog - Spherical Harmonics Lighting: Part II (zvxryb.github.io)

(8条消息) PRT算法介绍_子宽的专栏-CSDN博客

PRT(precomputed radiance transfer)

  • 在PRT之前,实时渲染的一大难题就是解决阴影和互反射问题
    • 主要难点在于这些物理现象要求对每个点的半球面求解入射光线的积分(渲染方程)
  • PRT算法的核心有两个
    • 将环境光照用基底编码,如球谐光照方法;
    • 将入射光映射为包含阴影、反射等信息的transferred radiance,预先计算、存储起来,在实时渲染时将其直接应用到实时光照上

公式

  • 第一步,它把BRDF干掉,变成纯diffuse,再把积分变成根据visibility的叠加。也就是: [公式]
  • 第二步,把L_i和V(omega dot n)都表达成SH,就成了 [公式]
  • Li项只和环境光有关,V项只和mesh有关。所以两个分别预计算,在运行时sum一下就行了。
  • 解决实时渲染的一大难题就是解决阴影和互反射问题

球谐光照

  • 球谐函数(spherical harmonics)是对定义在球面上的函数的分解,类似于傅里叶变换是对一维函数的分解一样。
  • 傅里叶变换将一维函数分解为不同频率的正弦函数的累加,而球谐函数将球面上的函数分解为一组(无穷多个)标准正交的基底的累加。
  • 因为环境光表示的是三维空间中各个方向上的光线,刚好可以看做是定义在球面上的函数,有了这一层“关系”,我们就可以利用球谐函数,将环境光参数化,既方便存储也方便使用。参数化的时候会有一个近似,
  • 绝大部分参数表示的都是高频光照,作用不是很大,可以忽略掉。
  • 对于常用的低频光照,3 ~ 5阶(9 ~ 25个)球谐系数就足够了。

漫反射部分

  • 直接光照L0,一次反射的间接关照L1... image.png
  • 直接光照 image.png image.png
  • 由于这里我们只考虑漫反射项,所以可以无视视角的影响,化简为:
  • V和H可以预计算 image.png image.png
  • Lenv Li 表示球谐系数 yi 表示球谐函数的基底 image.png
  • 进一步 image.png
  • 积分符号内部的所有项,包括pd, 带入最初考虑间接光照的渲染方程 image.png

镜面反射部分

  • 镜面高光往往在视角与平面法相接近的时候最强,垂直的时候最弱
  • 我们不如定义一个包含自遮挡、互反射项的,Lxfer即transferred incident radiance。其物理意义就是从点p向外看,看到的视角。 image.png
  • Lxfer的球谐系数跟Lenv的球谐系数线性相关,M是入射光,Lxfer然后跟BRDF和consine项相乘,得到出射光线 image.png

总结

  • 对漫反射可以用一个transfer vector M MM将入射光线(的球谐光照系数)转化为出射光线;
  • 对一般情况(或者说是高光部分),可以用一个transfer matrix M \mathcal{M}M将入射光线(的球谐光照系数)转化为包含自遮挡、互反射的transferred incident radiance。

实时渲染过程

  • 流程如下:
    • 根据入射光线,计算对应的球谐系数;
    • (如果需要)旋转入射光线的球谐系数;
    • 利用transfer vector/matrix对入射光线进行变换,计算出射光线;
    • 对于镜面反射,还需要乘上BRD项和其他与视角有关的项,得到最终结果;