RTR Chaptor10 下

环境映射

  将一个球面函数记录在一个或者多个图像中的做法,被称为环境映射(environment mapping),因为我们通常会使用纹理映射来实现对表格的查找。这种表现形式是目前最强大且最流行的环境光照形式之一。与其他球面表示方法相比,虽然它占据了更多的内存,但是这种方法的实时解码过程十分简单、速度很快。此外,它可以表达任意高频的球面信号(通过增加纹理分辨率即可),并且能够准确捕捉任何范围内的环境radiance(通过增加每个通道的bit即可)。但是这种准确性是有代价的,与存储在其他常用纹理中的颜色和着色器属性不同,存储在环境贴图中的radiance值通常都具有高动态范围(HDR)。每个纹素会使用更多的bit,这意味着环境贴图往往要比其他纹理占用更多的存储空间,并且其访问速度要更慢。

  对于任何的全局球面函数,我们都有这样的一个基本假设:场景中所有物体的入射radiance L i L_i Li都只依赖于方向这一个参数。这个假设要求物体与被反射的光线位于很远的地方,并且不会发生自反射现象(将自身反射的光线再次反射)。

  依赖于环境映射的着色技术,其典型特征并不是它们表现环境光照的能力,而是我们如何将它们与给定的材质整合在一起。也就是说,为了进行积分,我们必须对BRDF采用哪种方式的近似和假设?反射映射(reflection mapping)是环境映射中最基本的一种情况,在这种情况下,我们会假设BRDF是一个完美的镜面。一个光学平面或者镜面会将入射光线反射到光线的反射方向 r i \mathbf{r}_{i} ri上(章节9)。类似地,出射radiance只来源于一个方向上的入射radiance,即反射的观察向量 r \mathbf{r} r,该向量的计算方法与 r i \mathbf{r}_{i} ri相同(方程9.15):

r = 2 ( n ⋅ v ) n − v (10.28) \mathbf{r}=2(\mathbf{n} \cdot \mathbf{v}) \mathbf{n}-\mathbf{v} \tag{10.28} r=2(nv)nv(10.28)

  这样可以大大简化镜面的反射方程:

L o ( v ) = F ( n , r ) L i ( r ) (10.29) L_{o}(\mathbf{v})=F(\mathbf{n}, \mathbf{r}) L_{i}(\mathbf{r}) \tag{10.29} Lo(v)=F(n,r)Li(r)(10.29)

  其中 F F F是菲涅尔项(详见章节9)。请注意,与基于半向量的BRDF中的菲涅尔项(使用半向量 h \mathbf{h} h l \mathbf{l} l或者 v \mathbf{v} v之间的夹角)不同,方程10.29中的菲涅尔项使用了表面法线 n \mathbf{n} n与反射向量 r \mathbf{r} r之间的夹角(与表面法线 n \mathbf{n} n与观察向量 v \mathbf{v} v之间的夹角相同)。

  由于入射radiance L i L_i Li只与方向有关,因此可以将其存储在一个二维表格中。这种表示方法能够让我们对一个具有任意入射radiance分布和一个具有任何形状的镜面进行高效照明,我们通过计算每个着色点所对应的反射向量 r \mathbf{r} r,并在表中查找对应radiance来实现这个操作。Blinn和Newell 引入了这个表格,并将其称为环境贴图(environment map),如图10.23所示。

在这里插入图片描述

图10.23:反射映射。当相机看到一个物体的时候,使用表面法线 n \mathbf{n} n与观察向量 v \mathbf{v} v来计算反射观察向量 r \mathbf{r} r,并使用这个反射观察向量 r \mathbf{r} r来访问环境贴图。通过使用一些投影函数,来将反射观察向量 ( x , y , z ) (x, y, z) (x,y,z)转换为纹理坐标,从而检索环境贴图所存储的radiance。

  反射映射算法的步骤如下:

  • 生成或者加载表示环境的纹理贴图。
  • 对于包含反射物的每个像素,计算物体表面位置上的法线。
  • 根据观察向量和表面法线,计算反射的观察向量。
  • 使用反射观察向量来计算环境贴图的索引,通过这个索引来获取入射radiance值。
  • 使用来自环境贴图的纹素数据,来作为方程10.29中的入射radiance。

  环境映射有一个潜在障碍值得一提,在使用环境映射的时候,平坦表面通常无法很好地工作。这是因为平面所反射出来的光线差异通常不会超过几度,这些反射方向紧密的聚集在一起,会导致环境贴图中的一小部分被映射到一个相对较大的表面上。如果我们已知一个表面是完全平坦的(例如地板),我们完全可以使用实时的平面反射技术来进行实现(章节11)。

  使用纹理数据来对场景进行照明的想法,也称为基于图像的光照(image-based lighting,IBL),这种环境贴图通常是从现实世界中的场景获得的,一般会使用相机来捕获360度全景的、高动态范围的图像。

  将环境映射与法线映射组合使用特别有效,可以产生丰富的视觉效果,如图10.24所示。这些特性的组合在历史上也十分重要(译者注:可能体现在PS3时代游戏画面上的油腻感)。一种受限的凹凸环境映射首次在消费级图形硬件中使用了依赖纹理读取(章节6),这使得这种能力成为像素着色器的一部分。

在这里插入图片描述

图10.24:一个位于相机处的光源,以及凹凸映射与环境映射相结合的渲染效果。从左到右分别是:没有环境映射、没有凹凸映射、相机处没有光源、所有这三个特性组合在一起。

  有各种各样的投影函数可以将反射观察向量存储到一个或者多个纹理中。我们将在本小节中讨论一些比较流行的映射方法,并指出每种映射的优缺点。

经纬度映射

  1976年,Blinn和Newell 实现了第一个环境映射算法。他们所使用的映射方式与地球上所使用的纬度/经度系统相类似,这也就是为什么这种技术通常会被称为纬度-经度映射(latitude-longitude mapping)或者lat-long映射。他们的方案并不像是一个从外面进行观察的地球仪,而更像是夜空中的星座地图。就像地球仪上的信息可以被平展到Mercator投影或者其他投影地图上一样,空间中一个点周围的环境也可以被映射到纹理上。在计算特定表面位置上的反射观察向量时,这个向量会被转换为球坐标 ( ρ , ϕ ) (\rho, \phi) (ρ,ϕ)。这里的 ϕ \phi ϕ相当于经度,其弧度值在 [ − π , π ] [-\pi,\pi] [π,π]之间变化; ρ \rho ρ相当于纬度,其弧度值在 [ 0 , π ] [0,π] [0,π]之间变化。球坐标 ( ρ , ϕ ) (\rho, \phi) (ρ,ϕ)可以由方程10.30计算而来,其中 r = ( r x , r y , r z ) \mathbf{r} = (r_x, r_y, r_z) r=(rx,ry,rz)是归一化的反射观察向量, z z z轴正方向指向上方:

ρ = arccos ⁡ ( r z ) a n d ϕ = atan ⁡ 2 ( r y , r x ) . (10.30) \rho=\arccos \left(r_{z}\right) \quad and \quad \phi=\operatorname{atan} 2\left(r_{y}, r_{x}\right). \tag{10.30} ρ=arccos(rz)andϕ=atan2(ry,rx).(10.30)

  有关 atan2 ⁡ \operatorname{atan2} atan2的描述,详见章节1。在获得对应的球坐标之后,使用这些值来访问环境贴图,并检索在反射观察方向上所看到的颜色。请注意,这里所描述的经纬度映射与Mercator投影并不相同,经纬度映射会保持纬度线之间的距离恒定,而Mercator投影的纬度线距离会在两极处趋于无穷大。

  在将一个球体展开为一个平面的时候,总是会发生一些变形,尤其是在不允许多次切割的情况下,而且每种投影方法在保持面积、距离和局部角度之间都有自己的权衡。这种映射方法的一个问题,球面上的信息密度是非常不均匀的。在图10.25顶部和底部的极端拉伸中可以看到这种情况,相较于靠近赤道的区域,在靠近两极的区域上会有更多数量的纹素。这种扭曲会带来一定的问题,首先它无法产生最高效的编码,其次在使用硬件进行纹理滤波的时候也会产生瑕疵,尤其是在两极处。滤波核不会随着纹理一起进行拉伸,因此会在具有较高纹素密度的区域过度收缩。还需要注意的是,虽然这个投影操作在数学上很简单,但是实际执行起来的效率可能会很低,因为诸如反余弦(arccosine)这样的超越函数(transcendental function),在GPU上的计算成本会很高。这里的超越函数是指:一种在数学中无法用有限次基本代数运算(加、减、乘、除和开方)进行表示的函数。

在这里插入图片描述

图10.25:地球上的经纬度线是等距的,这与与传统的Mercator投影不同。

球面映射

  球面映射(sphere mapping)是第一个在商业图形硬件中所使用的环境映射技术,它最初是由Williams 提出的,并由Miller和Hoffman 独立开发而来的。这个纹理图像来自于环境的外观,就像是在一个完全反射的球体中,以正交投影的方式来进行观察的那样,所以这个纹理也被称为球面贴图(sphere map)。一种制作真实环境球面贴图的方法是,对着一个闪亮的球体(例如圣诞树装饰品)进行拍摄,如图10.26所示。

在这里插入图片描述

图10.26:球面贴图(左)和经纬度映射格式的等效贴图(右)。

  由此产生的圆形图像也称为光照探针(light probe),因为它捕获了球体所在位置的光照情况。即使我们在运行过程中使用其他的编码方法,拍摄球形探针也是一种捕捉基于图像照明的有效方法。我们总是能够在球面投影和其他形式之间进行转换,例如稍后我们所讨论的立方体映射,前提是捕获的图像有足够的分辨率来克服不同方法之间的失真差异。

  反射球只会在球的正面显示整个环境。它会将每个反射观察方向映射到球面二维图像上的一个点。假设我们看向另一个方向,即球面贴图上给定的一个点,我们需要计算反射的观察方向。为了实现这一点,我们首先会获取该点上的球面法线,然后再生成反射的观察方向。在检索的时候我们会反转这个过程,通过反射的观察方向来获得球面上的具体位置,因此我们需要推导球面上的表面法线,然后才能得到访问球面贴图所需的 ( u , v ) (u, v) (u,v)参数。

在这里插入图片描述

图10.27:在给定的球面贴图空间中,原始观察向量 v \mathbf{v} v是恒定的,球面贴图的法线 n \mathbf{n} n介于原始观察向量 v \mathbf{v} v与反射观察向量 r \mathbf{r} r之间。对于位于原点的单位球体而言,图中的交点 h \mathbf{h} h与单位法线 n \mathbf{n} n具有相同的坐标。同时,图中还展示了为什么 h y h_y hy(从原点开始测量)与球体贴图的纹理坐标 v v v(不要与观察向量 v \mathbf{v} v混淆)有关。

  球面上的法线,是反射观察向量 r \mathbf{r} r与原始观察向量 v \mathbf{v} v之间的半角向量,这里的原始观察向量 v \mathbf{v} v在球面贴图空间中为 ( 0 , 0 , 1 ) (0,0,1) (0,0,1),如图10.27所示。因此这里的球面法线 n \mathbf{n} n是原始观察向量 v \mathbf{v} v和反射观察向量 r \mathbf{r} r的和,即 ( r x , r y , r z + 1 ) \left(r_{x}, r_{y}, r_{z}+1\right) (rx,ry,rz+1),将这个向量归一化,就可以得到单位球面法线:

n = ( r x m , r y m , r z + 1 m ) ,   where m = r x 2 + r y 2 + ( r z + 1 ) 2 . (10.31) \mathbf{n}=\left(\frac{r_{x}}{m}, \frac{r_{y}}{m}, \frac{r_{z}+1}{m}\right), \ \text{ where} \quad m=\sqrt{r_{x}^{2}+r_{y}^{2}+\left(r_{z}+1\right)^{2}}. \tag{10.31} n=(mrx,mry,mrz+1),  wherem=rx2+ry2+(rz+1)2 .(10.31)

  如果这个球体位于原点处,并且半径为1,那么单位法线的坐标实际上就是这个法线在球面上的位置 h \mathbf{h} h。我们并不需要知道 h z h_z hz,因为 ( h x , h y ) (h_x, h_y) (hx,hy)已经能够描述球面图像上的一个点了,其中每个值都在 [ − 1 , 1 ] [- 1,1] [1,1]的范围内。为了能够访问球面贴图,我们需要将坐标映射到 [ 0 , 1 ) [0,1) [0,1)范围内,因此要将坐标分别除以2并再加上0.5,即:

m = r x 2 + r y 2 + ( r z + 1 ) 2 , u = r x 2 m + 0.5 , v = r y 2 m + 0.5 (10.32) m=\sqrt{r_{x}^{2}+r_{y}^{2}+\left(r_{z}+1\right)^{2}}, \\[3mm] u=\frac{r_{x}}{2 m}+0.5, \\[3mm] v=\frac{r_{y}}{2 m}+0.5 \tag{10.32} m=rx2+ry2+(rz+1)2 ,u=2mrx+0.5,v=2mry+0.5(10.32)

  与经纬度映射相比,球面映射的计算过程要简单得多,并且只会有一个位于图像圆边缘的奇异点。球面映射的缺点是,球面贴图纹理所捕获的环境视图仅对单一的观察方向有效。这个纹理确实捕获了整个环境中的光照信息,因此可以根据新的观察方向,重新计算一个纹理坐标,但是这样做可能会导致一些视觉瑕疵,因为球面贴图的一小部分会因为新的观察方向而被放大,同时边缘周围的奇点也会变得更加明显。在实践中,我们通常假设球面贴图会跟随相机一起运动,并在观察空间中进行操作。

  由于球面贴图被定义为固定的观察方向,原则上球面贴图上的每个点不仅定义了反射方向,还定义了表面法线的方向,如图10.27所示。对于任意各向同性的BRDF而言,可以求解其反射方程,并将结果存储在球面贴图中,这种BRDF可以包括漫反射、镜面反射、逆反射和其他项。只要光照和观察方向是固定的,那么球面贴图就是正确的。只要球体的BRDF是均匀且各向同性的,那么还可以使用在实际照明下,真实球体的摄影图像来作为球面贴图。

  还可以同时使用两个球面贴图,一个使用反射向量进行索引,另一个使用表面法线进行索引,从而模拟镜面反射和漫反射环境效果。如果我们根据表面材质的颜色和粗糙度,来调整存储在球面贴图中的值,我们就获得了一种廉价的技术,它可以生成令人信服的材质效果,尽管这个材质效果与观察方向无关。这种方法被雕塑软件Pixologic ZBrush推广为“MatCap”着色,如图10.28所示。

在这里插入图片描述

图10.28:MatCap渲染的例子。左侧物体使用了右侧两个球面贴图进行着色处理。其中右上方的贴图使用了观察空间中的法线来进行索引;而右下角的贴图则使用了观察空间中的反射向量来进行索引,并将二者的值相加。最终生成的效果是相当令人信服的,但是移动观察点,图像中的光照效果并不会发生改变。

立方体映射

  1986年,Greene 引入了立方体环境贴图(cubic environment map),但是通常会将其称为立方体贴图(cube map),它是目前最流行的方法,其投影操作可以直接在现代GPU硬件上实现。通过将环境投影到以相机位置为中心的立方体侧面,来创建一个立方体贴图,然后将立方体表面上的图像用作环境贴图,如图10.29和图10.20所示。立方体贴图通常会以“交叉”图的形式呈现,即将立方体展开到一个平面上。然而在硬件实现的时候,立方体贴图会被存储为6个正方形纹理,而不是将立方体展开后的平面直接存储为一个大的矩形纹理,因此并不会浪费存储空间。

在这里插入图片描述

图10.29:Greene的环境贴图。图中展示了对应的关键点,左侧的立方体会被展开到右侧的环境贴图中。

在这里插入图片描述

图10.30:与图10.26中所使用的环境贴图相同,不同之处在于这里将其转换为了立方体贴图的格式。

  可以将相机放置在立方体的中心,然后以 9 0 ∘ 90^{\circ} 90的视场角(FOV)看向每个立方体表面,依次进行渲染从而创建一个立方体贴图,如图10.31所示。为了能够从真实世界中生成立方体贴图,通常会将专用相机拍摄而来的(或者拼接而来的)球形全景图,投影到立方体贴图的坐标系中。

在这里插入图片描述

图10.31:《极限竞速7》中环境贴图的光照,会随着赛车位置的改变而更新。

  与球面映射不同,立体体环境映射是与视角无关的。立方体贴图具有比经纬度映射更加均匀的采样特征,经纬度映射往往会在两极处过度采样(相对于赤道地区而言)。Wan等人提出了一种被称为等立方体(isocube)的映射方法,它比立方体映射具有更低的采样率差异,同时仍然利用立方体映射的纹理硬件来提高性能表现。

  访问立方体贴图的方法非常简单,可以直接将输入向量作为一个三分量的纹理坐标,在其所指的方向上获取数据。因此,对于反射而言,我们可以直接将反射方向 r \mathbf{r} r传递给GPU,甚至不需要将其归一化。在一些老旧的GPU上,双线性滤波可能会凸显立方体边缘处的缝隙,因为那时的纹理硬件无法在不同的立方体表面之间进行正确地过滤(执行这个操作的开销很大)。为了避免这个问题,研究人员开发了一些技术,例如让视图投影更宽一些,这样单个立方体表面就可以包含这些相邻的纹素了。但是,所有现代的GPU都可以正确地执行这种过滤操作,因此这些方法不再是必须的了。

其他投影方法

  如今,立方体贴图是最流行的环境光照表格表示方法,原因是其通用性(versatility)、再现高频细节的准确性、以及在GPU上的执行速度很快。但是,还有一些其他的投影方法值得一提。

  Heidrich和Seidel 提出使用两个纹理来进行双抛物面环境映射(dual paraboloid environment mapping)。这个想法类似于球面映射,但是它并不是通过记录环境在球面上的反射信息来生成纹理的,而是使用了两个抛物线投影。每个抛物面都会创建一个类似于球面贴图的圆形纹理,每个圆形纹理都会覆盖一个环境半球。

  与球面映射一样,反射观察向量是在贴图的基底上计算的,即在贴图的参考坐标系中进行计算的。反射观察向量的 z z z分量的符号,用于决定访问具体哪一个纹理。这个访问函数为:

u = r x 2 ( 1 + r z ) + 0.5 , v = r y 2 ( 1 + r z ) + 0.5 (10.33) u=\frac{r_{x}}{2\left(1+r_{z}\right)}+0.5, \quad v=\frac{r_{y}}{2\left(1+r_{z}\right)}+0.5 \tag{10.33} u=2(1+rz)rx+0.5,v=2(1+rz)ry+0.5(10.33)

  方程10.33用于正面图像;同理,当 r z r_{z} rz的符号取反时,则用于背面图像。

  与球面贴图相比,抛物线贴图具有更加均匀的环境采样,甚至均匀性可以与立方体贴图相比。但是,当在两个投影之间的接缝处进行采样和插值的时候,必须十分小心,这使得访问双抛物面环境贴图的成本很高。

在这里插入图片描述

图10.32:球体的立方体展开和八面体展开。

  八面体映射(octahedral mapping)是另一个值得注意的投影方法。它没有将周围的球面环境映射到一个立方体中,而是映射到了一个八面体中(如图10.32所示)。为了将这个八面体展开平铺成一个纹理,它的八个三角形面会被切开并排列在一个平面上,在理论上,将其排列成正方形结构或者矩形结构都是可以的。如果我们将其排列成正方形结构,那么访问八面体贴图的效率将会很高。对于给定的反射方向 r \mathbf{r} r,我们使用 L 1 L_1 L1范数的绝对值来将其归一化:

r ′ = r ∣ r x ∣ + ∣ r y ∣ + ∣ r z ∣ \mathbf{r}^{\prime}=\frac{\mathbf{r}}{\left|r_{x}\right|+\left|r_{y}\right|+\left|r_{z}\right|} r=rx+ry+rzr

  如果 r y ′ r_{y}^{\prime} ry为正,那么我们可以使用下面的坐标来索引正方形的纹理贴图:

u = r x ′ ⋅ 0.5 + 0.5 , v = r y ′ ⋅ 0.5 + 0.5 (10.34) u=r_{x}^{\prime} \cdot 0.5+0.5, \quad v=r_{y}^{\prime} \cdot 0.5+0.5 \tag{10.34} u=rx0.5+0.5,v=ry0.5+0.5(10.34)

  如果 r y ′ r_{y}^{\prime} ry为负,那么我们则需要通过变换,来将八面体的后半部分向外“折叠”:

u = ( 1 − ∣ r z ′ ∣ ) ⋅ sign ⁡ ( r x ′ ) ⋅ 0.5 + 0.5 , v = ( 1 − ∣ r x ′ ∣ ) ⋅ sign ⁡ ( r z ′ ) ⋅ 0.5 + 0.5 (10.35) u=\left(1-\left|r_{z}^{\prime}\right|\right) \cdot \operatorname{sign}\left(r_{x}^{\prime}\right) \cdot 0.5+0.5, \quad v=\left(1-\left|r_{x}^{\prime}\right|\right) \cdot \operatorname{sign}\left(r_{z}^{\prime}\right) \cdot 0.5+0.5 \tag{10.35} u=(1rz)sign(rx)0.5+0.5,v=(1rx)sign(rz)0.5+0.5(10.35)

  与双抛物面环境映射不同,八面体映射并不会受到过滤问题的影响,因为参数化的接缝与所用纹理的边缘相对应。纹理的“wrap”采样模式可以自动从另一边访问纹素,并进行正确的插值。虽然八面体映射投影操作的数学计算要稍微复杂一些,但是在实践中的表现会更好。八面体贴图所引入的变形量与立方体贴图差不多,所以当立方体贴图纹理硬件不存在或者不支持的时候,八面体贴图是一个不错的选择。另外一个值得注意的用法是,仅使用两个坐标来表示三维的归一化方向,从而能够对纹理进行一定程度的压缩。

  有一种特殊情况是,环境贴图会围绕一个轴径向对称。对于这种情况,Stone 提出了一种简单的分解方法,使用一个一维纹理,存储来自对称轴子午线(meridian line)上的radiance值。后来他将这个方案扩展到二维纹理,在每一行中都存储一个环境贴图,并与不同的Phong波瓣进行预卷积。这种编码方式可以模拟大量材质,并被应用于编码从晴朗天空所发出的radiance。

基于图像的高光照明

  环境映射最初是作为一种镜面渲染技术发展起来的,但是也可以将它扩展到光泽(glossy)反射中。当用于模拟无限远处光源的镜面效果时,这样的环境贴图也被称为高光探针(specular light probe)。之所以使用这样一个术语,是因为它捕获(探测)了场景中给定点的各个方向上的radiance,并使用这个信息来计算一般的BRDF——而不仅仅针对于纯镜面或者Lambertian表面的特殊情况。可以将环境光照存储在立方体贴图中,并使用这些立方体贴图来控制光泽材质的反射效果,这样的贴图也被叫做高光立方体贴图(specular cube map)。

  为了模拟表面的粗糙度,可以对纹理中的环境光照信息进行预滤波(prefiltered)。通过对环境贴图进行模糊处理,我们可以表现出比完美镜面反射稍微粗糙一些的镜面反射效果。这种模糊处理应当以一种非线性的方式进行,即不同部分的纹理应当以不同的方式进行模糊。这种非线性处理是有必要的,因为环境贴图的纹理代表了一种到理想球面方向空间的非线性映射,两个相邻纹素中心之间的角距离是不固定的,单个纹素所覆盖的立体角也是不固定的。一些专门用于预处理立方体贴图的工具,例如AMD的CubeMapGen(现在是开源的),在对立方体贴图进行过滤的时候会考虑到这些因素。来自其他面的邻近样本会被用来创建mipmap,并且每个纹素所覆盖的角度范围也会被考虑在内。图10.33展示了这样的一个例子。

在这里插入图片描述

图10.33:在第一行中,左侧是原始环境贴图,右侧是将其应用到一个球体上的着色结果。在第二行中,使用高斯滤波器对相同的环境贴图进行模糊处理,模拟了粗糙材质的外观。

  这种通过对环境贴图进行模糊,同时根据经验来近似粗糙表面的外观,这个过程与实际的BRDF没有任何联系。一个更有原则的方法是,当给定表面法线和观察方向的时候,考虑BRDF函数在球面上的形状,然后我们再使用这个分布来对环境贴图进行过滤,如图10.34所示。使用一个镜面波瓣来对环境贴图进行过滤,这并不是一件简单的事情,因为BRDF可以表现出任意的形状,这取决于其粗糙度参数、观察向量和法线方向;也就是说,至少有五个维度的输入值(粗糙度和两组极坐标角度,分别用于表示观察方向和法线方向)控制了最终的波瓣形状。为其中的每个参数组合存储多张环境贴图是不现实的。

在这里插入图片描述

图10.34:左侧展示了一个被物体反射的光线,它被反射到了完美镜面反射方向上,使用这个方向来从环境纹理(在本例中是立方体贴图)中检索对应的值。右图展示了反射光线的镜面波瓣,它用于对环境纹理进行采样。绿色方块表示立方体贴图的横截面,红色的虚线代表了纹素之间的边界。

预过滤环境映射

  在实际实现中,应用于光泽材质的预过滤环境光照需要使用BRDF的近似值,以便生成的纹理能够独立于观察方向和表面法线。如果我们将BRDF的形状变化限制在材质光泽度上,即只有材质的光泽度会对BRDF的形状产生影响,那么我们就可以根据不同的粗糙度参数,预计算并存储对应的环境贴图,并在运行过程中,选择一个合适的环境贴图进行使用。在实践中,这意味着我们不需要使用模糊滤波核,也可以对波瓣形状进行控制,使得这个波瓣在反射向量周围径向对称。

  想象从一个给定的反射观察方向射入的一组光线,直接来自这个反射观察方向上的光线将提供最大的贡献值,随着入射光线方向与反射观察方向之间的夹角越来越大,这些光线的贡献也会越来越小。环境贴图的纹素面积与纹素的BRDF贡献值相乘,给出了该纹素的相对影响力。这个加权贡献乘上环境贴图的纹素颜色,并将结果进行求和可以获得 q \mathbf{q} q,同时也会计算加权贡献的总和 s s s。最后的结果 q / s \mathbf{q}/s q/s,就是在反射观察方向的波瓣上整体的颜色,将其存储在生成的反射贴图中。

  如果我们使用Phong材质模型,那么这种径向对称的假设自然而然是成立的,我们几乎可以准确地计算环境光照。Phong 是根据经验来推导出这个模型的,与我们在章节9中所看到的BRDF相比,这个模型并没有物理依据。Phong模型和我们在章节9中讨论的Blinn-Phong BRDF 都是幂次的余弦波瓣,但是在Phong模型中,这个余弦是由反射向量(详见方程9.15)和观察向量的点积而来的;而在Blinn-Phong BRDF中,这个余弦是由半向量(详见方程9.33)和表面法线点积而来的。这使得反射波瓣是旋转对称的,详见图9.35所示。

  对于一个径向对称的镜面波瓣,我们仍然无法接受的唯一效果是地平线裁剪(horizon clipping),因为它会使得镜面波瓣的形状依赖于观察方向。想象现在我们有一个闪亮的球体(其表面并不是镜面),此时如果我们观察球体表面的中心区域,就会得到一个对称的Phong波瓣。而如果我们观察球体轮廓的表面区域时,实际上波瓣的一部分必须要被切割掉,因为来自地平线以下的光线无法到达相机,如图10.35所示。这和我们之前讨论面光源近似值时所看到的问题是一样的,但是在实际应用中,这种现象经常会被实时方法所忽略。忽略这个效应,会使得在掠射角度下形成过于明亮的着色效果。

在这里插入图片描述

图10.35:两个观察者看向同一个闪亮的球体。球体上两个不同的位置对于两个观察者产生了相同的反射方向。左侧观察者所看到的表面反射是一个对称的波瓣。右边观察者所看到的反射波瓣则会被表面本身的视界所截断,因为光线并不会被视界(地平线)以下的表面所反射。

  Heidrich和Seidel 以这种方式,使用单个反射贴图来模拟表面的模糊性。为了适应不同的粗糙度水平,通常会使用环境立方体贴图的mipmap(章节6)。mipmap的每个级别都存储了入射radiance的模糊版本,较高级别的mipmap用于存储较为粗糙的表面,即更宽的Phong波瓣 。在运行过程中,我们通过使用反射向量来索引立方体贴图,并根据所需的Phong指数(材质粗糙度)来强制选择给定的mipmap层级,如图10.36所示。

在这里插入图片描述

图10.36:环境贴图预过滤。将立方体贴图与不同粗糙度的GGX波瓣进行卷积,并将结果存储在纹理的mipmap中。粗糙度从左到右递减,下面一行展示了生成的对应mipmap,上面一行展示了在反射方向上渲染的球体。

  对于比较粗糙的材质,会使用较宽的滤波核来去除高频信息,因此需要使用较低的分辨率才能得到充分模糊的结果,这正好与mipmap结构完美对应。此外,通过使用GPU硬件的三线性插值,可以在预滤波的mipmap层级之间进行采样,从而模拟我们没有精确表示的粗糙度值。当与菲涅尔项结合时,这种反射贴图对于光泽表面的效果要更好。

  出于性能和抗锯齿的原因,具体选择要使用哪一个mipmap层级,不仅要考虑着色点处的材质粗糙度,还要考虑屏幕像素足迹所覆盖的表面区域内的法线变化和粗糙度变化。Ashikhmin和Ghosh 指出,为了获得最佳效果,应当对两个候选mipmap层级进行比较(由纹理硬件计算而来的最小化层级与当前滤波器宽度所对应的层级),并在二者中选择使用分辨率较低的那个mipmap层级。为了使得结果更加准确,还应当考虑表面方差的扩大效应,并使用一个新的粗糙度水平,这个粗糙度水平与一个BRDF波瓣项有关,这个BRDF波瓣可以视为像素足迹内的平均波瓣。这个问题与BRDF抗锯齿(章节9)完全相同,并且适用相同的解决方案。

  前面提出的过滤方案都有着这样的一个假设,即对于给定的反射方向,所有的波瓣都具有相同的形状和高度。这个假设也意味着波瓣必须是径向对称的。除了上述我们提到地平线裁剪问题之外,大多数BRDF波瓣在所有角度也上并不都是均匀的、径向对称的,例如:在掠射角度下,波瓣通常会变得更尖更薄;此外,波瓣的长度通常也会随着仰角的变化而变化。

  上述的这些效应对于弯曲表面而言通常是很难感知到的,然而对于一些平坦的表面而言(例如地板),径向对称的滤波器可能会引入明显的误差。(详见图9.35)

卷积环境贴图

  想要生成预过滤的环境贴图意味着,要对与方向 v \mathbf{v} v相关的每个纹素上,计算环境radiance与镜面波瓣 D D D的积分:

∫ Ω D ( l , v ) L i ( l ) d l . \int_{\Omega} D(\mathbf{l}, \mathbf{v}) L_{i}(\mathbf{l}) d \mathbf{l}. ΩD(l,v)Li(l)dl.

  这个积分是一个球面卷积(spherical convolution),由于其中的 L i L_i Li只能通过环境贴图的表格形式获得,因此这个积分通常无法解析求解,只能通过数值方法进行求解。一种流行的数值方法是采用蒙特卡罗方法:

∫ Ω D ( l , v ) L i ( l ) d l ≈ lim ⁡ N → ∞ 1 N ∑ k = 1 N D ( l k , v ) L i ( l k ) p ( l k , v ) (10.36) \int_{\Omega} D(\mathbf{l}, \mathbf{v}) L_{i}(\mathbf{l}) d \mathbf{l} \approx \lim _{N \rightarrow \infty} \frac{1}{N} \sum_{k=1}^{N} \frac{D\left(\mathbf{l}_{k}, \mathbf{v}\right) L_{i}\left(\mathbf{l}_{k}\right)}{p\left(\mathbf{l}_{k}, \mathbf{v}\right)} \tag{10.36} ΩD(l,v)Li(l)dlNlimN1k=1Np(lk,v)D(lk,v)Li(lk)(10.36)

  其中 l k \mathbf{l}_{k} lk k = 1 , 2 , … , N k=1,2, \ldots, N k=1,2,,N)是单位球面上的离散样本(方向); p ( l k , v ) p\left(\mathbf{l}_{k}, \mathbf{v}\right) p(lk,v)是在方向 l k \mathbf{l}_{k} lk上生成样本(采样)的概率密度函数,如果我们对球面进行均匀采样,则总有 p ( l k , v ) = 1 p\left(\mathbf{l}_{k}, \mathbf{v}\right)=1 p(lk,v)=1。虽然这个总和对于我们想要积分的每个方向 v \mathbf{v} v而言都是正确的,但是当结果存储在环境贴图中时,我们还必须考虑投影所带来的失真扭曲,因此需要对每个纹素,按照其所占据的立体角进行加权。

  虽然蒙特卡洛方法是简单且正确的(无偏),但是它需要大量的样本才可能会收敛到积分的数值,即使对于离线过程而言也是很慢的。这种情况对于mipmap的第一级而言尤其明显,在第一级中,我们会对较浅的高光波瓣进行编码(在Blinn-Phong模型中是高指数,在Cook-Torrance模型中是指低粗糙度)。在这种情况下,我们不仅需要对更多的像素进行计算(因为我们需要更高的分辨率来存储高频细节),而且对于那些不接近完美反射的方向而言,其波瓣可能会接近于零。当 D ( l k , v ) ≈ 0 D\left(\mathbf{l}_{k}, \mathbf{v}\right) \approx 0 D(lk,v)0时,大多数样本都是无效的,这样的样本只会浪费计算量。

  为了避免这种现象,我们可以使用重要性采样(importance sampling),在这种情况下,我们会使用一个概率分布来生成采样方向,这个概率分布会尽量贴合镜面波瓣的形状。这是蒙特卡罗积分中一种常见的方差降低技术,并且对于大多数常用的波瓣而言,都存在使用重要性采样的策略。为了获得更加有效的采样方案,还可以将环境贴图中的radiance分布与镜面波瓣的形状结合起来考虑 。然而,所有依赖于点采样的技术,通常只能用于离线渲染和生成ground-truth中,因为这个过程通常需要使用数百个样本,需要耗费的时间过长。

  为了进一步降低采样方差(即噪声),我们还可以对样本之间的距离进行估计,并使用锥形方向上的和,而不是单一方向来进行积分。使用锥形对环境贴图进行采样,可以通过对其中一个mipmap层级进行点采样来近似,直到某个层级的纹素与锥形占据大致相同的立体角。虽然这样做会引入偏差,但是它可以大大降低实现无噪声结果所需的样本数量,这种类型的采样可以在GPU的帮助下,以交互式速率进行执行。

  McGuire等人开发了一种同样使用区域样本的技术,它旨在对镜面波瓣的卷积结果进行实时近似,并且不需要任何预计算。这个过程十分巧妙,它对非预过滤环境立方体贴图的多个mipmap层级进行了混合,以便能够重建Phong波瓣的形状。类似地,Hensley等人使用了SAT(详见章节6)来快速实现近似。McGuire等人和Hensley等人的技术严格来说还是存在预计算的,因为在渲染环境贴图之后,它们仍然需要生成mipmap层级或者前缀和(prefix sum,用于SAT),而对于这两种常见操作,都存在一些高效算法,因此所需的预计算量要比执行整个镜面波瓣卷积少得多。这两种技术的速度都很快,甚至可以用于环境光照的实时表面着色,但是缺点在于,不如其他依赖于预过滤的方法准确。

  Kautz等人提出了另一种变体方法,一种快速生成滤波抛物面反射贴图的分层技术。最近,Manson和Sloan 使用了一种高效的二次B样条滤波方案,来生成环境贴图的mipmap,这显著提高了SOTA的水平。这些经过特殊计算的B样条滤波mipmap,之后会通过组合少量样本进行使用,这与McGuire等人和Kautz等人的技术相类似,它可以生成快速且准确的近似结果。使用这种方法可以实时生成结果,而且与使用重要性采样的蒙特卡罗方法所计算出的ground-truth相比,二者的质量相当。

  当我们想要过滤的环境贴图是动态渲染而来的时候,快速卷积技术允许我们对预过滤立方体贴图进行实时更新。使用环境贴图通常会使得物体难以在不同的光照情况下进行移动,例如:从一个房间移动到另一个房间。我们可以逐帧生成立方体环境贴图,或者每隔几帧重新生成一次;如果我们采用了一些比较高效的滤波方案,那么替换新的镜面反射贴图也是相对高效的。

  另一种重新生成整个环境贴图的方法是,将动态光源的高光效果叠加到基础的静态环境贴图上,所添加的高光可以是预先过滤的“亮斑”,这些亮斑会被添加到预过滤的基础环境贴图中,这样做可以避免在运行时执行过滤操作。这种思路也有一些局限性,这个局限性来自于环境贴图的基本假设:光源和反射物体都位于远处,因此不会随着观察物体位置的改变而改变。这个基本假设意味着我们不能轻易使用局部光源。

  如果场景中的几何物体是静态的,但是一些光源(例如太阳)是动态的,此时有一种十分廉价的技术,它不需要将场景动态渲染到立方体贴图中,而是将表面属性(位置、法线、材质)存储在一个G-buffer 环境贴图中。有关G-buffer的内容将在章节20中进行详细讨论。然后,我们使用这些属性计算表面的出射radiance,并将其记录在环境贴图中。《使命召唤:无限战争》、《巫师3》和《孤岛惊魂4》等游戏都使用了这种技术。

微表面 BRDF 的分裂积分近似

  环境光照十分有用,因此出现了许多技术来减少立方体贴图预过滤中固有的BRDF近似问题。

  到目前为止,我们假设所使用的BRDF是一个Phong波瓣,然后再将其乘以一个完美镜面的菲涅尔项,从而构建了如下形式的近似:

∫ l ∈ Ω f ( l , v ) L i ( l ) ( n ⋅ l ) d l ≈ F ( n , v ) ∫ l ∈ Ω D Phong  ( r ) L i ( l ) ( n ⋅ l ) d l , (10.37) \int_{\mathbf{l} \in \Omega} f(\mathbf{l}, \mathbf{v}) L_{i}(\mathbf{l})(\mathbf{n} \cdot \mathbf{l}) d \mathbf{l} \approx F(\mathbf{n}, \mathbf{v}) \int_{\mathbf{l} \in \Omega} D_{\text {Phong }}(\mathbf{r}) L_{i}(\mathbf{l})(\mathbf{n} \cdot \mathbf{l}) d \mathbf{l}, \tag{10.37} lΩf(l,v)Li(l)(nl)dlF(n,v)lΩDPhong (r)Li(l)(nl)dl,(10.37)

  其中 ∫ Ω D Phong  ( r ) \int_{\Omega} D_{\text {Phong }}(\mathbf{r}) ΩDPhong (r)是环境贴图中每个反射方向 r \mathbf{r} r的预计算结果。如果此时我们考虑方程9.34中所使用的镜面微表面BRDF f smf f_{\text {smf}} fsmf,这里为了方便理解,我们再次给出这个BRDF的方程:

f s m f ( l , v ) = F ( h , l ) G 2 ( l , v , h ) D ( h ) 4 ∣ n ⋅ l ∣ ∣ n ⋅ v ∣ (10.38) f_{\mathrm{smf}}(\mathbf{l}, \mathbf{v})=\frac{F(\mathbf{h}, \mathbf{l}) G_{2}(\mathbf{l}, \mathbf{v}, \mathbf{h}) D(\mathbf{h})}{4|\mathbf{n} \cdot \mathbf{l}||\mathbf{n} \cdot \mathbf{v}|} \tag{10.38} fsmf(l,v)=4∣nl∣∣nvF(h,l)G2(l,v,h)D(h)(10.38)

  我们可以注意到,即使 D ( h ) ≈ D Phong  ( r ) D(\mathbf{h}) \approx D_{\text {Phong }}(\mathbf{r}) D(h)DPhong (r)是有效的,我们在方程10.37中积分也去掉了BRDF最重要的几个部分:shadowing-masking项 G 2 ( l , v , h ) G_{2}(\mathbf{l}, \mathbf{v}, \mathbf{h}) G2(l,v,h)和半向量菲涅尔项 F ( h , l ) F(\mathbf{h}, \mathbf{l}) F(h,l)。并且将菲涅尔项放到积分外部是没有理论基础的。Lazarov指出,与完全不使用菲涅尔项相比,使用依赖于 n ⋅ v \mathbf{n} \cdot \mathbf{v} nv的完美镜面的菲涅尔项,而不是微表面BRDF中的 n ⋅ h \mathbf{n} \cdot \mathbf{h} nh,会产生更大的误差。Goanda, Lazarov和Karis都独立推导出了一个类似的分裂积分近似(split-integral approximation):

∫ l ∈ Ω f s m f ( l , v ) L i ( l ) ( n ⋅ l ) d l ≈ ∫ l ∈ Ω D ( r ) L i ( l ) ( n ⋅ l ) d l ∫ l ∈ Ω f s m f ( l , v ) ( n ⋅ l ) d l (10.39) \int_{\mathbf{l} \in \Omega} f_{\mathrm{smf}}(\mathbf{l}, \mathbf{v}) L_{i}(\mathbf{l})(\mathbf{n} \cdot \mathbf{l}) d \mathbf{l} \approx \int_{\mathbf{l} \in \Omega} D(\mathbf{r}) L_{i}(\mathbf{l})(\mathbf{n} \cdot \mathbf{l}) d \mathbf{l} \int_{\mathbf{l} \in \Omega} f_{\mathrm{smf}}(\mathbf{l}, \mathbf{v})(\mathbf{n} \cdot \mathbf{l}) d \mathbf{l} \tag{10.39} lΩfsmf(l,v)Li(l)(nl)dllΩD(r)Li(l)(nl)dllΩfsmf(l,v)(nl)dl(10.39)

  请注意,尽管这个解决方案通常被称为“分裂积分(split integral)”,但是我们实际上并没有将积分分解为两个拆开的项,因为那并不是一个很好的近似。需要牢记的是, f smf f_{\text {smf}} fsmf中包含了镜面波瓣 D D D,同时我们注意到 D D D n ⋅ l \mathbf{n} \cdot \mathbf{l} nl项都出现在了右侧的第一个被积函数中。在上面的分裂积分近似中,我们在两个被积函数里都包含了环境贴图中围绕反射向量对称的所有项。Karis将他的推导称为分裂求和(split-sum),因为它是在预计算中所使用的重要性采样数值积分器(方程10.36)上完成的,但实际上它是完全相同的解。

  由此得到的两个积分都可以进行高效地预计算。其中第一种方法假设波瓣 D D D是径向对称的,该方法仅依赖于表面的粗糙度和反射向量,而在实践中,我们可以使用任意的波瓣,只要让 n = v = r \mathbf{n}=\mathbf{v}=\mathbf{r} n=v=r即可。这个积分可以像之前一样进行预计算,并存储在立方体贴图的mipmap中。当将半向量BRDF转换为绕反射向量的波瓣时,为了在环境光照和解析光源(analytic light)之间获得类似效果的高光,径向对称的波瓣应当使用修正的粗糙度。例如:要将一个基于Phong的反射向量镜面项,转换为一个基于半角的Blinn-Phong BRDF,可以将指数除以4,来获得较好的拟合结果。

  第二个积分是镜面项的半球定向反射率 R spec  ( v ) R_{\text {spec }}(\mathbf{v}) Rspec (v)(详见章节9)。函数 R spec  R_{\text {spec }} Rspec 取决于仰角 θ θ θ,粗糙度 α α α和菲涅尔项 F F F。通常菲涅尔项 F F F是使用Schlick近似(方程9.16)实现的,它只有 F 0 F_0 F0一个参数,因此函数 R spec  R_{\text {spec }} Rspec 是一个拥有三个输入参数的函数。Gotanda对函数 R spec  R_{\text {spec }} Rspec 进行了数值预计算,并将结果存储在一个三维查找表中。Karis和Lazarov注意到,可以将 F 0 F_0 F0 R spec  R_{\text {spec }} Rspec 中提取出来,这会产生两个因子,每个因子都取决于这两个参数:仰角 θ θ θ和粗糙度 α α α。基于这种观察和发现,Karis将函数 R spec  R_{\text {spec }} Rspec 的预计算查找表压缩成了一个可以存储在双通道纹理中的二维表格,而Lazarov则通过函数拟合,对这两个因子分别进行了解析近似。后来,Iwanicki和Pesce 推导出了一种更加精确且更加简单的解析近似。请注意, R spec  R_{\text {spec }} Rspec 还可以用于提高漫反射BRDF模型的准确度(详见方程9.65)。如果应用程序中同时实现了这两种技术,那么 R spec  R_{\text {spec }} Rspec 的实现可以同时用于这两种技术中,从而提高效率。

  对于一个恒定的环境贴图,分裂积分的解是精确的。立方体贴图部分提供了与镜面反射率成比例的光照强度,这是均匀光照下的正确BRDF积分。根据经验,Karis和Lazarov都观察到,这种近似也适用于一般的环境贴图,尤其是当内容频率相对较低的时候(低频信息),这种情况在一些户外场景中很常见,如图10.37所示。与ground-truth相比,该技术最大的误差来源是,它假设预过滤环境立方体贴图是径向对称的、没有被裁剪的镜面波瓣(如图10.35所示)。Lagarde建议,可以根据表面粗糙度,将用于检索预过滤环境贴图的向量,从反射方向往法线方向稍稍倾斜,因为从经验上来看,与ground-truth相比,这样做可以减少误差。这样做其实是有理论依据的,因为它对没有被表面入射radiance半球所剪切的波瓣进行了部分补偿。

在这里插入图片描述

图10.37:Karis的“分裂求和”近似。从左到右,材质的粗糙度越来越高。第一行:参考解决方案。第二行:分裂积分近似。第三行:在镜面波瓣上加入所需径向对称( n = v = r \mathbf{n}=\mathbf{v}=\mathbf{r} n=v=r)的分裂积分。最后一行会引入最多的误差。

不对称和各向异性波瓣

  到目前为止,我们所看到的解决方案都局限于各向同性的镜面波瓣,这意味着当入射方向和出射方向围绕表面法线旋转的时候,这些波瓣的形状和大小不会发生改变(详见章节9),并且仍然会围绕反射向量径向对称。微表面BRDF波瓣是围绕着半向量 h = ( l + v ) / ∥ l + v ∥ \mathbf{h}=(\mathbf{l}+\mathbf{v}) /\|\mathbf{l}+\mathbf{v}\| h=(l+v)/∥l+v(方程9)进行定义的,因此即使是在各向同性的情况下,也不会出现我们所需要的对称性。半向量依赖于光线方向 l \mathbf{l} l,对于环境光照而言,光线方向并不是唯一的。因此,与Karis 的做法一样,对于这样的BRDF,我们会让 n = v = r \mathbf{n}=\mathbf{v}=\mathbf{r} n=v=r,并推导出一个恒定的粗糙度修正因子,来让镜面高光的尺寸与原始的半向量方程相匹配。这些假设都是相当大的误差来源,如图10.38所示。

在这里插入图片描述

图10.38:红色代表了GGX BRDF,绿色代表了围绕反射向量径向对称的GGX NDF波瓣。后者进行了缩放修正,从而与GGX镜面波瓣的峰值相匹配,但是请注意,它无法捕获基于半向量BRDF的各向异性形状。在最右边,使用这两个波瓣各自渲染了一个球体,请注意二者之间高光的差异。

  我们在章节10中所提到的一些方法(例如来自Luksch等人、Colbert和Krivanek 的方法),可以在交互速率下计算具有任意BRDF的环境光照。然而,由于这些方法往往需要几十个样本来收敛,因此很少用于物体的实时表面着色,它们可以被视为蒙特卡洛积分中的重要性采样技术。

  通过在镜面波瓣上施加径向对称来创建预过滤的环境贴图,使用这个环境贴图的逻辑也很简单直接,即访问与当前表面镜面粗糙度相适应的预过滤波瓣即可。我们的结果只有在直视表面( n = v \mathbf{n}=\mathbf{v} n=v)的情况下才能保证是正确,而在其他任何其他情况下我们都不能保证正确;并且在掠射视角下,无论BRDF 波瓣的形状如何,都会产生一些误差,因为我们忽略了真实的波瓣不能低于着色表面点视界这一事实(地平线裁剪)。一般来说,在使用这种方法的情况下,镜面反射方向上所对应的数据很可能与实际情况不那么匹配。

  Kautz和McCool通过对存储在预过滤环境贴图中的径向对称波瓣使用更好的采样方案,从而对原生的预积分进行了改进。他们提出了两种方法:第一种方法使用单个样本,它试图找到一个最佳波瓣,来对当前观察方向上的BRDF进行近似,而不是依赖一个恒定的修正因子。第二种方法则是对来自不同波瓣的几个样本进行平均。第一种方法可以更好地模拟掠射角度下的表面。他们还推导出了一个修正因子,以修正使用径向对称波瓣近似方法与原始BRDF相比,反射出的总能量差异。第二种方法还对结果进行了扩展,包括典型半向量模型的拉伸高光。在这两种情况下,都使用了优化技术来计算驱动预过滤波瓣采样的参数表。Kautz和McCool的技术还使用了贪婪拟合算法和抛物线环境贴图。

  最近,Iwanicki和Pesce 推导了一种GGX BRDF与环境立方体贴图的类似近似,他们使用了一种称为Nelder-Mead 最小化的方法。他们还分析了利用现代GPU硬件的各向异性过滤能力来加速采样的想法。

  使用预过滤立方体贴图中的单个样本,但是将其位置调整到一个更加复杂的镜面BRDF峰值的想法,被Revie 用于与延迟着色相结合的毛皮渲染中。在这种情况下,方法的限制并不是直接来自于环境贴图,而是需要在G-buffer中编码数量尽可能少的参数。McAuley 对这个想法进行了扩展,将这种技术用于延迟渲染系统中的所有表面。

  McAllister等人开发了一种技术,该技术通过利用Lafortune BRDF的特性,可以实现各种渲染效果,包括各向异性和逆反射。这个BRDF 本身就是一种基于物理渲染的近似,它由多个Phong波瓣组成,这些波瓣会在反射方向周围进行扰动。Lafortune通过将这些波瓣拟合到He-Torrance模型中,并通过一个叫做goniorereflectometer的装置,来对真实材质进行测量,证明了这种BRDF表达复杂材质的能力。McAllister的技术基于这样一种观察:由于Lafortune波瓣是广义的Phong波瓣,因此可以使用传统的预过滤环境贴图,利用其mipmap层级来对不同的Phong指数进行编码。Green等人提出了一种类似的方法,该方法使用了高斯波瓣来代替Phong波瓣;此外,他们的方法还可以进行扩展,从而支持环境贴图的定向阴影。

环境映射

  上一小节中我们讨论了如何使用预过滤环境贴图来实现光泽反射,这些贴图同样也可以用于实现漫反射。镜面反射所使用的环境贴图具有一些共同的属性,无论它们是用于镜面反射的未过滤贴图,还是用于光泽反射的过滤贴图。在这两种情况下,高光环境贴图都是使用反射观察向量来进行索引的,并且它们都包含了radiance值,其中未过滤的环境贴图包含了入射的radiance,而过滤的环境贴图则包含了出射的radiance。

  相反,漫反射环境贴图只需要使用表面法线 n \mathbf{n} n来进行索引,并且它们所包含的是irradiance值,因此它们也被称为irradiance环境贴图。从图10.35中可以看出,使用环境贴图的光泽反射,由于其固有的模糊性(波瓣扩散角度),因此在某些条件下会产生误差(地平线裁剪),相同的反射观察向量可能会对应不同的反射情况。这些问题并不会发生在irradiance环境贴图中,因为表面法线包含了漫反射所有的相关信息。与原始光照相比,irradiance贴图是极其模糊的,因此可以使用较低的分辨率来进行存储。通常会使用预过滤镜面环境贴图的最低mipmap层级来存储irradiance数据。此外,与我们上一小节研究的光泽反射不同,我们不再针对BRDF波瓣进行积分,BRDF波瓣会被裁剪到表面法线周围的半球范围内。环境光照与clamped余弦波瓣(即clamp到0过后的余弦函数)的卷积是一个精确值,而不是一个近似值。

在这里插入图片描述

图10.39:计算irradiance环境贴图的过程。在原始环境纹理(本例中是一个立方体贴图)中对表面法线周围的余弦加权半球进行采样,并对采样结果进行求和,从而获得与视图无关的irradiance。图中绿色的方块代表了立方体贴图的横截面,红色的虚线代表了纹素之间的边界。这里使用的是一个立方体贴图,但实际上任何环境表示都是可以使用的。

  对于贴图中的每个纹素,我们需要将影响给定的法线方向表面的所有光照,将其贡献按照余弦进行加权并求和。irradiance环境贴图是通过对原始环境贴图应用一个far-reaching(意味影响深远的,波及广泛的)的滤波器创建的,这个滤波器会覆盖整个可见的半球范围,同时该滤波器还包含了余弦因子,如图10.39所示。图10.26中所展示的球面贴图与图10.40所展示的irradiance贴图相对应。图10.41则展示了一个实际使用中的irradiance贴图。

在这里插入图片描述

图10.40:从Grace大教堂球面贴图生成的irradiance贴图。左侧图像是原始的球面贴图。右侧图像则是通过将每个像素上半球范围内的颜色进行加权求和而得到的。

在这里插入图片描述

图10.41:使用irradiance贴图生成的人物光照,来自《死或生3》。

  irradiance环境贴图的访问和存储通常是与高光环境贴图或者高光反射贴图分开的,其访问和存储方式通常是一种视图无关的表示形式,例如立方体贴图,如图10.42所示。在访问这个立方体贴图的时候,会使用表面法线来检索irradiance值,而不是之前的反射观察向量。从irradiance环境贴图中获得的值会和漫反射率相乘,从高光环境贴图中获得的值会和镜面反射率相乘。通过在掠射角度下增加镜面反射率(可能也会降低漫反射率),还可以模拟菲涅尔效应。

在这里插入图片描述

图10.42:立方体贴图(左)及其过滤后的irradiance贴图(右)。

  由于生成irradiance环境贴图使用了非常宽的滤波器,因此很难通过采样来在运行时高效地创建它们。King 讨论了如何在GPU上使用卷积操作来创建irradiance贴图,他通过将环境贴图转换到频域(frequency domain),能够在2004年的硬件上,以超过300 FPS的速率来生成irradiance贴图。

  漫反射表面或者粗糙表面的过滤环境贴图可以以较低的分辨率进行存储,有时候也可以从相对较小的反射贴图中直接生成,例如一个每个面具有 64 × 64 64 × 64 64×64 纹素的立方体贴图。这种方法存在一个问题,将面光源渲染到如此小的纹理中,光线可能会“落在纹素之间的区域”,这会导致光线闪烁甚至完全消失。为了避免这个问题,Wiley和Scheuermann 建议在渲染动态环境贴图的时候,使用较大的“卡片(即有纹理的矩形)”来表示这样的面光源。

  在光泽反射的情况下,动态光源也可以被添加到预过滤的irradiance环境贴图中。Brennan 给出了一种廉价的方法,想象现在有一个单一光源的irradiance贴图,在光源的方向上,当光线直射到表面上的时候,radiance会达到最大值。给定表面法线(即给定纹素)的radiance会随着与光线夹角的余弦值而下降,并且在表面背对光源的地方达到0。GPU可以通过渲染一个半球,这个半球代表了余弦波瓣,以观察者为中心,半球的极点指向光源,从而快速地将这个光源的贡献添加到现有的irradiance贴图中。

球谐 irrandance

  上文中,我们讨论了仅使用贴图(例如立方体贴图)来表示irradiance环境贴图,还有一些其他表示方法也可以用来存储环境irradiance信息,如章节10所述。尤其是球谐函数,使用它来表示irradiance环境贴图是相当流行的,因为环境光照中的irradiance是平滑的。将radiance与余弦波瓣进行卷积,可以从环境贴图中去除所有高频信息。

  Ramamoorthi和Hanrahan表明,仅使用前9个SH系数(每个系数都是一个RGB向量,因此我们需要存储27个浮点数)就可以以1%的误差来表示irradiance环境贴图。这样一来,任何irradiance环境贴图都可以表示为一个球面函数 E ( n ) E(\mathbf{n}) E(n),并使用方程10.21和方程10.23将其投影到9个RGB系数上。相比立方体贴图和抛物线贴图而言,这种表示形式更加紧凑;并且在渲染的过程中,可以通过一些简单的多项式计算来重建irradiance信息,而不是去读取和检索纹理。一般来说,如果irradiance环境贴图表示的是间接照明,那么只需要较少的精度即可,这在交互式应用中十分常见。在这种情况下,我们只使用常量基函数和三个线性基函数,即一共四个系数(四个RGB向量,共12个浮点数)就可以产生很好的结果了,因为间接光照本身往往就是低频的,它随着角度的变化很缓慢。

  Ramamoorthi和Hanrahan还指出[,通过将每个系数乘上一个常数,可以将入射radiance函数 L ( l ) L(\mathbf{l}) L(l)的SH系数,转换为irradiance函数 E ( n ) E(\mathbf{n}) E(n)的SH系数。这样做可以生成一种将环境贴图快速过滤为irradiance环境贴图的方法,通过将环境贴图投影到SH基底上,然后再将每个SH系数乘上一个常数即可完成。例如:King 的快速irradiance滤波就是这样实现的,其核心思想是:从radiance中计算irradiance,实际上相当于在入射radiance函数 L ( l ) L(\mathbf{l}) L(l)与clamped余弦函数 cos ⁡ ( θ i ) + \cos \left(\theta_{i}\right)^{+} cos(θi)+之间进行球面卷积。由于clamped余弦函数围绕球体的 z z z轴是旋转对称的,因此它在SH中具有一种特殊的形式:它的投影在每个频带中只有一个非零系数。而这个非零系数则对应了图10.21中间一列的基函数,它们也被称为球带谐波(zonal harmonic)。

  将一个一般的球面函数与旋转对称函数(例如clamp过的余弦函数)之间进行球面卷积,所产生结果是球面上的另一个函数,这种卷积操作可以在函数的SH系数上高效进行。卷积结果的SH系数等于两个函数SH系数的点积(乘法),再通过 4 π / ( 2 l + 1 ) \sqrt{4 \pi /(2 l+1)} 4π/(2l+1) 进行缩放,其中 l l l是频带指数(frequency band index)。irradiance函数 E ( n ) E(\mathbf{n}) E(n)的SH系数,等于radiance函数 L ( l ) L(\mathbf{l}) L(l)的系数乘以clamped余弦函数 cos ⁡ ( θ i ) + \cos \left(\theta_{i}\right)^{+} cos(θi)+的系数,再按照频带常数进行缩放。clamped余弦函数的前九个系数值很小,这也就解释了为什么只使用九个系数就足以表示irradiance函数 E ( n ) E(\mathbf{n}) E(n)。SH irradiance环境贴图可以使用这种方式来进行快速计算,Sloan 描述了一种高效的GPU实现。

在这里插入图片描述

图10.43:clamped余弦函数(红色)与包含九个系数的球谐函数近似(蓝色)。近似结果十分接近。请注意在 π / 2 π/2 π/2 π π π之间,蓝色曲线有轻微的下降和上升。

  这里还存在一个固有的近似值,因为尽管函数 E ( n ) E(\mathbf{n}) E(n)的高阶系数值很小,但是它们并不为零,如图10.43所示。虽然 π / 2 π/2 π/2 π π π之间的曲线会发生“摆动”,这在信号处理中被称为振铃(ringing),但是这种近似总体还是非常接近的。这种振铃现象通常会发生在用少量基函数来对具有高频部分的函数进行近似的时候。在 π / 2 π/2 π/2处将函数clamp为0,会带来一个急剧的变化,这意味着我们的clamped余弦函数具有无限大的信号频率。振铃现象在大多数情况下都是不明显的,但是在一些极端的光照条件下仍然可以看到这种现象,例如颜色的剧烈变化或者位于物体阴影附近的明亮斑点。如果irradiance环境贴图只是用来存储间接光照的话(通常会这么做),那么振铃现象就不太可能成为一个问题。还有一些预过滤方法可以最小化这个问题,如图10.44所示。

在这里插入图片描述

图10.44:左图:由振铃现象所引起的视觉瑕疵。右图:一种可能的解决方案是让原始函数变得更加平滑,这样它就可以避免振铃现象,这个过程被称为“窗口化(windowing)”。

  图10.45展示了直接导出的irradiance贴图,与使用包含九个系数的球谐函数的对比结果。这种SH表示可以在渲染的过程中,使用当前表面的法线 n \mathbf{n} n进行计算,也可以使用SH来快速创建一个立方体贴图或者抛物线贴图供之后进行使用。对于漫反射而言,这样的光照效果虽然很廉价,但是可以提供不错的视觉效果。

  动态渲染的立方体环境贴图可以被投影到SH基底上。由于立方体环境贴图是入射radiance函数的离散表示,因此方程10.21中对球面的积分就变成了对立方体贴图纹素值的求和:

k L j = ∑ t f j ( r [ t ] ) L [ t ] d ω [ t ] (10.40) k_{L j}=\sum_{t} f_{j}(\mathbf{r}[t]) L[t] d \omega[t] \tag{10.40} kLj=tfj(r[t])L[t]dω[t](10.40)

  其中 t t t是当前立方体贴图纹素的索引, r [ t ] \mathbf{r}[t] r[t]为指向当前纹素的方向向量, f j ( r [ t ] ) f_{j}(\mathbf{r}[t]) fj(r[t])是第 j j j个SH基函数在 r [ t ] \mathbf{r}[t] r[t]处的值, L [ t ] L[t] L[t]是存储在纹素中的radiance值, d ω [ t ] d \omega[t] dω[t]是该纹素所对应的立体角。Kautz 、King 和Sloan 描述了如何计算这个立体角 d ω [ t ] d \omega[t] dω[t]

  为了将radiance系数 k L j k_{L j} kLj转换为irradiance系数,需要将其乘以clamped余弦函数的缩放系数:

k E j = k cos ⁡ + j ′ k L j = k cos ⁡ + j ′ ∑ t f j ( r [ t ] ) L [ t ] d ω [ t ] (10.41) k_{E j}=k_{\cos ^{+} j}^{\prime} k_{L j}=k_{\cos ^{+} j}^{\prime} \sum_{t} f_{j}(\mathbf{r}[t]) L[t] d \omega[t] \tag{10.41} kEj=kcos+jkLj=kcos+jtfj(r[t])L[t]dω[t](10.41)

  其中 k E j k_{E j} kEj是irradiance函数 E ( n ) E(\mathbf{n}) E(n)的第 j j j个系数, k L j k_{L j} kLj是入射radiance函数 L ( l ) L(\mathbf{l}) L(l)的第 j j j个系数, k cos ⁡ + j ′ k_{\cos ^{+} j}^{\prime} kcos+j是clamped余弦函数 cos ⁡ ( θ i ) + \cos \left(\theta_{i}\right)^{+} cos(θi)+ 4 π / ( 2 l + 1 ) \sqrt{4 \pi /(2 l+1)} 4π/(2l+1) (其中 l l l是频带系数)进行缩放的第 j j j个系数。

  给定 t t t和立方体贴图的分辨率,对于每个基函数 f j ( ) f_j() fj(),系数 k cos ⁡ + j ′ f j ( r [ t ] ) d ω [ t ] k_{\cos ^{+} j}^{\prime} f_{j}(\mathbf{r}[t]) d \omega[t] kcos+jfj(r[t])dω[t]都是恒定的。这些基函数的系数可以离线预计算,并将其存储在立方体贴图中,它应当与将要渲染的动态环境贴图具有相同的分辨率。可以通过在每个颜色通道中打包一个单独的基函数系数,来减少所要使用的纹素数量。为了计算动态立方体贴图的irradiance系数,需要将相应基函数系数贴图中的纹素,与动态立方体贴图中的纹素相乘,并对结果进行求和。除了关于动态irradiance立方体贴图的相关信息,King 还提供了在GPU上实现SH投影的细节。

  动态光源还可以被添加到现有的SH irradiance环境贴图中。这种合并是通过计算光线irradiance贡献的SH系数,并将其添加到现有系数中来实现的,这样做可以避免对整个irradiance环境贴图进行重新计算。这是一个十分简单的过程,因为点光源、圆盘光源和球形光源的系数都存在简单的解析表达式,对这些系数求和的效果与对irradiance求和的效果相同。对于那些与 z z z轴对齐的光源,通常这些表示都是以球带谐波(zonal harmonic)的方式给出的,然后可以通过旋转操作,来将光源定位到任意的方向上。球带谐波的旋转是SH旋转的一种特殊情况,它的效率更高,只需要进行一个点积操作即可,而不需要执行一个完整的矩阵变换。对于具有复杂形状的光源,可以先将它们绘制到一个图像中,然后再将图像数值投影到SH基底上,从而获得这些光源所对应的系数。对于物理天空模型这个特殊情况,Habel 展示了Preetham天光在球谐函数中的一种直接扩展。

  能够将常见的分析光源很容易地投影到SH中,这一点也是很重要的,因为通常环境光照会被用来代替远处或者较弱的光源,其中一个重要的例子就是补光灯(fill light)。在渲染中,这些光源会被放置在场景的特殊位置上,用于模拟场景中的间接光照,即被表面反弹的光线。这些补光灯通常不会计算高光效果,尤其是当这些光源在物理尺寸上相对于着色物体而言很大,并且相对于场景中的其他光源而言相对昏暗的时候,这些因素会使得它们的高光变得更加分散,在场景中不那么明显。这种类型的光源与在现实世界中的电影光照和视频光照有相似之处,在现实世界中,会使用一些补光灯来在阴影中添加一些照明,使得阴影看起来没有那么黑。

  在球谐函数空间中,也可以简单地进行相反的推导,即从投影在SH上的radiance中,提取出解析光源。在Sloan 对SH技术的研究中,给定一个已知轴的方向光,他展示了如何从SH irradiance表示中计算出光源应当具有的强度,来使得其自身与编码irradiance之间的误差最小化。

  在他之前的工作中,Sloan展示了如何在仅使用第一个(线性)频段系数的情况下,来选择一个接近最优的方向,该综述中还包含了一种用于提取多个方向光的方法。这项工作表明,对应光照求和而言,球谐函数是一个实用的基底。我们可以将多个光源同时投影到SH中,并提取出少量的方向光,这些光源可以对原来的光源集合进行较好地近似。lightcuts框架提供了一种聚合次要光源的一般性方法。

  虽然SH投影最常用于irradiance中,但是它也可以用来模拟有光泽的、视角相关的BRDF光照。Ramamoorthi和Hanrahan 描述了这样一种技术,他们在立方体贴图中没有存储单一的颜色,而是存储了使用视角相关的环境贴图进行编码的球谐函数投影系数。然而在实践中,这种技术要比我们之前所介绍的预过滤环境贴图方法占据更多的存储空间。Kautz等人推导出了一种更加经济的解决方案,该方法利用了SH系数的二维表格,但是这种方法只能用于相当低频的光照信息。

其他表示方法

  立方体贴图和球谐函数是irradiance环境贴图最常用的表示方法,但是还有一些其他的表示方法,如图10.45所示。

在这里插入图片描述

图10.45:irradiance编码的各种方式。从左到右分别是:使用环境贴图和对irradiance进行蒙特卡罗积分计算的漫反射光照;使用环境立方体(ambient cube)编码的irradiance;球谐函数;球面高斯函数;H-basis(它只能表示一个半球方向,因此指向下方的法线不会被着色)。

  许多irradiance环境贴图有两种主要颜色:顶部的天空颜色和底部的地面颜色。受到这一观察现象的启发,Parker等人提出了一种只使用两种颜色的半球光照(hemisphere lighting)模型,该方法假设上半球会发出一个均匀的radiance L s k y L_{sky} Lsky,下半球则会发出另一个均匀的radiance L g r o u n d L_{ground} Lground,在这种情况下,irradiance的积分是:

E = { π ( ( 1 − 1 2 sin ⁡ θ ) L s k y + 1 2 sin ⁡ θ L ground  ) ,  where  θ < 9 0 ∘ π ( 1 2 sin ⁡ θ L s k y + ( 1 − 1 2 sin ⁡ θ ) L ground  ) ,  where  θ ≥ 9 0 ∘ (10.42) E=\left\{\begin{array}{ll}\pi\left(\left(1-\frac{1}{2} \sin \theta\right) L_{\mathrm{sky}}+\frac{1}{2} \sin \theta L_{\text {ground }}\right), & \text { where } \theta<90^{\circ} \\[2mm] \pi\left(\frac{1}{2} \sin \theta L_{\mathrm{sky}}+\left(1-\frac{1}{2} \sin \theta\right) L_{\text {ground }}\right), & \text { where } \theta \geq 90^{\circ}\end{array}\right. \tag{10.42} E={π((121sinθ)Lsky+21sinθLground ),π(21sinθLsky+(121sinθ)Lground ), where θ<90 where θ90(10.42)

  其中方程中的 θ θ θ是表面法线与天空半球轴之间的夹角。Baker和Boyd提出了一个计算速度更快的近似方程,Taylor 对其进行了描述:

E = π ( 1 + cos ⁡ θ 2 L s k y + 1 − cos ⁡ θ 2 L g r o u n d ) (10.43) E=\pi\left(\frac{1+\cos \theta}{2} L_{\mathrm{sky}}+\frac{1-\cos \theta}{2} L_{\mathrm{ground}}\right) \tag{10.43} E=π(21+cosθLsky+21cosθLground)(10.43)

  方程10.43在天空和地面之间进行了线性插值,使用 ( cos ⁡ θ + 1 ) / 2 (\cos \theta+1) / 2 (cosθ+1)/2作为插值因子。其中 cos ⁡ θ \cos \theta cosθ通常可以通过向量点积来进行快速计算,并且当天空半球轴与某个基本轴(例如 y y y轴或者 z z z轴)重合的时候, cos ⁡ θ \cos \theta cosθ实际上根本不需要计算,因为它就等于法线 n \mathbf{n} n的某个世界空间的坐标分量。这个近似结果与原结果相当接近,而且速度要快得多,因此对于大多数应用而言,它比原本完整的表达式更加好用。

  Forsyth 提出了一种廉价且灵活的光照模型,被称为三重光源(trilight),其中包括了定向光照、双向光照、半球光照,还有作为特殊情况的环绕光照(wrap lighting)。

  Valve最初使用了环境立方体来表示irradiance。一般来说,我们所看到的所有球面函数表示方法,都可以用于预计算的irradiance。对于irradiance函数所表示的低频信号,我们知道SH是一个很好的近似。我们倾向于使用特殊的方法来简化或者使用比球谐函数更少的存储空间。

  如果我们想计算遮挡和其他全局光照效果,或者想整合光泽反射,就需要能够表达高频信号的复杂的表示方法。将所有的相互作用考虑在内,并对光照结果进行预计算,这个思想被称为预计算radiance传输(precomputed radiance transport,PRT),我们将在章节11中进行详细讨论。能够捕获光泽照明的高频信号的光照方法,也称为全频率(all-frequency)光照,在这种情况下经常会使用小波(wavelet)表示来作为压缩环境贴图的手段,并以一种与之前所介绍的球谐函数相类似的方式,来设计高效的运算方法。Ng等人展示了使用Haar小波来对irradiance环境映射进行推广,从而对自阴影效应进行建模。他们在小波基底中存储环境贴图以及在物体表面上变化的shadowing函数。这种表示十分值得注意,因为它相当于对环境立方体贴图进行了变换,在每个立方体表面上执行二维的小波投影,因此它也可以被视为一种立方体贴图的压缩技术。

误差来源

  为了正确地进行着色计算,我们必须在非定点光源上计算积分。在实践中,这一要求意味着,我们可以根据所计算光源的属性,采用许多不同的技术。实时引擎通常会以解析方式来对一些重要的光源进行建模,对光源照亮区域计算近似积分,并通过阴影贴图来计算遮挡信息。而所有其他光源(远距离光源、天光、补光和表面反弹光源),通常都会使用环境立方体贴图来表示高光分量,使用球面基底来表示漫反射irradiance。

  使用这种混合照明技术意味着,我们永远不会直接使用给定的BRDF模型,而是使用具有不同程度误差的近似值。有时候BRDF近似是显式的,因为我们对中间模型进行了拟合,从而计算光照积分,LTC就是这样一个例子。但是在其他时候,我们所构建的近似值只有在某些条件(通常很少)下,对于给定的BRDF才是精确的,在大多数情况下都会出现误差,预过滤立方体贴图就属于这一类。

  在开发实时着色模型的时候,需要考虑一个重要因素,即确保不同形式光照之间的差异不明显。从视觉上看,来自不同表示的连贯光照效果,甚至可能要比每种表示的绝对近似误差更加重要。

  遮挡对于真实感渲染而言也很重要,因为在没有光线的地方出现“漏光”现象,在视觉上通常要比在应当有光的地方没有光更加明显。大多数面光源表示对于阴影而言都是很难处理的,在如今,即使使用了各种阴影“软化”技术(章节7),也没有任何一种实时阴影技术能够准确考虑光源的形状。我们计算了一个标量因子,当物体投射阴影的时候,我们将其相乘以减少给定光源的贡献值,这实际上是错误的,在使用BRDF进行积分的时候,我们应当考虑到这种遮挡所带来的影响。这对于环境光照而言尤其困难,因为我们没有一个明确的、主要的光源方向,因此无法使用任何精确光源的阴影技术。

在这里插入图片描述

图10.46:电影行业中的人工照明。

  即使我们已经看到了一些相当先进的光照模型,但是请记住,它们都不是对现实世界光照来源的精确表示,例如:在环境光照中,我们会假设radiance来自于无限远处,但是现实中这是不可能的。而且,我们看到的所有解析光源都基于了这样一个更加强势的假设:光源表面上的每个点,都会均匀地向半球方向上发出radiance。但是在实践中,这种假设也是一种可能的误差来源,因为真实世界中的光源往往具有很强的方向性。在摄影照明和电影照明中,被称为镜头挡光板(gobo)、剪影遮光片(cuculori)或者cookies的特制蒙版和滤镜,经常被用来实现某些艺术效果。如图10.46所示,摄影师Gregory Crewdson所拍摄的照片,展示了电影光照的复杂情况。为了限制光源的照明角度,同时保持大面积的光线发射,可以在大型发光面板(即所谓的柔光箱)前面添加栅格化的黑色屏蔽材料,这种装置被称作honeycombs(蜂窝)。光源的外壳处也会使用复杂的镜面和反光板,例如:室内照明、汽车前灯和手电筒等。如图10.47所示,这些光学系统会在远离其物理中心的地方,生成一个或者多个发射光线的虚拟发射器,在进行光源衰减计算的时候,也应当考虑到这个偏移。

在这里插入图片描述

图10.47:相同的圆盘光源有着两种不同的发射方式。左边:圆盘上的每一点都均匀地向外半球发射光线。右边:radiance集中在圆盘法线周围的波瓣上。

  请注意,我们始终应当在一个面向感知的、面向结果的框架中对这些误差进行评估,除非我们的目标是进行预测渲染,即精确可靠地模拟真实世界的表面外观。在艺术家手中,即使某些简化并不真实,但是仍然可以生成有用并且富有表现力的光照效果。当这些基于物理的模型能够使艺术家更容易创建视觉可信的图像时,那么它们就是有用的,因为我们的最终目标是渲染出令人信服的图像,而不是这些物理模型本身。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值