Chapter18 基于物理的渲染
- 一、PBS理论和数学基础
- 1.光是什么
- 微表面模型
- 2.渲染方程
- 3.精确光源
- 4.双向反射分布函数 BRDF
- 5.漫反射项
- (Lambert 模型)Lambertian BRDF为:
- Disney BRDF中漫反射项
- 6.高光反射项
- 微面元理论
- BRDF的高光反射项
- ①菲涅尔反射函数
- ②法线分布函数
- ③阴影-遮挡函数
- 7.PBS中的光照
- 8.Unity中PBS实现
- 二、Unity的Standard Shader
- 1.如何实现
- 2.如何使用
- 三、复杂例子
- 1.设置环境光照
- 2.设置反射探针
- 3.设置材质
- 4.设置线性空间
一、PBS理论和数学基础
1.光是什么
光是一种电磁波,由光源射出,与场景中的物体相交,一部分被吸收,一部分被散射,最后被感应器(眼睛等)吸收成像。光的传播方向会受到介质折射率的影响,折射率突变会导致散射现象。
我们一般假设两个介质的边界是无限大并且光滑的。用菲涅尔等式来描述光的反射与折射的各自占比
微表面模型
- 微表面模型:真实物体表面由许多微小的凹凸不平的表面组成,这些表面称为微表面,微表面模型假设每个微表面都是光学平滑的
- 光滑表面反射光线方向变化小,高光反射清晰;粗糙表面反射光线方向变化大,高光反射模糊
- 金属材质所有被折射的光会被吸收,转化为其他能量;非金属材质一部分会吸收,一部分又会散射到外部,散射出去的光叫做 次表面散射光(subsurface-scattered light)
- 次表面散射距离:次表面散射光从内部射出的位置与入射点之间的距离称为次表面散射距离
由于像素大小有限,如果次表面散射距离小于像素大小,可以忽略次表面散射光的影响,在局部范围内进行渲染;如果次表面散射距离大于像素大小,则需要使用特殊的渲染技术来模拟次表面散射效果——次表面散射渲染技术
2.渲染方程
- 辐射率 radiance:单位面积、单位方向上光源的辐射通量,用L来表示,被认为是单一光线的亮度和颜色评估
- 着色(shading)过程:通常使用入射光线的 L i L_{i} Li 来计算出射光线 L o L_{o} Lo
- 渲染方程:给定观察视角v,该方向上的出射辐射率 L o L_{o} Lo = 该点向观察方向发出的自发光辐射率 L e L_{e} Le + 所有有效入射光 L i ( ω i ) L_{i}(\omega_{i}) Li(ωi) 到达观察点的辐射率积分和
在实时渲染中,自发光项通常是直接加上某个自发光值,累加部分也基本无法实现,因此积分部分基本会被若干精确光源的叠加所替代,而不需要计算所有入射光线在半球面上的积分
3.精确光源
在实时渲染中,会用 精确光源 来近似模拟面光源 —— 点光源、平行光、聚光灯等。用 l c l_{c} lc 来表示方向,使用 c l i g h t c_{light} clight 来表示颜色,使用下面等式来计算在某个观察方向v上的出射辐射率:
若场景中包含多个点光源,把它们结果相加即可
- f ( l c , v ) f(l_{c},v) f(lc,v) :当给定入射光方向后,有多少百分比的光照被反射到了观察方向上——双向反射分布函数
4.双向反射分布函数 BRDF
-
两种理解 f ( l , v ) f(l,v) f(l,v)
- 给定入射角度 l 后,BRDF可以给出所有出射方向上的反射和散射光线的相对分布情况
- 给定出射角度 v 后,BRDF可以给出所有入射方向到该出射方向的光线分布
- (更直白)当一束光沿着入射方向 l 到达表面某点时, f ( l , v ) f(l,v) f(l,v) 表示有多少能量被反射到了观察方向上
-
BRDF是基于物理的:满足交换律和能量守恒
- 交换律:交换 l 和 v 后不变 f ( l , v ) = f ( v , l ) f(l,v) = f(v,l) f(l,v)=f(v,l)
- 能量守恒:表面反射能量不能超过入射能量 ∫ Ω f ( l , v ) ( n ⋅ l ) d ω o ≤ 1 \int_{Ω}{}f(l,v)(n·l)d\omega_{o} ≤ 1 ∫Ωf(l,v)(n⋅l)dωo≤1
BRDF可以用于描述两种物理现象:表面反射(高光反射项)和次表面散射(漫反射项)
5.漫反射项
(Lambert 模型)Lambertian BRDF为:
c d i f f c_{diff} cdiff: 表示漫反射光线所占比例——漫反射颜色;
除以 π \pi π :假设漫反射在所有方向上的强度都是相同的,而BRDF要求半球内的积分值为1。
给定入射方向 l 的光源在表面某点的出射漫反射辐射率值为:
Disney BRDF中漫反射项
- baseColor 是表面颜色,通常由表面纹理采样得到
- roughness 是表面粗糙度。
- 使用了 Schlick 菲涅尔近似等式来模拟在掠射角的反射变化,同时使用了表面粗糙度来改变 —— 使得光滑材质在掠射角具有更为明显的阴影边,又使得粗糙材质在掠射角具有亮边
6.高光反射项
微面元理论
计算BRDF时,入射方向 l 和 出射方向 v 都会被给定,只有一部分微面元反射的光线会进入我们眼睛中,即它们的法线 m 等于 l 和 v 的一半,即半程向量 h;这些微面元反射也不一定会全部被添加到BRDF中,因为可能出现其他面元遮挡的情况
BRDF的高光反射项
- D ( h ) D(h) D(h):微面元的法线分布函数 NDF——计算有多少比例的微面元法线满足 m = h
- G ( l , v , h ) G(l,v,h) G(l,v,h):阴影-遮掩函数——计算满足 m = h 的微面元中有多少不会被遮挡(活跃微面元的所占浓度)
- F ( l , h ) F(l,h) F(l,h):菲涅尔反射——反射光线占入射光线的比率
- 分母 4 ( n ⋅ l ) ( n ⋅ v ) 4(n·l)(n·v) 4(n⋅l)(n⋅v):于校正从微面元的局部空间到整体宏观表面数量差异的校正因子
①菲涅尔反射函数
描述了当光照方向和观察方向夹角逐渐增大时高光反射强度增大的现象
- Schlick 菲涅尔近似等式
- c s p e c c_{spec} cspec 是材质的高光反射颜色
②法线分布函数
值是非负的标量,决定了高光区域的大小、亮度和形状
- Blinn-Phong 模型:(归一化的Phong法线分布函数)
- g l o s s gloss gloss 是表面粗糙度相关参数
- 是一种经验模型,不能真实反映真实世界
- GGX分布(Trowbridge-Reitz法线分布函数)
- α \alpha α是表面粗糙度参数
- 具有更明亮、更狭窄且拖尾更长的高光区域
- GTR分布(Generalized-Trowbridge-Reitz法线分布函数),把分母指数的2变为可调参数
- Disney 还发现让 α = r o u g h n e s s 2 \alpha = roughness^{2} α=roughness2可以在粗糙度上得到更加线性的变化
③阴影-遮挡函数
G ( l , v , h ) G(l,v,h) G(l,v,h) 也被称为几何函数,具有给定面法线 m 的微面元在沿着入射方向 l 和观察方向 v 上不会被其他微面元挡住的概率,是一个0~1的概率值
习惯把 G ( l , v , h ) G(l, v, h) G(l,v,h) 和高光反射项的分母 ( n ⋅ l ) ( n ⋅ v ) (n ⋅ l)(n ⋅ v) (n⋅l)(n⋅v) 部分结合起来,即把 G ( l , v , h ) / ( n ⋅ l ) ( n ⋅ v ) G(l, v, h)/(n ⋅ l)(n ⋅ v) G(l,v,h)/(n⋅l)(n⋅v) 的部分合在一起讨论,称这个合项为可见性项(visibility term)
- Smith 模型(为GGX设计的)
- θ v \theta_{v} θv 表示观察方向 v 和表面法线 n 之间的夹角
- θ v \theta_{v} θv 表示观察方向 v 和表面法线 n 之间的夹角
- Smith-Joint 模型
Λ(ωo) 和 Λ(ωi) 分别评估出射方向和入射方向上的阴影和遮掩,基于这种分开计算的 Λ(ωo) 和 Λ(ωi)的 Smith 模型
7.PBS中的光照
随着新的技术不断被提出,实时面光源也不再是一个奢侈的梦想
- 基于图像的光照(imag-based lighting,IBL)
- 是把场景中远处的光照存储在类似环境贴图的图像中
- 环境贴图可以表示光滑物体表面反射的环境光
- 在 Unity 中,这种光照通常是由反射探针(Reflection Probes)机制来实现的,我们可以在 Shader中获取当前物体所在的反射探针并在需要时对它们的采样结果进行混合
8.Unity中PBS实现
基于GGX模型,与Disney BRDF中的漫反射项相同
- 漫反射项:
- 高光项:
- 菲涅尔反射函数
- 法线分布函数
- 阴影-遮掩函数(Smith-Joint 模型)
Λ(ωo) 和 Λ(ωi) 分别评估出射方向和入射方向上的阴影和遮掩,基于这种分开计算的 Λ(ωo) 和 Λ(ωi)的 Smith 模型
- 菲涅尔反射函数
二、Unity的Standard Shader
Unity创建模型或者材质时,默认着色器都是一个名为Standard 的着色器——基于物理的渲染
- Unity支持的两个工作流:金属工作流(metallic workfollow)和高光反射工作流(specular workflow)
- 金属工作流:定义了材质表面的金属值(是金属类型的还是非金属类型的)
- 高光反射工作流:可以直接指定表面的高光反射颜色(有很强的高光反射还是很弱的高光反射)等
1.如何实现
Standard.shader 和 StandardSpecular.shader
- SubShader:都定义了两个SubShader
- 第一个定义了前向渲染路径和延迟渲染路径的Pass,以及用于投射阴影和提取元数据的Pass
- 第二个定义了四个Pass,两个用于前向渲染路径,一个用于提取投射阴影,另一个用于提取元数据(相比于第一个取消了一些计算——视差贴图、不计算软阴影等)
- 两个shader最大的区别在于设置BRDF的输入时,使用了不同的函数来设置各个参数—— MetallicSetup 和 SpecularSetup
2.如何使用
- 需要在 Edit →Project Setttings→Player→Other Settings→Color Space 中选择Linear 才可以,这是因为基于物理的渲染需要使用线性空间
三、复杂例子
1.设置环境光照
- 使用 HDR 格式的 Skybox 可以让场景中物体的反射更加真实,有利于我们得到更加可信的光照效果
- 实时全局光照 GI 系统,场景中的物体可以接受直接光照和间接光照的影响
- 直接光照:需要保证平行光的方向和 Skybox 中的太阳或其他光源的位置一致,使得物体产生的光照信息可以与 Skybox 互相吻合
- Mode 设置:
- Realtime 模式进行实时的光照计算;
- Baked模式烘焙到一张光照纹理(lightmap)中,物体移动时阴影等光照效果不改变;
- Mix模式混合使用实时模式和烘焙模式,它会把场景中的静态物体(即那些被标识为 Static 的物体)的光照烘焙到光照纹理中,但仍然会对动态物体产生实时光照
- 间接光照:Indirect multiplier可以调整间接光强度
2.设置反射探针
- 在实时渲染中,我们经常使用Cubemap来模拟反射效果,但是当物体移动时,就容易穿帮——可以使用反射探针
- 反射探针的工作原理:它允许我们在场景中的特定位置上对整个场景的环境反射进行采样,并把采样结果存储在每个探针上
- 探针有三种类型:
- Baked:提前烘焙,只会处理那些静态物体(标识为 Reflection Probe Static)
- Realtime:实时更新当前的 Cubemap,并且不受静态物体还是动态物体的影响
- Custom:既可以让我们从编辑器中烘焙它,也可以让我们使用一个自定义的 Cubemap 来作为反射映射,但自定义的 Cubemap 不会被实时更新
- 反射探针应该被放置在那些具有明显反射现象的物体的旁边,或是一些墙角等容易发生遮挡的物体周围
- 反射探针还可以模拟互相反射
3.设置材质
真实可信的渲染效果,我们需要为场景中的物体指定合适的材质
4.设置线性空间
线性空间可以得到更加真实的效果