实时全局光照技术(一)——开篇

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

写在前面

20230115143833.jpg
上图是计算机图形学领域里一篇经典论文的“预告图(teaser image)”预告图通常是论文的结晶放在开头用来吸引读者的。一些读者看到这张图片可能会想“这张照片有什么吸引人的”但是如果我说这不是照片而是由计算机渲染出来的图片呢
计算机图形学论文的预告图一般是由论文中提出的技术渲染出来的上图也不例外但是它看起来太真实了细节非常丰富(图中有标明)简直可以以假乱真这种达到照片级别的渲染就是当下流行的真实感渲染(photorealistic rendering)要达到真实感渲染的效果整个渲染过程需要“符合”物理学原理所以我们也称它是基于物理的渲染(PBR — Physically based rendering)。
那么要如何做到 PBR 呢
我们都知道人之所以能看到五彩缤纷的世界是因为人眼能够感光成像光照到物体物体会吸收一部分光也会反射一部分光人眼接收到物体反射的光就是物体对外展示的色彩所以为了做到 **PBR **我们需要在计算机渲染中模拟这个过程。PBR 涉及的内容非常多为了便于理解我将 PBR 的要素简化提炼一下

  • 基于物理的光照
  • 基于物理的材质
  • 基于物理的渲染方法

我们认为全局光照就是基于物理的光照材质可以由基于物理的双向反射分布函数(BRDF)来表示基于物理的渲染方法当然就是大名鼎鼎的渲染方程(Render Equation)。
本系列文章将以实时全局光照为切入点来介绍不同时期人们提出的精妙的算法理论看看这些理论是如何解渲染方程的最后还会介绍虚幻引擎(UnrealEngine)中的全局光照背后是如何应用这些算法的。
本篇是实时全局光照技术的开篇将介绍全局光照的概念怎么理解实时全局光照中的“实时”本系列文章主要介绍的是光照相关的技术理论但是避免不了牵涉 BRDF 和 Render Equation 相关内容所以在进入系列篇章之前我会对这些内容做一些简单介绍可以作为前置阅读资料也可以在后面的篇章中遇到了再回头来看。

全局光照

在这里插入图片描述

上图其实也不是真实照片而是由计算机渲染出来的 3D 场景图片但是看上去非常真实对不对。我们再来看看下面这张图片
image.png
这张图片看起来也不错不过总感觉缺有点违和问题出在哪里呢
我们可以注意一下两个图中标注出来的 p 点图2中的 p 点明显要暗上许多(其实是纯黑色的)我们再仔细观察下其他没被“阳光”直射的地方都非常暗这显然不符合物理规律。图1 就好很多p 点和其他未被光源直射的点虽然会暗一些但并非纯黑色而是有一定的亮度造成这个区别的原因就在光照上图1 应用了全局光照(Global Illumination)而图2 只有直接光照(Direct Illumination)。

**注**光源直接照射到物体表面被称为直接光照被光源直接照射的物体表面再照亮其他物体被称为间接光照(Indirect Illumination)而全局光照则是直接光照和间接光照的叠加Global Illumination(GI) = Direct Illumination + Indirect Illumination

实时全局光照

我们知道了全局光照可以带来非常真实的渲染效果而本文的主题是实时全局光照(Realtime GI)这个实时要怎么理解呢
在计算机图形学中一般大于 30FPS 的渲染被称为实时渲染10FPS 左右的我们称为可交互渲染再慢的就是离线渲染。离线渲染主要用于电影行业一般可以通过 Monte Carlo Path Tracing 等算法达到非常接近现实世界的效果我们甚至可以认为它就是 Ground Truth(基准真相) 。电影级别的离线渲染一帧可能需要渲染几个小时甚至几天而实时渲染要求一帧至少要在 1/30 秒(约 30ms)内完成可见要做到高质量实时渲染(既有优质的渲染效果并且要做到实时)的挑战有多大。
实时全局光照就是高质量实时渲要解决的一大挑战本文会带大家领略一下在实时全局光照研究方向上一些鼎鼎大名的算法同时也会介绍其中一些算法在 UnrealEngine 中是怎么应用的。
上面提到 Global Illumination = Direct Illumination + Indirect Illumination Indirect Illumination(间接光照)我们前面讲过本质上是由非光源反射的光带来的照明我们可以想象一下由间接光照照亮的物体是不是还会照亮其他物体只要被照亮的物体说明他们都对外反射了光线这些光线又会照亮其他物体物体之间还会存在相互照亮的情况现实世界的光照反射实在是太复杂了我们需要先做一个抽象的定义再根据定义来解决问题。

间接光射出的光线打到物体后直接反射到人眼我们称为一次弹射(one-bounce)如果间接光在场景中经过多次反射再进入人眼我们称为多次弹射(multi-bounce)。

我们可以做如下定义N-bounce global illumination = Direct illumination + N-bounce Indirect Illumination即一次弹射的全局光照等于直接光照加上一次弹射的间接光照同样的多次弹射的全局光照等于直接光照加上多次弹射的间接光照。
根据上面的定义我们再来对比下面的几张图片
image.png
我们可以看到 Direct Illumination 和 One-bounce Global Illumination 的差别非常大
而 One-bounce 和 Two-bounce 还有 Sixteen-bounce global Illumination 的差别已经不那么明显了。
我们前面讲过在电影行业中通过离线渲染一帧需要几小时甚至几天时间其实就是用到了 Multi-bounce Global Illumination。每多一次 bounce 带来的计算量是指数级增长的渲染时间也会大大延长这在实时渲染中是不能接受的而我们又发现 One-bounce GI 虽然没有那么真实但效果也还不错所以我们第一个大胆的近似就来了在 Real-time GI 中我们只处理 One-bounce Global Illumination(Direct Illumination + One-bounce Indrect Illumination)。

在实时渲染领域由于硬件的限制和对时间的极致要求通过近似(approximate)去表达真实的方法会很常见有时候人们会根据观察提出假设来近似有时候会通过数学中的不等式或约等式来近似。

系列篇章

限于篇幅实时全局光照技术会拆为下面几个篇章分别介绍

  • 直接光照介绍光源、环境光(Environment Light不是指 AO(Ambient Occlusion) 中的环境光)的概念以及在实时渲染领域如何带入渲染方程进行计算
  • 间接光照从 RSM(Reflective Shadow Map) 开始介绍一些在实时渲染领域有名的间接光照算法原理和优缺点
  • 阴影有光的地方就有阴影阴影篇章会介绍常见的阴影生成算法
  • UnrealEngine 中的光照技术最后我会介绍一下在虚幻引擎中是如何应用前文提到的算法

直接光照

TBD

详见《[WIP]实时全局光照技术(二)——直接光照

间接光照

详见《[WIP]实时全局光照技术(三)——间接光照

阴影

TBD

详见《[WIP]实时全局光照技术(四)——阴影渲染

UnrealEngine 中的光照技术

TBD

详见《[WIP]实时全局光照技术(五)——UnrealEngine 中的光照技术

PBR 理论资料

本章节作为实时全局光照技术的补充阅读资料可以在后续篇章中遇到了再回来查阅。

辐射度量学 Radiometry

PBR 需要用到基于物理的光照我们首先要把光照通过数学表达出来这里我们用到了辐射度量学的一些概念。

辐射通量 Radiant Flux

我们都知道光照是一种能量(energy)能量用 Q 表示单位是焦耳(joule)但是在图形学中我们一般不用能量来描述光照而是用到了辐射通量或者辐射功率这个概念它是单位时间的能量(joules per second)辐射通量用 Φ 表示单位是 W(atts)也就。其公式定义为
Φ = d Q d t Φ = \frac{dQ}{dt} Φ=dtdQdt 表示单位时间。

辐射强度 Radiant Intensity

辐射强度是单位立体角的辐射通量用 I 表示单位是 candela 辐射通量我们知道再来看看立体角的定义。

立体角定义

image.png
以观测点为球心构造一个单位球面任意物体投影到该单位球面上的投影面积即为该物体相对于该观测点的立体角。因此立体角是单位球面上的一块面积这和“平面角是单位圆上的一段弧长”类似。

立体角公式

球坐标系中任意球面的极小面积为
d A = ( r s i n θ d φ ) ( r d θ ) = r 2 ( s i n d θ d φ ) dA=(rsinθdφ)(rdθ)=r^2(sindθdφ) dA=(rsinθdφ)(rdθ)=r2(sindθdφ)
因此极小立体角单位球面上的极小面积为
d Ω = d A r 2 = s i n θ d θ d φ dΩ=\frac{dA}{r^2}=sinθdθdφ dΩ=r2dA=sinθdθdφ
所以立体角是投影面积与球半径平方值的比这和“平面角是圆的弧长与半径的比”类似。 对极小立体角做曲面积分即可得立体角
Ω = ∫ ∫ S d Ω = ∫ ∫ S s i n θ d θ d φ Ω=\int\int_SdΩ=\int\int_Ssinθdθdφ Ω=SdΩ=Ssinθdθdφ
知道了立体角和辐射通量我们可以得出辐射强度的公式表达为
I = d Φ d w I = \frac{dΦ}{dw} I=dwdΦdw 表示单位立体角。

辐照度 Irradiance

辐照度是单位面积的辐射通量用 E 表示单位是 W·m−2 。公式表达为
E = d Φ d A E = \frac{dΦ}{dA} E=dAdΦdA 表示单位面积。

辐射率 Radiance

辐射率是单位面积单位立体角的辐射通量用 L 表示单位是 W·sr−1·m−2 。公式表达为
L = d Φ d A d w = E d w = I d A L = \frac{dΦ}{dAdw}=\frac{E}{dw}=\frac{I}{dA} L=dAdwdΦ=dwE=dAI

双向反射分布函数 BRDF(Bidirectional Reflectance Distribution Function)

BRDF 的定义是反射光和入射光的比例前面我们学习了光照的数学表示那么 BRDF 我们也可以通过公式表达出来了 f r = d L o d E i fr=\frac{dL_o}{dE_i} fr=dEidLo其中 fr 就是 BRDF d L o dL_o dLo表示出射光 Radiance d E i dE_i dEi表示入射光 Irradiance。
双向反射分布函数是用于描述物体表面材质的这里的双向指的是视线方向和光照方向也就是上面渲染方程的示意图中标注的 w o w_o wo w i w_i wi下面我们用实际的例子来看看为什么物体的材质跟 w o w_o wo w i w_i wi有关联。
如果视线方向和光照方向我们都不考虑那么看到物体就会感觉非常平(面)没有立体感就像这样
image.png
我们把光照对物体表面颜色的影响加上看看我们得先知道光照是怎么影响物体表面颜色的。

兰伯特余弦定理

人们观察发现在现实世界里同一个物体不同的位置的明暗程度是不一样的如果光源被移动了物体的明暗位置也会随之改变人们很早就在素描中用到了这个发现。著名的兰伯特余弦定理( Lambert’s cosine law )给出了理想漫反射模型下 BRDF 的数学计算推导兰伯特余弦定理假设没有光照能量损耗所有光照都被均匀反射我们把出射光也可以类比成半球面上所有方向的入射光因此在半球面积分时也需要考虑出射光与法线的夹角即 ∫ Ω + L o c o s θ o d w o = d E i c o s θ i \int_{Ω^+}L_ocosθ_odw_o=dEicosθ_i Ω+Locosθodwo=dEicosθi注意等式两面的 θ θ θ不同 θ o θ_o θo表示出射光方向 θ i θ_i θi表示入射光和法线的夹角我们带入到 BRDF 的基本公式中可得 f r = d L o d E i c o s θ i = d L 0 ∫ Ω + d L 0 c o s θ o d w o = 1 ∫ Ω + c o s θ o d w o fr=\frac{dL_o}{dEicosθ_i}=\frac{dL_0}{\int_{Ω^+}dL_0cosθ_odw_o}=\frac{1}{\int_{Ω^+}cosθ_odw_o} fr=dEicosθidLo=Ω+dL0cosθodwodL0=Ω+cosθodwo1
前文提到立体角 d Ω dΩ dΩ的定义带入上述公式得 f r = 1 ∫ Ω + c o s θ o d w o = 1 ∫ 0 2 π ∫ 0 π 2 c o s θ o s i n θ o d θ o d φ fr=\frac{1}{\int_{Ω^+}cosθ_odw_o}=\frac{1}{\int_0^{2π}\int_0^{\frac{π}{2}}cosθ_osinθ_odθ_odφ} fr=Ω+cosθodwo1=02π02πcosθosinθodθodφ1
解一下三角函数积分可得 f r = 1 2 π ∫ 0 π 2 c o s θ o s i n θ o d θ o = 1 π ∫ 0 π 2 s i n 2 θ o d θ o = 1 π ( − c o s 2 θ o ∣ 0 π 2 2 ) = 1 π fr=\frac{1}{2π\int_0^{\frac{π}{2}}cosθ_osinθ_odθ_o}=\frac{1}{π\int_0^{\frac{π}{2}}sin2θ_odθ_o}=\frac{1}{π(-\frac{cos2θ_o|_0^{\frac{π}{2}}}{2})}=\frac{1}{π} fr=2π02πcosθosinθodθo1=π02πsin2θodθo1=π(2cos2θo02π)1=π1单位是 s r − 1 sr^{-1} sr1
我们把这个公式带入到渲染看看效果
image.png
兰伯特模型认为物体表面的明暗跟光线入射角度有关我们通过这个模型去做渲染已经能看到物体的立体感了。后来人们发现兰伯特模型的明暗变化太快了不符合直觉于是把 -1 到 1 的明暗色阶变成 0 到 1 的范围。
image.png
上面经过调整明暗色阶之后的模型叫做半兰伯特(Half-lambert)模型效果看上去会好不少。

Phong/Blnn-Phong 模型

不过我们发现这个模型没有办法去描述一些光滑的物体我们可以回想一下对于较为光滑的物体我们会看到一片明显高亮的区域这个区域也会随着人们的视角变化。因此人们在渲染模型中引入了视角方向比较出名的模型有冯(phong)模型和布林冯(blnn-phong)模型效果如下
image.png
phong 模型有漫反射和镜面反射两个部分漫反射部分还是使用兰伯特模型镜面反射部分则是根据入射光方向(lDir)在入射点法线方向(nDir)的镜面反射方向(rDir)和视角方向(vDir)的夹角计算得出。但是我们观察到不同物体的高亮区域的面积不同所以 phong 模型的镜面反射部分在出射光方向和视角方向的点乘运算外还加了一个乘方我们可以通过调整乘方的指数来控制高亮区域大小乘方的指数越大高亮面积越小反之则越大。具体公式如下
L 0 = k d L i c o s θ i + k s L i c o s n θ r v L_0 = k_dL_icosθ_i + k_sL_icos^nθ_{rv} L0=kdLicosθi+ksLicosnθrv

  • L o L_o Lo L i L_i Li分别表示出射光和入射光
  • k d k_d kd k s k_s ks分别表示漫反射系数和镜面反射系数
  • θ i θ_i θi表示 lDir 和 nDir 的夹角
  • θ r v θ_{rv} θrv表示 rDir 和 vDir 的夹角
  • n n n是 rDir 和 vDir 夹角余弦的乘方用于控制高亮区域的大小

使用 phong 或者 blnn-phong 模型我们通过调整 k d k_d kd k s k_s ks n n n能够实现不错的渲染效果。但是这几个参数都是根据人们的经验给出的并没有基于物理原理渲染结果自然也没那么真实。

微表面模型

直到后来有人提出微表面模型(microfacet model)微表面模型认为物体的表面是由非常多的微小的表面形成对于每个微表面我们认为它只会进行完美的镜面反射。物体表面的材质不同其微表面的法线分布(Distribution)也各不相同越光滑的物体表面它的法线分布越集中对应的微表面反射的光线也就越集中这就会形成我们看到的高光与之相反的是越粗糙的物体表面它的法线分布越分散其高光的面积也就越大对于非常粗糙的物体表面我们有时候都很难看到高光了。
基于微表面的模型我们不得不提一提 Cook-Torrance BRDFCook-Torrance BRDF 也分漫反射和镜面反射部分跟前面的 phong 模型一样漫反射和镜面反射根据材质不同有不同的系数 k d k_d kd k s k_s ks。漫反射部分沿用了 lambert 模型在镜面反射部分则基于物理规律分为了三项

  • F(Fresnel 项)光线入射方向不同其在物体表面发生反射和折射的比例也不一样一般情况下光线入射方向越接近物体表面物体呈现的反射越高。
  • D(法线分布函数)描述粗糙度对法线分布影响的函数
  • G(几何遮蔽函数)也和粗糙度相关越粗糙的物体光线在入射和反射过程中都可能会被凹凸不平的表面遮挡这可能会让物体显得更暗一些

其镜面反射部分具体公式如下
f r ( i , o ) c o o k − t o r r a n c e = F ( o , n ) G ( i , o , n ) D ( n , h ) 4 ( i ⋅ n ) ( o ⋅ n ) fr(i, o)_{cook-torrance} = \frac{F(o,n)G(i,o,n)D(n,h)}{4(i·n)(o·n)} fr(i,o)cooktorrance=4(in)(on)F(o,n)G(i,o,n)D(n,h)
我们前面提到的漫反射 k d k_d kd和镜面反射系数 k s k_s ks同样也由菲涅尔方程决定限于篇幅我后续会独立一片文章来介绍F、G、D项的推导过程以及金属度的引入缘由这里先直接给出实时渲染中常用的反射方程(简化的渲染方程)近似结果
L o ( x , w o ) = ∫ Ω + f r ( x , w i , w o ) L i ( x , w i ) c o s θ i d w i = ∫ Ω + ( ( 1 − m e t a l l i c ) b a s e C o l o r π + F ( o , n ) G ( i , o , n ) D ( n , h ) 4 ( i ⋅ n ) ( o ⋅ n ) ) L i ( x , w i ) c o s θ i d w i L_o(x, w_o) = \int_{Ω^+} f_r(x, w_i, w_o)L_i(x,w_i)cosθ_idw_i=\int_{Ω^+}((1-metallic)\frac{baseColor}{π}+\frac{F(o,n)G(i,o,n)D(n,h)}{4(i·n)(o·n)})L_i(x,w_i)cosθ_idw_i Lo(x,wo)=Ω+fr(x,wi,wo)Li(x,wi)cosθidwi=Ω+((1metallic)πbaseColor+4(in)(on)F(o,n)G(i,o,n)D(n,h))Li(x,wi)cosθidwi
基于 Cook-Torrance BRDF 后来又有一些有名的法线分布函数例如 Beckmann、GGX这些 NDF 让 BRDF 更加基于物理也能够渲染出更加真实的图片。

渲染方程 Render Equation

在辐射度量学部分我们知道了光的数学表达以及光的传播运算这些将在渲染方程的表示和求解中使用到。
image.png
L o ( x , w o ) = L e ( x , w o ) + ∫ Ω + f r ( x , w i , w o ) L i ( x , w i ) c o s θ i V ( x , w i ) d w i L_o(x, w_o) = L_e(x, w_o) + \int_{Ω^+} f_r(x, w_i, w_o)L_i(x,w_i)cosθ_iV(x,w_i)dw_i Lo(x,wo)=Le(x,wo)+Ω+fr(x,wi,wo)Li(x,wi)cosθiV(x,wi)dwi

  • L o ( x , w o ) L_o(x,w_o) Lo(x,wo) w o w_o wo方向看过去 x 点的出射光
  • L e ( x , w o ) L_e(x, w_o) Le(x,wo) w o w_o wo方向看过去 x 点的自发光
  • f r ( x , w i , w o ) f_r(x, w_i, w_o) fr(x,wi,wo)x 的 BRDF (双向反射分布函数)由物体材质属性确定的入射方向到出射方向光的反射比例
  • L i ( x , w i ) c o s θ i L_i(x,w_i)cosθ_i Li(x,wi)cosθi: 从 w i w_i wi方向入射的光这里乘以 c o s θ i cosθ_i cosθi是考虑了光照方向和物体法线有夹角有能量损失我们很多情况下也会把 c o s θ i cosθ_i cosθi放到 L i ( p , w i ) L_i(p,w_i) Li(p,wi)里这样渲染方程就没有 c o s θ i cosθ_i cosθi
  • V ( x , w i ) V(x,w_i) V(x,wi)光照方向 w i w_i wi是否能照射到 x 点如果不能则整个积分项结果为 0 。

渲染方程简单来说就是对于任意着色点 x我们眼睛从 w o w_o wo方向看过去的光照 L o ( x , w o ) L_o(x, w_o) Lo(x,wo)等于 x 点的自发光加上对「 x 点半球面( Ω + Ω^+ Ω+)所有入射光跟 x 点材质计算值」积分之后得到的光照。

有向距离场 SDF(Signed Distance Field)

SDF 表示的是空间中任意点到离它最近的物体表面的距离SDF 是有向的如果这个点在物体内 SDF 的值就是负值否则 SDF 的值就是正值。SDF 用处很广它既能作为光线步进时每一步距离的依据还能够用作几何的“隐式表达”。

TO BE CONTINUED

参考

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6