在Unity 5中引入的基于物理的渲染(PBR)是一种shading模型,它试图以一种与现实世界中光线工作方式相似的方式渲染图形。我们在第5章“理解照明模型”中遇到的所有照明模型都是对光的行为的非常原始的描述。创造它们最重要的方面是效率。实时阴影是昂贵的,像Lambertian或Blinn-Phong这样的技术是计算成本和真实感之间的妥协。
拥有更强大的GPU让我们能够编写更复杂的照明模型和渲染引擎来模拟光的行为。简而言之,这就是PBR背后的哲学。顾名思义,它试图尽可能接近过程背后的物理,让我们对每种材料有一个独特的看法。尽管如此,术语PBR在营销活动中被广泛使用,它更多地是最先进渲染的同义词,而不是一种定义良好的技术。
Unity主要通过以下两种方式实现 PBR:
- 第一个是一个全新的照明模型(称为标准)。表面着色器允许开发人员指定材料的物理属性,但他们不强加实际的物理约束。PBR通过使用一个照明模型来克服这一缺陷,该模型实施了一些物理原理,如能量守恒(物体反射的光不能超过它接收的光量)、微表面散射(与光滑表面相比,粗糙表面反射的光更不规则)、菲涅耳反射率(镜面反射出现在掠掠角)和表面闭塞(暗角和其他难以发光的几何图形)。所有这些方面,以及许多其他方面,都用来计算标准照明模型。
- 使PBR如此真实的第二个方面被称为全局照明(GI),它是基于物理光传输的模拟。这意味着物体不会在场景中被绘制,就像它们是独立的实体一样。它们都有助于最终的渲染,因为光线可以在击中其他物体之前反射到它们上。这方面不是捕捉在着色器本身,但是渲染引擎如何工作的一个基本部分。不幸的是,精确模拟光线在表面上的实时反弹超出了现代图形处理器的能力。Unity做了一些聪明的优化,允许我们在不牺牲性能的情况下保持视觉的逼真度。然而,一些最高级的技术(如反射)需要用户输入。
所有这些方面都将在本章中讨论。重要的是要记住,PBR和GI不能自动保证你的游戏将是逼真的。实现摄影现实主义是一项非常具有挑战性的任务,就像每一门艺术一样,它需要巨大的专业知识和特殊的技能。
前几章已经反复提到了 PBR,但没有透露太多。如果你不仅想了解骑马赛马是如何运作的,还想了解如何最大限度地利用它,那么你应该阅读这一章。在本章中,您将学习如何利用 PBR 及其赋予我们的属性。
在本章中,我们将介绍以下食谱:
- 理解金属结构
- 增加 PBR 的透明度
- 创建镜子和反射表面
- 烘焙灯光到你的场景
在本章结束时,您将更好地理解什么是PBR,它是如何工作的,以及如何通过几个着色器示例来利用它。
理解金属结构
Unity提供了三种不同类型的PBR着色器;它们在材质检查器标签的下拉菜单中被称为标准、标准(粗糙度设置)和标准(镜面设置)。主要的区别是标准和标准(粗糙度设置)暴露金属属性,但标准包含平滑属性,而第二用粗糙度替换平滑。标准(镜面设置)包含平滑,但用镜面代替金属属性。平滑度和粗糙度是相反的,所以平滑度值为1意味着粗糙度值为0,反之亦然。无论你使用哪种着色器,你通常都会得到相同的结果,所以这主要取决于个人喜好。
这些设置表示初始化 PBR 材质的不同方式。推动PBR的一个概念是提供有意义的,物理相关的属性的能力,艺术家和开发者可以调整和玩。有些材料的性质更容易表示,表明它们的金属程度。对于其他的,更重要的是要具体说明它们是如何直接通过它们的反射光的。这个食谱将告诉你如何有效地使用金属设置。重要的是要记住,金属工作不仅仅是金属材质; 它也是一种根据材质表面的金属或非金属程度来定义材料外观的方法。
尽管作为两种不同类型的着色器,金属和镜面设置通常都是一样的表达。正如在Unity文档http: http: //docs. unity3d. com/Manual/StandardShaderMetallicVsSpecular. html,正如前面提到的,相同的材料通常可以用这两种设置重新创建(见下面的截图):
准备
这个配方将使用标准着色器,所以不需要创建一个新的。遵循以下步骤:
- 创建一个新材质(MetallicMat)。
- 在它的检查器选项卡中,确保从它的着色器下拉菜单中选择了Standard。
- 你还需要一个有纹理的3D模型。我们之前使用的基本角色(basicCharacter,位于项目的第03章/模型文件夹中)将很好地工作。拖放到场景中。然后,将MetallicMat材料拖放到角色的每个部分上。同时,将材质的纹理(skin_man或skin_woman,两者都位于Chapter 04/Textures文件夹中)分配给Albedo属性:
怎么做……
两个主要的纹理需要配置在标准着色器: 反照率和金属。为了有效地使用金属加工,我们需要正确地初始化这些映射。遵循以下步骤:
-
反照率贴图应该用3D模型的未光照纹理进行初始化。
-
要创建金属 Map,首先要复制反照率Map的文件。您可以通过从Project选项卡中选择地图并按Ctrl + D来做到这一点。
-
使用白色(#ffffff)给Map上对应纯金属材质的区域上色。
-
其他颜色使用黑色(#000000)。灰色应该用于尘土飞扬、风化或磨损的金属表面,包括铁锈、刮伤的油漆等。Unity只使用红色通道来存储金属值;绿色和蓝色的会被忽略。
-
使用图像的alpha通道来提供关于材料光滑性的信息:
对于我们简单的角色,腰带和卫衣的小末端是我们唯一需要金属的部分。我还为主角设置了55%的不透明度,腰带的不透明度为80%
-
将金属贴图分配给材质。金属滑块将消失,因为这两个属性现在由Map控制。你可以使用平滑滑块为你提供的地图提供一个修改:
它是如何工作的……
已知金属能导电;光是以电磁波的形式被测量的,这意味着几乎所有的金属与非导体(通常被称为绝缘体)相比表现都是相似的。导体倾向于反射大多数光子(70-100%),导致高反射率。剩余的光被吸收,而不是扩散,这表明导体有一个非常暗的扩散成分。另一方面,绝缘体的反射率很低(4%);其余的光分散在表面,形成了它们分散的外观。
在标准着色器中,纯金属材质有深色的扩散成分,其镜面反射的颜色由反照率图决定。相反,纯非金属材料的扩散分量由反照率图决定;它们的高光的颜色是由入射光的颜色决定的。遵循这些原则允许金属加工结合反照率和镜面反照率映射,强制物理准确的行为。这也让你节省更多的空间,导致显著的速度增加,以减少控制你的材料的外观为代价。
另请参阅
有关金属设置的更多信息,可以参考以下链接:
- 校准图:如何校准金属材料(https://docs.unity3d.com/uploads/Main/StandardShaderCalibrationChartMetallic.png )
- 材质图:如何初始化普通材质的标准着色器参数 ( http: //docs.unity3d.com/Manual/
StandardShaderMaterialCharts.html ) - Quixel Megascans:一个巨大的材质库,包括纹理和PBR参数( https: //quixel. com/megascans/home)
- PBR纹理转换: 如何将传统着色器转换为PBR着色器( https: //marmoset.co/posts/pbr-texture-conversion/ )
- Substance Designer:用于处理PBR的基于节点的软件( https: //www.substance3d. com/products/substance-designer )
- 基于物理的渲染理论: PBR 的完整指南( https: //academy. substance3d. com/courses/the-pbr-guide-part-1 )
增加PBR的透明度
透明度是游戏中非常重要的一个方面,标准着色器支持三种不同的方式来实现这一点。如果你需要透明或半透明属性的真实材料,这个配方将对你有用。玻璃、瓶子、窗户和水晶都是PBR透明着色器的好选择。这是因为你仍然可以拥有由PBR引入的所有真实感,但添加了透明或半透明的效果。如果你需要一些不同的透明度,如UI元素或像素艺术,有更有效的选择。这些在第4章“使用纹理映射”的“创建透明材质配方”中进行了探讨。
重要的信息
要获得透明的标准材料,仅改变其反照率颜色属性的alpha通道是不够的。除非你设置了渲染模式属性,否则你的材质不会显示为透明的
准备
这个配方将使用标准着色器,所以不需要创建一个新的
- 创建一个新材质(TransparencyMat)
- 确保材质检查器选项卡中的着色器属性设置为标准或标准(镜面设置)
- 将新创建的材质分配给你想要透明的3D对象:
怎么做……
标准着色器提供了三种不同类型的透明度。尽管它们非常相似,但它们有细微的区别,用于不同的上下文。
半透明材料
有些材料如透明塑料、晶体和玻璃是半透明的。这意味着它们需要PBR的所有现实效果(如镜面高光和菲涅尔折射和反射),但允许物体后面的几何形状与附加的材料被看到。如果这是你所需要的,请遵循以下步骤:
- 在材质的检查器选项卡中,设置渲染模式为Transparent。
- 透明度的多少是由反照率颜色的alpha通道或反照率贴图(如果有)决定的。如果单击反照率部分右侧的方框,就会弹出一个颜色菜单。调整A通道将使项目或多或少可见:
- 将A通道设置为4,6,创建如下效果:
- 下面的截图显示了Unity校准场景与四个不同的高度抛光塑料球。从左到右,它们的透明度越来越高。最后一个球体是完全透明的,但保留了所有添加的PBR效果:
透明渲染模式是完美的窗户,瓶子,宝石,和耳机。
重要的信息
注意,许多透明材料通常不会投射阴影。最重要的是,材料的金属性和平滑性会干扰透明效果。像镜子一样的表面可以将alpha设置为零,但如果它反射所有入射的光,它就不会显得透明。
Fading 对象
有时,你想要一个对象完全消失与淡出效果。在这种情况下,镜面反射和菲涅耳折射和反射也应该消失。当褪色对象是完全透明时,它也应该是不可见的。要做到这一点,请遵循以下步骤:
- 在材质的检查器选项卡中,设置渲染模式为Fade。
- 正如我们之前所做的,使用反照率颜色或贴图的alpha通道来确定最终透明度:
3. 下面的截图显示了四个褪色的球体。在这里,我们可以看到PBR效果随着球体的衰减。如你所见,右边最后一个几乎看不见:
这种渲染模式最适合于非现实的物体,如全息图、激光、人造光、幽灵和粒子效果
有孔的几何图形
游戏中遇到的大多数材料都是固体,这意味着它们不允许光线通过。与此同时,许多对象具有非常复杂(但臃肿)的几何结构。用3D对象建模树叶和草通常是多余的。一种更有效的方法是使用带有叶子纹理的四边形(矩形)。虽然叶子本身是固体的,其余的纹理应该是完全透明的。如果这是你想要的,那么遵循以下步骤:
-
在材质的检查器选项卡中,设置渲染模式为Cutout。
-
使用Alpha Cutoff滑块来确定阈值的切割。在反照率图中,alpha值小于或等于alpha Cutoff的所有像素将被隐藏。
以下截图,摘自Unity Official Tutorials on PBR ( https: //
www. youtube. com/watch?v=fD_ho_ofY6A),展示了如何使用Cutout渲染模式在几何体上创建一个洞:
值得注意的是,Cutout不允许看到几何体的背面。在前面的例子中,你看不到球体的内部体积。如果你需要这样做,你需要创建一个着色器,并确保背面几何没有被剔除。
另请参阅
更多关于反照率和透明度的信息可以在 http: //docs.unity3d.com/Manual/StandardShaderMaterialParameterAlbedoColor.html
创建镜子和反射表面
当从一定角度观察物体时,镜面材料会反射光线。不幸的是,即使是最精确的菲涅尔反射模型之一,也不能正确地反射来自附近物体的光。我们在前几章中检查的照明模型只考虑了光源;他们忽略了从其他表面反射过来的光。到目前为止,根据你对着色器的了解,制作镜像是不可能的。
GI通过向PBR着色器提供关于其周围环境的信息使这成为可能。这使得物体不仅有镜面高光,也有真实的反射,这取决于周围的其他物体。实时反射非常昂贵,必须设置和调整才能工作。如果操作得当,它们可以用来创建镜像表面,如下面的截图所示:
准备
这个配方将不会有一个新的着色器。相反,大部分工作将直接在编辑器中完成。遵循以下步骤:
- 创建一个新的场景,并将一个对象放入要反射的场景中。我使用的兔子模型位于Chapter 03/Models文件夹
- 创建一个quad (GameObject | 3D Object | quad); 这可以当镜子用。我将其放大到(10,10,1),移动到(- 10,3 -11),并在Y轴上旋转到-65,以便更容易看到。
- 创建一个新的材质(MirrorMat)并将其附加到镜子上
- 在GameObject | Light | refection probe中创建一个新的反射探针,并将其放置在四边形的前面:
怎么做……
如果你正确地遵循了前面的步骤,你应该在你的场景中间有一个四边形,靠近反射探头。要将其转换为镜像,需要进行一些更改:
- 再次检查材质的着色器设置为标准,渲染模式设置为不透明
- 改变它的金属和平滑属性为1。在检查器视图中,你应该能更清楚地看到反射天空的材料。然而,在主场景中,你可能会看到场景视图中的材质变成黑色:
- 选择反射探头和改变类型为实时和刷新模式为每帧。此外,确保剔除蒙版设置为Everything。
- 接下来,检查Box投影属性,然后改变它的框大小和框偏移属性,直到它在四边形的前面,它包围了所有你想反射的对象
- 为了使项目更清晰,在Cubemap捕获设置下,将分辨率更改为2048。
您的反射探测现在应该配置好了,如下面的截图所示:
- 使用这些设置,你应该会看到类似这样的内容:
你可能会注意到,这只兔子看起来比旁边的更大。如果探头用于真实的镜子,则应该检查Box Projection 标志(在本例中,将盒子大小设置为1,1,1可以很好地使它看起来像镜子)。如果它被用于其他反射表面,如闪闪发光的金属或玻璃桌子,你可以取消检查。
它是如何工作的……
当一个着色器想要关于它周围环境的信息时,它通常在一个叫做立方体映射的结构中提供。这些在第二章 “创建你的第一个着色器” 中简单提到过,作为着色器属性类型之一,包括Color, 2D, Float和Vector。从广义上说,立方体映射相当于2D纹理;它们代表了从一个中心点看世界的360度视角。
Unity预览带有球形投影的立方体地图,如下图所示:
当立方体Map附加到相机上时,它们被称为天空盒,因为它们被用来提供一种反射天空的方式。它们可以用来反映不存在于实际场景中的几何图形,例如星云、云和恒星。
它们被称为立方体地图的原因是因为它们的创建方式:一个立方体地图由6个不同的纹理组成,每个纹理都附着在立方体的表面。您可以手动创建多维数据集映射,也可以将其委托给反射探测。你可以把反射探头想象成六个相机的集合,创建周围区域的360度地图。这也让你了解了为什么探测器如此昂贵。通过在我们的场景中创建一个,我们允许Unity知道哪些对象在镜子周围。如果需要更多的反射面,可以添加多个探针。您不需要为反射探测工作做任何其他事情。标准着色器将自动使用它们。
您应该注意到,当它们被设置为Realtime时,它们会在每一帧的开始呈现它们的多维数据集映射。有一个小技巧可以让它更快;如果你知道几何体的一部分你想反射不移动,你可以烘烤反射。这意味着Unity可以在开始游戏之前计算反射,允许更精确(和计算成本高)的计算。要做到这一点,你的反射探针必须设置为烘焙,将只工作的对象是疲惫为静态。静态对象不能移动或变化,这使得它们非常适合地形、建筑和道具。每当一个静态对象被移动时,Unity将为其烘焙反射探针重新生成立方体映射。这可能需要几分钟到几个小时。
你可以混合使用Realtime和烘焙探头来增加游戏的真实感。焙烤探针将提供非常高质量的反射和环境反射,而实时探针可以用于移动物体,如汽车或镜子。烘焙灯到你的场景部分将解释如何光烘焙工作
另请参阅
如果你有兴趣了解更多关于反射探测的知识,你应该查看以下链接:
- 关于refection probe的Unity手册: http: //docs. unity3d. com/Manual/class-ReflectionProbe.html
- 盒子投影和其他高级反射探头设置: https://docs.unity3d.com/Manual/AdvancedRefProbe.html
在你的场景中烘焙灯光
渲染照明是一个非常昂贵的过程。即使有最先进的图形处理器,准确计算光的传输(即光在表面之间的反射)也需要数小时。为了使这一过程在游戏中可行,实时渲染是必不可少的。现代引擎在现实主义和效率之间妥协;大部分的计算都是预先在一个叫做光烘焙的过程中完成的。这个食谱将解释灯光烘焙是如何工作的,以及如何最大限度地利用它。
准备
灯光烘焙需要你有一个场景准备。它应该包含几何图形,显然,还有灯。对于这个配方,我们将依赖Unity的标准功能,这样就不需要创建额外的着色器或材质。我们将重用在第一章后处理堆栈中使用过的映射。为了更好的控制,你可能想要访问Lighting窗口。如果你没有看到它,从菜单中选择Window | Rendering | Lighting,并将它停靠在更方便的地方。
怎么做…
灯光烘焙需要一些手动配置。你需要遵循三个基本而独立的步骤。
配置静态几何图形
按照以下步骤配置静态几何图形:
- 确定场景中所有位置、大小和材质不变的物体。可能的候选对象包括建筑、墙壁、地形、道具、树木等。在本例中,它将是除了FPSController及其子对象之外的所有对象。
- 选择这些对象并选中Inspector选项卡中的Static框,如下面的截图所示。如果任何被选中的对象都有子对象,Unity将询问你是否希望它们也被认为是静态的。如果满足要求(固定位置、大小和材质),在弹出框中选择“Yes, change children”
TIP
如果一个光符合静态对象的条件,但照亮非静态几何,请确保其烘焙属性设置为混合。如果它只影响静态对象,将其设置为烘焙。
配置光探针
你的游戏中有些物体会移动,比如主角、敌人和其他不可玩的角色(npc)。如果它们进入一个被照亮的静态区域,您可能想要用光探针包围它。要做到这一点,请遵循以下步骤:
-
从菜单中,导航到GameObject | Light | Light Probe Group。一个叫做Light Probe Group的新对象将出现在Hierarchy窗口中
-
一旦被选中,八个相互连接的球体将会出现。点击并在场景中移动它们,这样它们就包围了角色可以进入的静态区域。下面的截图展示了如何使用光探针来包围静态办公空间的示例:
在我们的例子中,这只是玩家可以进入的中心区域
3. 选择将进入光探测区域的移动对象。
4. 从它们的Inspector选项卡,展开它们的渲染器组件(通常,这是Mesh renderer),并确保Light Probes没有设置为Off checked(见以下截图):
决定何时何地使用光探针是一个关键问题;关于这方面的更多信息可以在How it works…这个食谱的一部分。
烘烤灯光
烘焙灯,遵循以下步骤:
- 首先,选择你想要烘焙的灯。在Inspector选项卡中,确认Mode被设置为在Light组件中烘焙:
- 要烘焙灯光,打开照明窗口,点击Window | Rendering | Lighting 。在那里,选择 Scene Tab。
- 如果启用了“自动生成”复选框,Unity将在后台自动执行烘焙过程。如果没有,单击Generate Lighting。
TIP
灯光烘焙可能需要几个小时,即使是相对较小的场景。如果你不断移动静态对象或灯光,Unity将从头开始重新启动进程,导致编辑器严重减速。您可以取消从Window | Rendering | Lighting 窗口的自动生成复选框,以防止这种情况,以便您可以决定何时手动启动该过程。
它是如何工作的……
渲染中最复杂的部分是光线的传输。在这个阶段,GPU计算光线如何在物体之间反弹。如果一个物体和它的光不移动,这个计算只能进行一次,因为它在游戏中永远不会改变。将一个对象标记为Static是告诉Unity可以进行这样的优化。
粗略地说,光烘焙指的是计算静态对象的GI并将其保存在所谓的光图中的过程。烘焙完成后,可以在照明窗口的烘焙灯光图选项卡中看到:
点击打开预览按钮,你就可以看到生成的其他贴图,包括烘焙方向性贴图:
灯光烘焙的代价是:Memory。每个静态表面都被重新纹理,这样它就已经包含了它的光照条件。让我们想象一下,你有一个森林的树,所有的树都共享相同的纹理。一旦它们被做成静态的,每棵树都会有自己的纹理。光烘焙不仅会增加游戏的大小,而且如果不加区分地使用,还会占用大量的纹理内存。
在这个配方中介绍的第二个方面是光探测。光烘烤对于静态几何图形产生极高质量的结果,但对移动物体不起作用。如果你的角色进入一个静态区域,它看起来就会脱离环境。它的阴影与周围环境不匹配,导致了一个不愉快的审美结果。其他对象,比如蒙皮网格渲染器,将不会接收GI,即使它们是静态的。实时烘焙灯光是不可能的,尽管光探针提供了一个有效的替代方案。每个光探测器在空间的一个特定点对GI进行采样。光探测组可以对空间中的几个点进行采样,允许GI在特定的体积内进行插值。这让我们可以更好地投射移动物体的光线,即使GI只计算了几个点。重要的是要记住光探针需要包围一个体积才能工作。最好将光探头放置在光线条件突然变化的区域。与光贴图类似,探测消耗内存,应该明智地放置;记住它们只存在于非静态几何中。因为在演示场景中没有可见的对象,所以这样做纯粹是为了演示目的。
即使在使用光探测时,也有一些方面是Unity的GI无法捕获的。例如,非静态物体不能将光线反射到其他物体上。
另请参阅
你可以在http: //docs.unity3d.com/Manual/LightProbes. html .上阅读更多关于光探测的信息