不同于全局光照
我的Blog:
我的Blog:
球谐函数近似环境光漫反射的问题:
如何解决??引入了PRT。
PRT将Lighting部分拆成球面谐波基函数
L ( i ) ≈ ∑ l i B i ( i ) L(i)\approx \sum l_iB_i(i) L(i)≈∑liBi(i)
将light transport部分进行预计算,出射方向已知的情况下,light transport也可以展开维一个球面谐波函数。
V ( i ) ρ ( i , o ) m a x ( 0 , n ⋅ i ) ≈ ∑ t i B i ( i ) V(i)\rho(i,o)max(0,n\cdot i)\approx \sum t_iB_i(i) V(i)ρ(i,o)max(0,n⋅i)≈∑tiBi(i)
疑问:light transport与o(出射方向)无关,是不是代表着摄像机不可以转动?
疑问:那什么是不可以动的?
疑问:如果不变换环境光,是不是可以将 light transport 项和 lighting 项直接计算好值保存在着色点。这不就是给每个着色点预计算了所有的光照颜色吗?
如果BRDF为常量,PRT可近似为如下函数,我们将光照与Visibility拆成两个积分分别计算(注意:这里并不是数学上严谨的,而是一种近似)
得到结果:
L ( o ) ≈ ρ ∑ l i ∫ Ω B i ( i ) V ( i ) m a x ( 0 , n ⋅ i ) d i L(o)\approx \rho \sum l_i \int_{\Omega} B_{i}(i)V(i)max(0,n\cdot i)di L(o)≈ρ∑li∫ΩBi(i)V(i)max(0,n⋅i)di
这里将光照的球谐函数留在了Visibility项中
∫ Ω B i ( i ) V ( i ) m a x ( 0 , n ⋅ i ) d i \int_{\Omega}B_{i}(i)V(i)max(0,n\cdot i)di ∫ΩBi(i)V(i)max(0,n⋅i)di
这里Light Transport项乘以一个基函数的积分,就是Light Transport的函数投影到基函数上的系数,这个系数可以预计算。
而预计算的结果就是Basic Function给数量的数字。即: ∫ Ω B i ( i ) V ( i ) m a x ( 0 , n ⋅ i ) d i \int_{\Omega}B_{i}(i)V(i)max(0,n\cdot i)di ∫ΩBi(i)V(i)max(0,n⋅i)di为一个预计算的常数
优点:光源可以切换,只要光源被预计算过
问题:场景中所有预计算过的东西都不能动
注意:这里是每一个 Shadering Point,也就是说,对于每一个着色顶点都要记录一串球谐函数展开的可见性系数(一般存储25个数,也就是5阶;更高的阴影精度需要存储更高阶的系数)
PRT既可以解决阴影问题,还可以解决Glossy的BRDF的问题。
将大量的渲染时间放在渲染之前,在渲染时只需要获取数据进行简单计算就好。该算法在2002年那个年代,就可以做到100帧的运行速率,可以说速度是非常快的。
Diffuse材质中提到,Light Transport项与出射方向无关,故是一个二维函数。
但Glossy物体BRDF不仅仅与入射角度有关,还与出射角度有关。也就是说它是一个4维的函数。
这里的i被预计算了,计算结果为 l i l_i li, T i ( o ) T_i(o) Ti(o)为预计算的与o有关的函数
然后我们将计算得到的 T i ( o ) T_i(o) Ti(o) 投影到关于 o o o 的球谐函数上。
最终我们可以得到一个球谐函数的系数矩阵!!!
计算出射光照公式变为
将 L L L提出来得到
∑ i ( ∑ j t i j B j ( o ) ) L i \sum_i \left( \sum_j t_{ij}B_j(o) \right)L_i i∑(j∑tijBj(o))Li
我们已知,再Diffuse下,一个着色点保存了可见性函数的球谐函数系数。
而在Glossy下,一个着色点保存了与o有关的系数计算矩阵。
入射光照球谐系数与BRDF可见性矩阵相乘得到的向量 ∑ l i t i j \sum l_it_{ij} ∑litij,即为关于 o o o 的球谐函数的系数列表。
再将该系数与关于 o o o的基函数相乘求和,得到以o为出射角度的环境光镜面反射!
如果环境光照不变,我们可以将 light 项和 transport matrix项 直接计算好,得到一个关于o的基函数系数!
一般情况下,人们会使用3/4/5阶球谐基函数去近似。因此一个像素点需要存储 81/256/625 个系数
5万网格数,在2.2GHZ P4,ATI Radeon 8500上有3.6fps。
在现代GPU上,运行到100帧以上是没有问题的。
当金属度很高,反射接近于镜面时,PRT便解决不了这个问题了。
但到此为止,做的也仅仅是环境光照,直接光照的一种形式,而并不是有间接光照的全局光照。
经过了第一次的预计算,现在每一个着色点都记录了BRDF&visibility项在球谐函数下的展开系数,我们可以通过将着色点这些着色点作为次级光源再次预计算。
若我们将直接光照的计算表示为 L 1 L_1 L1:
L 1 ( x , ω ⃗ o ) = L e ( x , ω ⃗ o ) + ∫ Ω L ( x ′ , ω ⃗ i ) ρ ( x , ω ⃗ i , ω ⃗ o ) V ( x , x ′ ) G ( x , x ′ ) d ω ⃗ i L_1\left(x, \vec{\omega}_{o}\right)=L_{e}\left(x, \vec{\omega}_{o}\right)+\int_{\Omega} L\left(x^{\prime}, \vec{\omega}_{i}\right) \rho\left(x, \vec{\omega}_{i}, \vec{\omega}_{o}\right) V\left(x, x^{\prime}\right) G\left(x, x^{\prime}\right) d \vec{\omega}_{i} L1(x,ωo)=Le(x,ωo)+∫ΩL(x′,ωi)ρ(x,ωi,ωo)V(x,x′)G(x,x′)dωi
那么光线弹射一次得到的次级光照 L 2 L_2 L2计算即为
L 2 ( x , ω ⃗ o ) = ∫ Ω L 1 ( x ′ , ω ⃗ i ) ρ ( x , ω ⃗ i , ω ⃗ o ) ( 1 − V ( x , x ′ ) ) G ( x , x ′ ) d ω ⃗ i L_2\left(x, \vec{\omega}_{o}\right)=\int_{\Omega} L_1\left(x^{\prime}, \vec{\omega}_{i}\right) \rho\left(x, \vec{\omega}_{i}, \vec{\omega}_{o}\right) (1-V\left(x, x^{\prime}\right) )G\left(x, x^{\prime}\right) d \vec{\omega}_{i} L2(x,ωo)=∫ΩL1(x′,ωi)ρ(x,ωi,ωo)(1−V(x,x′))G(x,x′)dωi
而次级光照中,被照射的点为变为单个着色点,光源变为着色点周围可能会弹射直接光照的片元。
注意这里的差别:
L 2 L_2 L2中的visibility项变为了 1 − V ( x , x ′ ) 1-V(x,x') 1−V(x,x′)
这是因为次级光源正是来自那些被遮挡的部分。
本块内容参照了PRT完整讲解 https://zhuanlan.zhihu.com/p/609597945
并在其基础上 增加了 对于 Glossy物体 的 间接光反射 计算!
一些解决方法
将任意一个二维函数投影到小波对应的基函数上,可以发现大量的基函数的系数接近0.
这样我们就可以选取基函数中系数最大的多少个,做到有损压缩。
与SH(Spherical Harmonics )最大的区别是小波支持全频率的表示,既可以表示低频,也可以表示高频。
小波变换,对CubeMap中的每一个图单独做变换,将高频的信息留在周围三个区块,低频的东西留在左上图中。
然后对左上的图继续做小波变换,将高频取出,低频留在左上
相同的存储量,小波可以得到更好的高频信息。
代价:小波不支持快速的旋转,不可以旋转光照。
在实时全局光照中,一般指光线弹射两次的光照,即直接光照和一次的间接光照。
具体内容参照之后专题: