欢迎光临散文网 会员登陆 & 注册

【图形学笔记】实时范围光Area Light渲染及其数学原理推导

2023-06-16 11:48 作者:小豆子zyq  | 我要投稿

引言

    在灯光渲染中,点光、平行光和聚光灯的实现较为容易,原因是要么光源为一个定点或者光线方向恒定。但范围光Area Light四面八方的光源来自连续的表面,实现方法有本质上的不同。对于离线渲染可以通过路径追踪(蒙特卡洛积分)暴力解算,但是在实时渲染中需要更为巧妙的方式实现。

Sponza scene illuminated by a textured, rectangular area light. [1]

    前几天我和同学复刻了一下基于LTC (Linear Transformed Cosines) 的实时范围光渲染,所以打算写一篇笔记分享一下学习过程。教程[3]和文献[1][4]来源会放在文末的引用中。如果笔记内容有误请多多指正

前置知识

    前置知识涉及部分辐射计量学、渲染方程以及简易积分。我当时由于这部分基础不太牢(学的不系统),在后续的数学推导中浪费了很多时间去补充,所以这个部分我尽量写细一些。


立体角

    用于描述一个立体方位和辐照积分的积分域,通常用ω表示,而θ和φ(或者α)可以看做是空间极坐标系中两个用于描述方位的角度。需要注意的是θ是法向和特定方向的夹角,而不是特定方向和水平圆面的夹角,这个定义会影响后续积分时的表达。

立体角和方位角的符号定义 [2]

值得一提的是,对于立体角的球面积分的过程为:

%5Cvcenter%7B%5Cint_%5COmega%20d%5Comega%3D%5Ciint%5Csin%5Ctheta%20d%5Ctheta%20d%5Calpha%3D2%5Cpi%5Ccdot%20(%5Csin(%5Cfrac%5Cpi2)-%5Csin(-%5Cfrac%5Cpi2))%3D4%5Cpi%7D

  • 所以d%5Comega可以理解为在单位球面上的面积微元,其与两个方位角的微分关系为d%5Comega%3D%5Csin%5Ctheta%20d%5Ctheta%20d%5Calpha

  • 通过计算球面某一区域的面积即可求得该面积所对应的立体角

辐照度 Irradiance

这个物理量我感觉是PBR中最总要的一个,其定义为:

E%3D%7B%5Cfrac%20%7B%5CPhi%5Ccos%5Ctheta%7D%20%7BA%5E%5Cperp%7D%7D

  • %5CPhi辐射通量,在图形学中一般表示为光的亮度(vec3,0%5Cto%2B%0A%5Cinf

  • %5Cfrac%7B%7BA%5E%5Cperp%7D%7D%7B%5Ccos%5Ctheta%7D受光面积,其中%7BA%5E%5Cperp%7D正对面积%5Ccos%5Ctheta的作用是将受光面积转换为正对面积

特别的是,对于辐照度半球积分,假设任意方向的辐照度都为1

%5Cvcenter%7B%5Cint_%7B%5COmega%5E%2B%7DEd%5Comega%3D%5Cint_%7B%5COmega%5E%2B%7D%5Ccos%5Ctheta%20d%5Comega%3D%5Ciint%5Ccos%5Ctheta%5Csin%5Ctheta%20d%5Ctheta%20d%5Calpha%3D2%5Cpi%5Cint%20%5Cfrac12%5Csin2%5Ctheta%20d%5Ctheta%7D%3D%5Cpi

所以在图形学中辐照度积分都要除以π来归一化

I%3D%5Cfrac1%5Cpi%5Cint_%7BS%7D%20%5Ccos%5Ctheta%20d%0A%5Comega%EF%BC%8CS%5Csubseteq%5COmega%5E%2B


渲染方程

L_o(%5Comega_o)%3D%5Cint_%7B%5COmega%5E%2B%7Df_r(%5Comega_o%2C%5Comega_l%2Cn)L_i(%5Comega_l)%5Ccdot(%5Comega_l%5Ccdot%20n)%5Ccdot%20d%5Comega_l%20

  • 一定程度上,出射光线等于无数条入射光线的加权和,其中BDRF函数(f_r)就代表着出射光和某一条入射光的比例关系,我认为这是实现Area Light的核心思想之一

根据光路可逆,左边的可以理解为出射光,右侧的几根为入射光,球面函数为权重 [1]


范围光

    在给定视角方向(需要求出出射光线的方向)、法线方向。现在需要做的就是在范围光的光源(也就是自发光多面体)上进行加权采样,最后求得该出射光方向上的光线。

BRDF即渲染方程中的fr,也就是一定程度上的权重 [1]


积分转化

    很明显,在实时渲染中无法对几何体进行采样,也无法让BRDF和几何体的球面投影进行卷相乘,因为时间复杂度太大了。不过学者[1][4]提出了一种很牛的思路,将几何体面采样转换为有限的边缘求和(积分)


投影变换 [4]
  • 某N变形几何体的球面投影(传统积分的对象)为S_%5COmega

  • 其球面投影在圆盘面C上的投影为S_C%0A%0A

其二者的换算关系为

S_%5COmega%5Ccdot%5Ccos%5Ctheta%20%3DS_C%2C~dS_%5COmega%5Ccdot%5Ccos%5Ctheta%3DdS_C

  • 这个换算过程可以理解为投影,跟辐照度中正对面积%5Cvcenter%7B%5Ccos%5Ctheta%7D%0A是一个原理

于是神奇的事情发生了,通过积分换底(Jacobian),从原来的球面立体角的面积变成了投影的面积

I%3D%5Cfrac1%5Cpi%5Cint_%7BS_%5COmega%7DEd%5Comega%3D%5Cfrac1%5Cpi%5Cint_%7BS_%5COmega%7D%5Ccos%5Ctheta%20d%5Comega%3D%5Cfrac1%5Cpi%5Cint_%7BS_C%7Dd%5Csigma%3D%5Cfrac%7B%20S_C%7D%5Cpi


边缘积分

接下来的任务就是计算多面体在球面的投影在圆盘的投影的面积

signed sum [4]

这部分的操作是逐边缘计算有符号子面积然后求和。给出任意两个圆心指向顶点的向量,公式为:S'%3DS%5Ccdot%5Ccos%20%5Ctheta%3D%5Cfrac12%5Calpha%5Ccdot%20r%5Ccdot%5Ccos%20%5Ctheta%5C%5C%0A%5Calpha%20%3D%20%5Carccos(%5Cvec%20v_1%20%C2%B7%20%5Cvec%20v_2)%5C%5C%0A%5Ccos%5Ctheta%3Dn%5Ccdot%5Cfrac%7B%5Cvec%20v_1%20%C3%97%20%5Cvec%20v_2%7D%7B%5C%7C%5Cvec%20v_1%20%C3%97%20%5Cvec%20v_2%5C%7C%7D

相当于先求出一个完整的圆弧(两个顶点矢量和球面上的圆弧组成)的面积,然后投影回圆盘

所有边的积分式为:

I%3D%5Cfrac%201%5Cpi%5Csum%5Cfrac12%5Carccos(%5Cvec%20v_i%20%C2%B7%20%5Cvec%20v_j)%5Ccdot(n%5Ccdot%5Cfrac%7B%5Cvec%20v_i%20%C3%97%20%5Cvec%20v_j%7D%7B%5C%7C%5Cvec%20v_i%20%C3%97%20%5Cvec%20v_j%5C%7C%7D)


LTC Linearly Transformed Cosines

Learn OpenGL CN没有翻译这篇文章,我也没找到中文翻译。大致意思是由多种线性变换一个半球余弦分布函数集合。

原始权重分布函数Do [1]

假设我们的范围光是均一的,辐射通量%5CPhi为定值,则积分公式:

I%3D%5Cfrac1%5Cpi%5Cint_%7BS_%5COmega%7DEd%5Comega%3D%5Cfrac%5CPhi%5Cpi%5Cint_%7BS_%5COmega%7D%5Ccos%5Ctheta%20d%5Comega%3D%5Cfrac%7B%5CPhi%20S_C%7D%5Cpi

其中不难看出这个积分(加权和)所采用的权重分布函数D_o%0A为上图中的第三种,Clamped Cosine(正半球余弦分布)

D_o(%5Comega_o)%3D%5Cfrac1%5Cpi%5Ccos%5Ctheta_o%0A

  • 其中的%5Cfrac1%5Cpi同样是为了保证权重的半球积分结果为1

线性变换

    很明显,现在的求和方式仅能针对粗糙度为0的情况,来自自发光多边形的入射光全部以漫反射发射出去,为了模拟BRDF对于粗糙度变化、视角变化(甚至材质各向异性变化),需要将初始权重分布函数D_o%0A应用一个三乘三线性变换矩阵去拟合入射光和反射光在不同材质和摄像机角度下的权重分布。这也就是这个技术中“Linearly Transformed”的含义

变化过程可视化 [1]

由此一来,对入射光的权重分布函数D%0A将获得近似BRDF的权重分布,即:

D(%5Comega_o)%3DD_o(M%C3%97%5Comega_o)%5Capprox%20f_r(%5Comega_o)%5Ccdot%5Ccos%5Ctheta_o

  • 这里顺便把渲染方程中的%5Cvcenter%7B%5Ccos%5Ctheta%7D%0A一起乘上了,毕竟是权重分布而不是简单地BRDF分布

拟合情况 [1]


但是根据边缘积分公式的推导,边缘积分仅适用于D_o的分布情况,所以在渲染中要将自发光多面体进行M%5E%7B-1%7D变换。从而计算边缘积分,这步非常重要。

将D变换回Do,将同样过程应用在多面体上 [1]


最终的渲染方程就是

I%3Dk_d%5Cint_PD_o(%5Comega)d%5Comega%2Bk_s%5Cint_%7BM%5E%7B-1%7D%C3%97P%7DD_o(%5Comega)d%5Comega

  • 其中第一项是漫反射项,第二项是高光项

  • k_dk_s是典中典之菲涅尔过渡,k_d%2Bk_s%3D1%2C~k_s%3DF

  • P%0A是指自发光多面体(Polygonal Light)展开的话就是

%5Cint_PD_o(%5Comega)d%5Comega%3D%5Cfrac%201%5Cpi%5Csum_%7B%5Cvec%20v_i%2C%5Cvec%20v_j%5Cin%20P%7D%5Cfrac12%5Carccos(%5Cvec%20v_i%20%C2%B7%20%5Cvec%20v_j)%5Ccdot(n%5Ccdot%5Cfrac%7B%5Cvec%20v_i%20%C3%97%20%5Cvec%20v_j%7D%7B%5C%7C%5Cvec%20v_i%20%C3%97%20%5Cvec%20v_j%5C%7C%7D)


关于三乘三矩阵

将粗糙度变换、各向异性变换、摄像机角度变换,三个三乘三矩阵依次相乘即可得出用于拟合BRDF的变换矩阵,即

M_v%C3%97M_a%C3%97M_r%3DM%3D%5Cbegin%7Bvmatrix%7D%0Aa%260%26b%5C%5C%0A0%26c%260%5C%5C%0Ad%260%261%0A%5Cend%7Bvmatrix%7D

又因为a,b,c,d的具体数字只与两个变量有关:粗糙度、摄像机与法线的夹角。那么接下来就是典中典之查表环节了。将abcd分别对应像素的RGBA,横纵坐标分别为粗糙度(在论文中为了粗糙度变化平滑,采用%5Csqrt%7Br%7D作为粗糙度轴)和摄像机与法线的夹角。即可存储为一张LUT,在渲染的时候以读取纹理的形式构建变换矩阵


效果


论文中的效果 [1]
我和同学实现的效果

其他三维软件中的Area Light大多以矩形和椭圆形为主,但是论文和教程中使用的技术远远打过如此。LTC可以解决任意面数任意形态的自发光光源,并且支持灯光贴图


关于灯光贴图

这部分还没实现,大致思路是对贴图先进行预积分,跟IBL一样,然后根据灯光距离和表面粗糙度进行线性插值(大概)


实现方法

详见Learn OpenGL网站[3],里面有详细的代码实现和更全面的文献资料。

特别特别感谢大佬同学帮我在渲染器里实现了范围光,GitHub@theta-lin


引用

  • [1] Real-Time Polygonal-Light Shading with Linearly Transformed Cosines, ACM Siggraph '16 

  • [2] Understanding the concept of Solid Angle, ENGINEERING STREAMLINED (Youtube)

  • [3] Area Lights, LearnGL guest articles 2022 

  • [4] Geometric Derivation of the Irradiance of Polygonal Lights, Eric Heitz


【图形学笔记】实时范围光Area Light渲染及其数学原理推导的评论 (共 条)

分享到微博请遵守国家法律