本文继续对《UnityShader入门精要》——冯乐乐 第十八章 基于物理的渲染 进行学习
在https://github.com/candycat1992/Unity_Shaders_Book中,冯乐乐给出了2019年改版后的第18章,本文基于此版本进行学习。
在上面的内容中,我们首先介绍了 PBS 实现的数学和理论基础,并简单概括了 Unity 中Standard Shader 的实现原理,以及如何使用它来为不同类型的物体调整适合它们的材质参数。随后,我们通过一个更加复杂的场景,来展示如何在 Unity 中使用环境光照、实时光源、反射探针以及 Standard Shader 来渲染一个基于物理渲染的场景。但我们相信,读者在读完后仍有很多困惑,考虑到内容的连贯性,我们未能在文中对某些概念进行展开。在本节中,我们将对一些重要的概念进行更为深入地解释。
一、什么是全局光照
在上面的内容中,我们可以发现全局光照对得到真实的渲染结果有着举足轻重的作用。全局光照,指的就是模拟光线是如何在场景中传播的,它不仅会考虑那些直接光照的结果,还会计算光线被不同的物体表面反射而产生的间接光照。在使用基于物理的着色技术时,当渲染表面上一点时,我们需要计算该点的半球范围内所有会反射到观察方向的入射光线的光照结果,这些入射光线中就包含了直接光照和间接光照。
通常来讲,这些间接光照的计算是非常耗时间的,通常不会用在实时渲染中。一个传统的方法是使用光线追踪,来追踪场景中每一条重要的光线的传播路径。使用光线追踪能得到非常出色的画面效果,因此,被大量应用在电影制作中。但是,这种方法往往需要大量时间才能得到一帧,并不能满足实时的要求。
Unity 采用了 Enlighten 解决方案来让全局光照能够在各种平台上有不错的性能表现。事实上,Enlighten 也已经被集成在虚幻引擎(Unreal Engine)中,它已经在很多 3A 大作中展现了自身强大的渲染能力。总体来讲,Unity 使用了实时+预计算的方法来模拟场景中的光照。其中,实时光照用于计算那些直接光源对场景的影响,当物体移动时,光照也会随之发生变化。但正如我们之前所说,实时光照无法模拟光线被多次反射的效果。为了得到更加真实的渲染效果,Unity 又引入了预计算光照的方法,使得全局光照甚至在一些高端的移动设备上也可以达到实时的要求。
预计算光照包含了我们常见的光照烘焙,也就是指我们把光源对场景中静态物体的光照效果提前烘焙到一张光照纹理中,然后把这张光照纹理直接贴在这些物体的表面,来得到光照效果。
这些光照纹理不仅存储了直接光照的结果,还包含了那些由物体反射得到的间接光照。但是,这些光照纹理无法在游戏运行时不断更新,也就是说,它们是静态的。不过这种方法的确为移动平台的复杂光照模拟提供了一个有效途径。以上提到的这些技术很多读者都已非常熟悉,并可能已经在实际工作中大量使用了它们。
由于静态的光照烘焙无法在光照条件改变时更新物体的光照效果,因此,Unity 使用了预计算实时全局光照(Precomputed Realtime GI)为我们提供了一个解决途径,来动态地为场景实时更新复杂的光照结果。正如我们之前看到的,使用这种技术我们可以让场景中的物体包含丰富的全局光照效果,例如多次反射等,并且这些计算都是实时的,可以随着光源和物体的移动而发生变化。这是使用之前的实时光照或烘焙光照所无法实现的。
那么,这些是如何实现的呢?它们实际上都利用了一个事实— 一旦物体和光源的位置被固定了,这些物体对光线的反弹路径以及漫反射光照(我们假设漫反射光照在各个方向的分布是相同的)也是固定的,也就是说是和摄像机无关的。因此,我们可以使用预计算方法来把这些物体之间的关系提前计算出来,而在实时运行时,只要光源的位置(光源的颜色是可以实时变化的)不变,即便改变了光源颜色和强度、物体材质属性(指的是漫反射和自发光相关的属性),这些信息就一直有效,不需要实时更新。
在预计算阶段,Enlighten 会在由所有静态物体组成的场景上,进行简化的“光线追踪”过程。在这个过程中 Enlighten 会自动把场景分割成很多个子系统,它并不是为了得到精确的光照效果,而是为了得到场景中物体之间的关系。需要注意的是,这些预计算都是在静态物体上进行的,因此,为了利用上述的预计算方法,我们至少需要把场景中的一个物体标识为 Static(至少需要把 Lightmap Static 勾选上)。
一个例外是物体的高光反射,这是和摄像机的位置相关的,Unity 的解决方案是使用反射探针,正如我们之前看到的那样。对于动态移动的物体来说,我们可以使用光照探针来模拟它的光照环境。因此,在实时运行时,Unity 会利用预计算得到的信息来计算光照信息,并把它们存储在额外的光照纹理、光照探针或 Cubemap 中,再和物体材质进行必要的光照计算,得到最后的渲染效果。
Unity 全新的全局光照解决方案可以大大提高一些基于 PC/游戏机等平台的大型游戏的画面质量,但如果要在移动平台上使用仍需要非常小心它的性能。一些低端手机是不适合使用这种比较复杂的基于物理的渲染,不过,Unity 会在后续的版本中持续更新和优化。而且随着手机硬件的发展,未来在移动平台上大量使用 PBS 也已经不再是遥不可及的梦想了。更多关于 Unity 中全局光照的内容,读者可以在 Unity 官方手册的全局光照(http://docs.unity3d.com/Manual/GIIntro.html)一文中找到更多内容,本章最后的扩展阅读部分也会给出更多的学习资料。
二、什么是伽马校正
我们在 18.3.4 节中讲到,要想渲染出更符合真实光照环境的场景就需要使用线性空间。而Unity 默认的空间是伽马空间,在伽马空间下进行渲染会导致很多非线性空间下的计算,从而引入了一些误差。而要把伽马空间转换到线性空间,就需要进行伽马校正(Gamma Correction)。
相信很多读者都听过伽马校正这个名词,但对于伽马校正是什么、为什么要有它、怎么使用它都存在着很多疑问。伽马校正中的伽马一词来源伽马曲线。通常,伽马曲线的表达式如下:
image.png
其中指数部分的发音就是伽马。最开始的时候,人们使用伽马曲线来对拍摄的图像进行伽马编码(gamma encoding)。事情的起因可以从在真实环境中拍摄一张图片说起。摄像机的原理可以简化为,把进入到镜头内的光线亮度编码成图像(例如一张 JEPG)中的像素。如果采集到的亮度是 0,像素就是 0 亮度是 1,像素就是 1 亮度是 0.5,像素就是 0.5。如果我们只用 8 位空间来存储像素的每个通道的话,这意味着 0~1 区间可以对应 256 种不同的亮度值。但是,后来人们发现,人眼有一个有趣的特性,就是对光的灵敏度在不同亮度上是不一样的。在正常的光照条件下,人眼对较暗区域的变化更加敏感,如图 18.18 所示。
图18.18 人眼更容易感知暗部区域的变换,而对较亮区域的变化比较不敏感
图 18.18 说明了一件事情,亮度上的线性变化对人眼感知来说是非均匀的。Youtube 上有一个名为 Color is Broken的非常有趣的视频,在这个视频中,作者用了一个非常生动的例子来说明这个现象。当一个屋子的光照由一盏灯增加到两盏灯的时候,人眼对这种亮度变化的感知性要远远大于从101 盏灯增加到 102 盏灯的变化,尽管从物理上来说这两种变化基本是相同的。
那么,这和之前讲的拍照有什么关系呢?如果使用 8 位空间来存储每个通道的话,我们仍然把0.5 亮度编码成值为 0.5 的像素,那么暗部和亮部区域我们都使用了 128 种颜色来表示,但实际上,对亮部区域使用这么多颜色是种存储浪费。一种更好的方法是,我们应该把把更多的空间来存储更多的暗部区域,这样存储空间就可以被充分利用起来了。摄影设备如果使用了 8 位空间来存储照片的话,会使用大约为 0.45 的编码伽马来对输入的亮度进行编码,得到一张编码后的图像。因此,图像中 0.5 像素值对应的亮度其实并不是 0.5,而大约为 0.22。这是因为:
image.png
如上所见,对拍摄图像使用的伽马编码使得我们可以充分利用图像的存储空间。但当把图片放到显示器里显示时,我们应该对图像再进行一次解码操作,使得屏幕输出的亮度和捕捉到的亮度是符合线性的。这时,人们发现了一个奇妙的巧合—CRT 显示器本身几乎已经自动做了这个解码操作!这又从何说起呢?在早期,CRT(Cathode Ray Tube,阴极射线管)几乎是唯一的显示设备。这类设备的显示机制是,使用一个电压轰击它屏幕上的一种图层,这个图层就可以发亮,我们就可以看到图像了。但 CRT 显示器有一个特性,它的输入电压和显示出来的亮度关系不是线性的,也就是说,如果我们把输入电压调高两倍,屏幕亮度并没有提高两倍。我们把显示器的这个伽马曲线称为显示伽马(diplay gamma)。
非常巧合的是,CRT 的显示伽马值大约就是编码伽马的倒数。CRT 显示器的这种特性,正好补偿了图像捕捉设备的伽马曲线,人们想,“天呐,太棒了,我们不需要做任何调整就可以让拍摄的图像在电脑上看起来和原来的一样了!”虽然现在 CRT设备很少见了,并且后来出现的显示设备有着不同的伽马响应曲线,但是,人们仍在硬件上做了调整来提供兼容性。 图 18.19 展示了编码伽马和显示伽马在图像捕捉和显示时的作用。
图18.19 编码伽马和显示伽马
随后,微软联合爱普生、惠普提供了 sRGB 颜色空间标准,推荐显示器的显示伽马值为 2.2,并配合 0.45 的编码伽马就可以保证最后伽马曲线之间可以相互抵消(因为 2.2×0.45≈1)。绝大多数的摄像机、PC 和打印机都使用了上述的 sRGB 标准。
读到现在,读者可能还是有所疑问,这和渲染有什么关系?答案是关系很大。事实上,由于游戏界长期以来都忽视了伽马校正的问题,造成了我们渲染出来的游戏总是暗沉沉的,总是和真实世界不像。由于编码伽马和显示伽马的存在,我们一不小心就可能在非线性空间下进行计算,或是使得输出的图像是非线性的。
对于输出来说,如果我们直接输出渲染结果而不进行任何处理,在经过显示器的显示伽马处理后,会导致图像整体偏暗,出现失真的状况。我们在本书资源的 Scene_18_4_2_a 显示了伽马对光照效果的影响。在场景 Scene_18_4_2_a 中,我们放置了一个球体,并把场景中的环境光照设为全黑,再把平行光的方向设置为从上方直接射到球体表面,球体使用的材质为内置的漫反射材质。图 18.20 显示了在伽马空间和线性空间下的渲染结果。
图18.20 左图:伽马空间下的渲染结果。右图:线性空间下的渲染结果
从图 18.20 可以看出,伽马空间下的渲染结果整体偏暗,一些读者甚至认为这看起来更加正确。然而,实际此时屏幕输出的亮度和球面的光照结果并不是线性的。假设球面上有一点 A,它的法线和光线方向成 60°,还有一点 B,它的法线和光线方向成 90°。那么,在 Shader 中计算漫反射光照时,我们会得出 A 的输出是(0.5, 0.5, 0.5),B 的输出是(1.0, 1.0, 1.0)。在图 18.20 的左图中,我们没有进行伽马校正,因此,由于显示器存在显示伽马就引入了非线性关系,也就是说 A点的亮度其实并不是 B 亮度的一半,而约为它的 1/4。在图 18.20 的右图中,我们使用了线性空间,Unity 会在把像素写入颜色缓冲前进行一次伽马校正,来抵消屏幕的显示伽马的作用,此时得到屏幕亮度才是真正跟像素值成正比的。
伽马的存在还会对混合造成影响。在场景 Scene_18_4_2_b 中演示了一个简单的场景来说明这个现象。在场景 Scene_18_4_2_b 中,我们放置了 3 个互相重叠的圆,它们使用的材质均为简单的透明混合材质,并使用了一个边界模糊的圆作为输入纹理。场景在伽马空间和线性空间下的效果如图 18.21 所示。
图18.21 左图:伽马空间下的混合结果。右图:线性空间下的混合结果
在图 18.21 左图所示的伽马空间下,我们可以看到在绿色和红色的混合边界处出现了不正常的蓝色渐变。而正确的混合结果应该是如图 18.21 右边图所示的从绿色到红色的渐变。除此之外,我们也可以看到图 18.21 左边图中交叉的边界似乎都变暗了。这是因为在混合后进行输出时,显示器的显示伽马导致接缝处颜色变暗。
实际上,渲染中非线性输入最有可能的来源就是纹理。为了充分利用存储空间,大多数图像文件都进行了提前的校正,即已经使用了一个编码伽马对像素值编码。但这意味着它们是非线性的,如果我们在 Shader 中直接使用纹理采样值就会造成在非线性空间的计算,使得结果和真实世界的结果不一致。我们在使用多级渐远纹理(mipmaps)时也需要注意。如果纹理存储在非线性空间中,那么在计算多级渐远纹理时就会在非线性空间里计算。由于多级渐远纹理的计算是种线性计算—即采样的过程,需要对某个方形区域内的像素取平均值,这样就会得到错误的结果。正确的做法是,我们要把非线性的纹理转换到线性空间后再计算多级渐远纹理。
如上所说,伽马的存在使得我们很容易得到非线性空间下的渲染结果。在游戏渲染中,我们应该保证所有的输入都被转换到了线性空间下,并在线性空间下进行各种光照计算,最后在输出前通过一个编码伽马进行伽马校正后再输出到颜色缓冲中。Untiy 的颜色空间设置就可以满足我们的需求。
当我们选择伽马空间时,实际上就是“放任模式”,不会对 Shader 的输入进行任何处理,即使输入可能是非线性的;也不会对输出像素进行任何处理,这意味着输出的像素会经过显示器的显示伽马转换后得到非预期的亮度,通常表现为整个场景会比较昏暗。
当选择线性空间时,Unity 会把输入纹理设置为 sRGB 模式,在这种模式下,硬件在对纹理进行采样时会自动将其转换到线性空间中;并且,GPU 会在 Shader 写入颜色缓冲前自动进行伽马校正或是保持线性在后面进行伽马校正,这取决于当前的渲染配置。
如果我们开启了 HDR(见 18.4.3 节)的话,渲染就会使用一个浮点精度的缓冲。这些缓冲有足够的精度不需要我们进行任何伽马校正,此时所有的混合和屏幕后处理都是在线性空间下进行的。当渲染完成要写入显示设备的后备缓冲区(back buffer)时,再进行一次最后的伽马校正。如果我们没有使用 HDR,那么 Unity 就会把缓冲设置成 sRGB格式,这种格式的缓冲就像一个普通的纹理一样,在写入缓冲前需要进行伽马校正,在读取缓冲时需要再进行一次解码操作。如果此时开启了混合(像我们之前的那样),在每次混合时,硬件会首先把之前颜色缓冲中存储的颜色值转换回线性空间中,然后再与当前的颜色进行混合,完成后再进行伽马校正,最后把校正后的混合结果写入颜色缓冲中。这里需要注意,透明通道是不会参
与伽马校正的。
然而,Unity 的线性空间并不是所有平台都支持的,例如,移动平台就无法使用线性空间。此时,我们就需要自己在 Shader 中进行伽马校正。对非线性输入纹理的校正代码通常如下:
float3 diffuseCol = pow(tex2D( diffTex, texCoord ), 2.2 );
在最后输出前,对输出像素值的校正代码通常如下面这样:
fragColor.rgb = pow(fragColor.rgb, 1.0/2.2);return fragColor;
但是,手工对输出像素进行伽马校正会在使用混合时出现问题。这是因为,校正会导致写入颜色缓冲内的颜色是非线性的,这样混合就发生在非线性空间中。一种解决方法是,在中间计算时不要对输出颜色值进行伽马校正,但在最后需要进行一个屏幕后处理操作来对最后的输出进行伽马校正,也就是说我们需要保证伽马校正发生在渲染的最后一步中,但这可能会造成一定的性能损耗。
你会说,伽马这么麻烦,什么时候可以舍弃它呢?如果有一天我们对图像的存储空间能够大大提升,通用的格式不再是 8 位时,例如是 32 位时,伽马也许就会消失。因为,我们有足够多的颜色空间可以利用,不需要为了充分利用存储空间进行伽马编码的工作了。这就是我们下面要讲的 HDR。
三、什么是 HDR
在使用基于物理的渲染时,我们经常会听到一个名词就是 HDR。HDR是 High Dynamic Range的缩写,即高动态范围,与之相对的是低动态范围(Low Dynamic Range,LDR)。那么这个动态范围是指什么呢?
通俗来讲,动态范围指的就是最高的和最低的亮度值之间的比值。在真实世界中,一个场景中最亮和最暗区域的范围可以非常大,例如,太阳发出的光可能要比场景中某个影子上的点的亮度要高出几万倍,这些范围远远超过图像或显示器能够显示的范围。通常在显示设备使用的颜色缓冲中每个通道的精度为 8 位,意味着我们只能用这 256 种不同的亮度来表示真实世界中所有的亮度,因此,在这个过程中一定会存在一定的精度损失。
早期的拍摄设备利用人眼的特点,使用了伽马曲线来对捕捉到的图像进行编码,尽可能充分地利用这些有限的存储空间,这点我们已经在 18.4.2 节解释过了。然而,HDR 的出现给我们带来了新的希望,HDR 使用远远高于 8 位的精度(如 32 位)来记录亮度信息,使得我们可以表示超过 0~1 内的亮度值,从而可以更加精确地反映真实的光照环境。尽管我们最后还是需要把信息转换到显示设备使用的 LDR 内,但中间的计算却可以让我们得到更加真实可信的效果。
Nvidia 曾总结过使用 HDR 进行渲染的动机:让亮的物体可以真的非常亮,暗的物体可以真的非常暗,同时又可以看到两者之间的细节。
使用 HDR 来存储的图像被称为高动态范围图像(HDRI),例如,我们在 18.3 节中就是使用了一张 HDRI 图像来作为场景的 Skybox。这样的 Skybox 可以更加真实地反映物体周围的环境,从而得到更加真实的反射效果。不仅如此,HDR 对与光照叠加也有非常重要的作用。如果我们的场景中有很多光源或是光源强度很大,那么一个物体在经过多次光照渲染叠加后最终得到的光照亮度很可能会超过 1。如果没有使用 HDR,这些超过 1 的部分全部会截取到 1,使得场景丢失了很多亮部区域的细节。但如果开启了 HDR,我们就可以保留这些超过范围的光照结果,尽管最后我们仍然需要把它们转换到 LDR 进行显示,但我们可以使用色调映射(tonemapping)技术来控制这个转换的过程,从而允许我们最大限度地保留需要的亮度细节。
HDR 的使用可以允许我们在屏幕后处理中拥有更多的控制权。例如,我们常常同时使用 HDR和 Bloom 效果。我们曾在 12.5 节解释了 Bloom 特效的实现原理,Bloom 效果需要检测屏幕中亮度大于某个阈值的像素,把它们提取出来后进行模糊,再叠加到原图像中。但是,如果不使用 HDR的话,我们只能使用小于 1 的阈值来提取需要的像素,但很多时候我们实际上是需要提取那些非常亮的区域,例如车窗上对太阳的强烈反光。由于没有使用 HDR,这些值实际上很可能和街上一些颜色偏白的区域几乎一样,造成不希望的区域也会出现泛光的效果。如果我们使用 HDR,这些就都可以解决了,我们只需要使用超过 1 的阈值来只提取那些非常亮的区域即可。
总体来说,使用 HDR 可以让我们不会丢失高亮度区域的颜色值,提供了更真实的光照效果,并为一些屏幕后处理提供了更多的控制能力。但 HDR 也有自身的缺点,首先由于使用了浮点缓冲来存储高精度图像,不仅需要更大的显存空间,渲染速度会变慢,除此之外,一些硬件并不支持 HDR。而且一旦使用了 HDR,我们无法再利用硬件的抗锯齿功能。事实上,在 Unity 中如果我们同时打开了硬件的抗锯齿(在 Edit → Project Settings → Quality → Anti Aliasing 中打开)和摄像机的 HDR,Unity 会发出警告来提示我们由于开启了抗锯齿,因此,无法使用 HDR 缓冲。尽管如此,我们可以使用基于屏幕后处理的抗锯齿操作来弥补这一点。
在 Unity 中使用 HDR 也非常简单,我们可以在 Camera 组件面板中打开 HDR 选项即可。此时,场景就会被渲染到一个 HDR 的图像缓冲中,这个缓冲的精度范围可以远远超过 0~1。最后,我们可以再使用一个色调映射的屏幕后处理脚本来把 HDR 图像转换到 LDR 图像进行显示。读者可以在 Unity 官方手册中的高动态范围渲染一节(http://docs.unity3d.com/Manual/HDR.html)以及本章最后的扩展阅读中找到更多的内容。
四、那么,PBS 适合什么样的游戏
在把 PBS 引入当前的游戏项目之前,我们需要权衡一下它的优缺点。需要再次提醒读者的是,PBS 并不意味着游戏画面需要追求和照片一样真实的效果。事实上,很多游戏都不需要刻意去追求与照片一样的真实感,玩家眼中的真实感大多也并不是如此。PBS 的优点在于,我们只需要一个万能的 Shader 就可以渲染相当一大部分类型的材质,而不是使用传统的做法为每种材质写一个特定的 Shader。同时,PBS 可以保证在各种光照条件下,材质都可以自然地和光源进行交互,而不需要我们反复地调整材质参数。
然而,在使用 PBS 时我们也需要考虑到它带来的代价。如上面提到的,PBS 往往需要更复杂的光照配合,例如大量使用光照探针和反射探针等。而且 PBS 也需要开启 HDR 以及一些必不可少的屏幕特效,例如抗锯齿、Bloom 和色调映射,如果这些屏幕特效对当前游戏来说需要消耗过多的性能,那么 PBS 就不适合当前的游戏,我们应该使用传统的 Shader 来渲染游戏。
使用 PBS对美工人员来说同样是个挑战。美术资源的制作过程和使用传统的 Shader 有很大不同,普通的法线纹理+高光反射纹理的组合不再适用,我们需要创建更细腻复杂的纹理集,包括金属值纹理、高光反射纹理、粗糙度纹理、遮挡纹理,有些还需要使用额外的细节纹理来给材质添加更多的细节表面。除了使用图片扫描的传统辅助方法外,这些纹理的制作通常还需要更专业的工具来绘制,例如 Allegorithmic Substance Painter 和 Quixel Suite。
五、扩展阅读
Unity 官方提供了很多学习 PBS 的资料。在 Unity 官方博客中的全局光照一文①中,简明地阐述了全局光照的解决方案。在另外两篇博客②③中,介绍了 Standard Shader 的用法和注意事项。在Unity 官方教程的 Graphics 分项④下,也有很多关于 PBS 的教程,例如,在预计算实时 GI 的系列文章⑤中,介绍了 Unity 5 的 Enlighten 系统中预计算实时 GI 的实现原理,以及如何正确地把它应用在大型项目中来提升画面效果并减少烘焙时间。在 Unity 5 的光照概览⑥中,介绍了 Unity 5 中使用的各种全局光照技术;在 Standard Shader 的视频教程⑦中,Unity 介绍了 Standard Shader 的基本用法以及和光照之间的配合。
官方项目也是很好的学习资料。Unity 开放了基于物理着色器的示例项目 Viking Village 以及两个更小的示例项目 Shader Calibration Scene 和 Corridor Lighting Example 来着重介绍如何使用 Unity 5 全新的 Standard Shader 和全局光照系统。看过 Unity 5 宣传视频的读者想必对 Unity 5制作出来的电影短片 The Blacksmith 印象深刻,尽管 Unity 没有开放出完整的工程,但把许多关键的技术实现放到了资源商店里,例如,人物角色使用的 Shader、头发使用的 Shader、人物阴影、大气次散射等。与之类似的还有 Adam 的相关资源⑧,这些都是非常好的学习资料,读者可以在Asset Store 上找到并下载这些资源。
① https://blogs.unity3d.com/2014/09/18/global-illumination-in-unity-5/
② https://blogs.unity3d.com/2015/02/18/working-with-physically-based-shading-a-practical-approach/
③ https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/
④ https://unity3d.com/learn/tutorials/topics/graphics
⑤ https://unity3d.com/learn/tutorials/topics/graphics/introduction-precomputed-realtime-gi
⑥ https://unity3d.com/learn/tutorials/topics/graphics/lighting-overview
⑦ https://unity3d.com/learn/tutorials/topics/graphics/standard-shader
⑧ https://blogs.unity3d.com/2016/11/01/adam-demo-executable-and-assets-released/
近年来,Unity 在 Unite 和 SIGGRAPH 等大会上也分享不少关于 PBS 的技术资料。
在 Unite 2016 上,Mathieu Muller 在他的演讲 A Step by Step Guide to Making a Scene That Looks Like The Adam Demo 中简要介绍了如何使用 Unity 开放出来的 Adam 资源在 Unity 5 中一步步渲染出视频中的一个画面;在 Unite 2015 上的 Advanced Global Illumination in Unity 5 演讲中,官方人员简要介绍了全局光照的相关概念以及如何使用 Enlighten 来得到高质量的实时渲染效果;来自Allegorithmic 的技术人员在 Unite 2015 上做了名为 PBR Workflows & Guidelines for Unity 5 的演讲,他介绍了如何使用 Substance 系列产品来制作适合于 PBS 的高质量贴图;
在 Unite 2014 会议上,Anton Hand 在他的演讲(名称:Best Practices For Physically Based Content Creation)中给出了很多关于如何创建 PBS 中使用的资源的最佳实践;Renaldas Zioma 和 Erland Krner 则在 Unite 2014 上讲解了如何在 Unity 5 中更加有效地使用 PBS(名称:Mastering Physically Based Shading)。
在 SIGGRAPH 2016 上,Eric Heitz 和 Stephen Hill 在他们名为 Real-Time Area Lighting: a Journey from Research to Production 的演讲中分享了如何实现实时面光源的渲染,这也是 Unity 的 Adam Demo 中使用的技术;Sébastien Lagarde 在 SIGGRAPH 2016 上介绍了 Unity 的技术人员是如何制作全景 HDRI 图像的(名称:An Artist-Friendly Workflow for Panoramic HDRI);
在SIGGRPAH 2015 上,来自 Unity 的技术人员分享了 The Blacksmith 的环境制作过程(名称:Authoring of Procedural Environments in “The Blacksmith”);Renaldas Zioma 在他的 SIGGRPAH 2015 演讲 Optimizing PBR for Mobile 中介绍了如何在移动平台上应用和优化 PBR。
如果读者希望更深入地学习 PBS 的理论和实践,可以在近年来的 SIGGRAPH 课程上找到非常丰富的资料。SIGGRAPH 自 2006 年起开始出现与 PBS 相关的课程,连续 5 年(2012~2016)在名为 Physically Based Shading in Theory and Practice 的课程中由来自各大游戏公司和影视公司的技术人员分享他们在 PBS 上的实践。例如在 2012 年的课程上[2],Disney 公布了他们在离线渲染时使用的 BRDF 模型,这也是 Unity 等很多游戏引擎使用的 PBR 的理论基础;在 2013 的课程上,Brian Karis 在名为 Real Shading in Unreal Engine 4 的演讲中分享了虚幻引擎 4(Unreal Engine 4) 中的 PBR 实现;在 2014 年的课程上,Sébastien Lagarde 和 Charles de Rousiers 在名为 Moving Frostbite to PBR 的演讲①中则介绍了寒霜引擎(Frostbite)中的 PBR 实现。Kostas Anagnostou 在他的文章②中整理了非常多的关于 PBR 的相关文章,包括我们上面提到的 SIGGRAPH 课程,强烈建议有兴趣的读者去浏览一番。
国内的相关资料则相对较少。龚敏敏在他的 KlayGE 引擎中引入了 PBS,并写了系列博文③来简明地阐述其中的理论基础;在知乎专栏 Behind the Pixels④中,作者文刀秋二给出了三篇关于基于物理着色的系列文章;FOXhunt 在他的专栏文章如何看懂这些"该死的"图形学公式一文⑤中以比较详细易懂的方式解释和推导了 BRDF 模型中的各种参数和公式。
① http://www.frostbite.com/2014/11/moving-frostbite-to-pbr/
② https://interplayoflight.wordpress.com/2013/12/30/readings-on-physically-based-rendering/
③ http://www.klayge.org/tag/pbr/
④ http://zhuanlan.zhihu.com/graphics
⑤ https://zhuanlan.zhihu.com/p/21489591?refer=c_37032701
六、参考文献
[1] Hoffman N. Background: physics and math of shading[C]//Fourth International Conference and
Exhibition on Computer Graphics and Interactive Techniques, Anaheim, USA. 2013: 21-25.
[2] Burley B, Studios W D A. Physically-based shading at disney[C]//ACM SIGGRAPH. 2012: 1-7.
[3] Walter B, Marschner S R, Li H, et al. Microfacet models for refraction through rough surfaces[C]//Proceedings of the 18th Eurographics conference on Rendering Techniques. Eurographics Association, 2007: 195-206.
http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html
[4] Beckmann P, Spizzichino A. The scattering of electromagnetic waves from rough surfaces[J]. Norwood, MA, Artech House, Inc., 1987, 511 p., 1987, 1.
[5] Torrance K E, Sparrow E M. Theory for off-specular reflection from roughened surfaces[J]. JOSA, 1967, 57(9): 1105-1112.
[6] Smith B G. Geometrical shadowing of a random rough surface[J]. Antennas and Propagation, IEEE Transactions on, 1967, 15(5): 668-671.
[7] Blinn J F. Models of light reflection for computer synthesized pictures[C]//ACM SIGGRAPH Computer Graphics. ACM, 1977, 11(2): 192-198.
[8] Schlick C. An inexpensive BRDF model for physically-based rendering[C]//Computer graphics forum. 1994, 13(3): 233-246.
[9] Cook, Robert L., and Kenneth E. Torrance, “A Reflectance Model for Computer Graphics,” ACM Trans- actions on Graphics, vol. 1, no. 1, pp. 7–24, January 1982.
http://graphics.pixar.com/library/ReflectanceModel/
[10] Kelemen, Csaba, and L azl o Szirmay-Kalos, “A Microfacet Based Coupled Specular-Matte BRDF Model with Importance Sampling,” Eurographics 2001, short presentation, pp. 25–34, September 2001.
http: //www.fsz.bme.hu/~szirmay/scook_link.htm
[11] Brian Karis. Real Shading in Unreal Engine 4[C]//ACM SIGGRAPH. 2013.
[12] Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs |