走近标准着色器
本书简单介绍了如何使用标准/PBR(基于物理的渲染)着色器(shader),使物体看起来更美观。
译者按:
本文主要介绍 Unity Standard 着色器的相关知识。或许您最终不会将 Unity Standard 用于内容制作,但是通过学习这个最基础的着色器相关知识,认知不同类型的贴图作用,仍然可以为您日后学习其他社区自定义的着色器打下一定的知识基础。
原作者:Silent ;翻译校对:Stursi、Anteness
简介
Unity 的标准着色器(Standard Shader)在 VRChat 中一直是备受误解和争议的一部分。标准着色器提供了相当逼真的外观效果,这要归功于它基于物理规则的渲染方式。然而,它也存在一些易于混淆的术语,比如那些无法区分“光滑度”和“金属度”的人可能会对其感到困惑。
一个重要的关于标准着色器的事实是,它遵循基于物理规则的渲染(PBR)逻辑。PBR 的设计目的是以一种优雅而逼真的方式反映不同光照条件下的视觉效果。这也意味着材质的外观是符合能量守恒的——它们不会反射比入射更多的光线。它们会根据经过精心调整的算法将光线分散到材质的表面上,这些算法经过测试,以匹配真实世界的相似条件。
虽然我不会在这里详细介绍PBR,但我会在文末提供相关链接,其中包括一些关于使用标准着色器时您必须知道的非常重要的信息。
译者注:在中文语境下,texture 被同时翻译为“纹理”和“贴图”,它们表达的是同一个东西。为阅读方便,本文对于大部分的 texture 相关英文,译为“贴图”。
贴图纹理的种类
程序员之间流行着这样一句话:“输入的是垃圾,输出也会同样是垃圾”。如果您不知道自己给着色器输入的东西是什么,您最终也只会得到糟糕的效果。那么,标准的着色器支持哪些不同类型的贴图输入?它们各自的作用又是什么呢?让我们来找出答案!
漫反射/基础色(Albedo/Diffuse)
首先,让我们来谈谈 基础色(Albedo)。基础色虽然听起来很“基础”,但它其实非常重要,因为它是您材质球的主要颜色来源!它在其他游戏引擎里可能被称为 颜色、主色 或 漫反射贴图。或者更进一步来说,Albedo 的意思在于它提供了一个光线打在物品表面时有多少光线会被反射,有多少不会被吸收的指标。
注意这里的“不被吸收”,稍后您会发现它的重要性。
此外,我们还需要注意纹理颜色。请注意,这里所述的纹理颜色并不是贴图的颜色!这是一个重要却经常被忽视的内容——当您从Blender导出模型时,Blender通常会将对象的材质变成灰色。而当Unity加载模型时,也会将材质设为灰色,这会让模型的表面看起来更加暗淡!所以,每当您在Unity中加载新模型时,务必确保纹理颜色是白色且完全不透明。
译者注:所谓“纹理颜色”在此处只是为了区分于“贴图颜色”而单独更改。结合作者表达的意思来看,其指向的应该是模型的网格初次导入到 Unity 的时候,在赋予材质球之前,Unity 为模型自动覆盖的白色外观。
法线贴图(Normal Maps)
接下来,让我们谈谈 法线贴图。法线贴图可以为材质表面带来与模型的网格形状不同的额外光影细节。
也许您阅读到这里的时候,对法线贴图不太了解。不用担心,让我来解释一下!模型的网格是由多边形组成的,而每个顶点是空间中的一个点,它们互相连接组成了多边形。多边形不仅代表了空间中三个点所构成的形状,它还存储着有关多边形的表面垂直于哪个方向的信息——也就是法线方向。这会直接影响模型接受光照的效果。不正确的法线会导致模型表面出现怪异的缝隙和形变,与我们的期望不符。正确的法线会让表面在必要的地方看起来柔和圆润,在其他地方硬朗锐利!
现在请在您的脑海中想象一个多边形,它是一个简单的平面,您可以为它添加贴图使其表现出细节,但由于它本身只是一个平坦的面,不会表现出更多的细节。所以,有人想到一个好主意,通过贴图来调整表面法线,以增加细节。显然,相比于直接修改网格本身,直接修改贴图可以更加细致和灵活,这就是法线贴图的作用。
在Unity中,这些贴图在导入后需要以特殊的格式读取,这就是为什么您需要在导入法线贴图之后,需要进入检查器将其标记为法线贴图的原因。如果一个贴图被指定为材质球的法线贴图,却没有作为法线贴图导入,Unity 会显示警告。
如果您导入了来自其他游戏引擎的法线贴图,它的法线方向可能是反的。您可以通过观察凸起和凹陷的形状来判断它的方向是否正确。尤其是为 Unreal Engine 制作的法线贴图,它们通常是反向的。在目前版本的Unity中,一旦将贴图设置为法线贴图,您可以通过勾选“Flip green channel”选项来纠正它的方向。
如果您导入的资产没有包含法线贴图,不用担心,如果作者没有做,那就意味着它不是必需的。在这种情况下,法线贴图更多是用于改进照明效果的细节。如果您需要,可以尝试自己生成。
点击这里 查看有关法线贴图方向的更多详细信息,以及默认情况下哪些应用程序支持导出的表格。
高光贴图和金属度贴图(Specular and Metallic Maps)
高光贴图(Specular Map)(又称:镜面反射贴图)是一个复杂的话题。许多关于镜面反射贴图的文章都专注于讨论特定游戏或渲染引擎处理它们的方式,以及它们各不相同的妥协和优化。然而有一点是共同的,高光贴图可以用来制作闪亮光泽的效果。
在 Unity 中,这种效果由遵循 PBR 原则的两个组成部分定义。第一部分 决定哪些区域吸收光线,类似于金属;或者反射光线,类似于纸张。这些信息存储在 金属度贴图的 红色通道 中。另一部分 则决定哪些区域平滑且反光,类似经过抛光的木材;或者粗糙,如生锈的金属。这些信息存储在 金属度贴图的 透明通道 中,被称为 金属度(Metallic) 和 光滑度(Smoothness)。
从技术角度来看,像布料这样的非金属表面被称为介电质材质。打在它们表面的光线会在内部反弹,并产生柔和均匀的颜色;相对的,由于金属材质具有导电的特性,可以反射撞击它的光子,并吸收未反射的光 —— 最终会产生镜面反射光。
这就是 金属度贴图(Metallic Map) 的功能。那么高光贴图又是怎么一回事呢?将高光和阴影直接烘焙到基础色贴图,并为之附上一个简单的金属度贴图,是最简洁也最节省内存的方法。相比起来,同时使用金属度贴图和高光贴图将会占用额外的内存,尽管这样制作起来要容易一些。这是因为,金属度贴图无法很好地体现布料或皮肤这样既非金属又非硬物的质感。因此,可以将高光贴图视为定义特定类型的光泽效果的方式,而金属度贴图则仅定义某物是否为金属。这就是Standard和Standard(Specular)之间的区别。
在高光贴图的机制中,材质球的金属部分在高光贴图的RGB通道中定义,而透明通道仍然被保留用于表达光滑度。这需要消耗更多的内存,但当简单的遮罩无法满足需求时,它将是有用的。一个很好的真实例子是嵌有闪亮的薄金属线的表面,从斜侧面或远处看的时候,它们会因纹理过滤而失去金属的光泽。但若加入高光贴图,它们将保持适当的光泽。
然而,如果您为一个物体添加金属度/高光贴图,您可能会注意到模型表面光滑的区域变暗了。这符合能量守恒定律。一个材质不能同时处于非金属和金属状态,而只能是其中之一,或是两者之间的某种混合状态。因此,导入另一个游戏引擎制作的高光贴图时,您可能需要进行适当编辑以改善其效果。
总结:
- 金属贴图 在贴图的 红色通道 中存储的是布尔值(“是”或“否”),指定材质的部分是否是金属。而 Albedo 则用于指定镜面反射效果的强度。
- 高光贴图 的 红、绿、蓝(RGB)通道存储了它所反射的颜色的值。
- 光滑度、光泽度或表面粗糙度的信息反向存储在透明通道中,无论是金属模式抑或镜面反射模式。
参考文献:
- https://google.github.io/filament/Filament.md.html Google 将 PBR 与其 Filament 引擎结合使用的指南。它由谷歌工程师编写并更深入地探讨了该主题。
- https://academy.allegorithmic.com/courses/b6377358ad36c444f45e2deaa0626e65
- https://marmoset.co/posts/pbr-texture-conversion/
- https://www.sharetextures.com/textures/blog/physically-based_rendering/
- https://google.github.io/filament/Material Properties.pdf Google 的 PBR 材料参考图表。这是制作贴图时手头有用的参考之一。
遮挡、高度和发光贴图(Occlusion, Height, and Emission Maps)
遮挡贴图(Occlusion Maps)
接下来是 遮挡贴图,这些贴图包含环境阴影,通常指那些光线无法直接到达的裂缝和缝隙,除非光线直接照射进去。
对于像道具和角色这样的单一模型,您可以使用Blender进行烘焙,但结果取决于您的模型比例和UV映射。对于重复的贴图,例如砖墙、地砖或甚至一些泥土,您可以从法线或高度图生成它们。
在标准着色器中,绿色通道用于遮挡贴图。
高度贴图(Height Maps)
高度贴图 在Unity中用于提供“视差遮挡”效果。它们基于高度贴图和您的视角来移动贴图。使用这种效果的成本在Unity中相对较低,但需注意,从错误的角度观看可能导致显示错误,因此要小心,不要设置得太高。
在标准着色器中,红色通道用于高度贴图。
发光贴图(Emission Maps)
发光贴图 用于决定模型的发光区域。制作一盏灯需要的 材质(Material)便包括发光贴图。然而,发光贴图必须 单独制作,特别是未发光的部分必须是黑色的!错误设置发光贴图可能会使你的模型看起来非常奇怪。在渲染的时候,发光贴图与发光颜色相叠加。
夜光效果的发光强度应设置为 1.0。明亮的发光效果则至少应为 5.0。
细节遮罩(Detail Mask)
接下来是 细节遮罩,它控制 细节贴图 的应用范围(我们将在下面讲到)。在细节遮罩为黑色的地方,细节贴图不会被应用。这使您可以让细节贴图影响模型的某些部分而不影响其他部分。
在标准着色器中,蓝色通道被用于表示细节遮罩。
细节贴图(Detail Maps)
在 Unity 中,细节贴图(Detail Maps)常与 基础色(Albedo)结合使用。正因如此您可以为其指定不同的平铺大小,从而在不那么精细的贴图上覆盖添加图案,使其看起来更加细致。这听起来不错,但实际应用起来相当的困难。
默认情况下,标准着色器会将 基础色 与 细节贴图 互相叠加。要注意的是,中灰色的细节贴图不会使材质产生亮度变化,细节贴图偏白色会使材质球变亮,细节贴图偏黑色则会使材质球变暗。
细节法线贴图 的工作方式十分类似于细节贴图,但专用于法线。一个例子是在墙上应用图案,使其在与材料其他部分的不同尺度上看起来更粗糙,增加其变化效果。或者通过细节贴图提供的特征增加深度。
设置好 UV 通道选项 对于 细节贴图 来说非常重要。就像网格提供 UV 来告诉它们贴图的位置一样,标准着色器支持使用第二个 UV 图以在网格上添加细节。例如,有一件衣服,主色只包含布料部分,然后细节贴图只包含一个标志的图案。使用标志图案作为细节贴图,并将次级 UV 通道映射到标志图案的贴图,您可以结合两种贴图,在模型的材质球上渲染出清晰的标志图案。
更多关于细节贴图的详细信息,请参考 Unity 官方文档。
贴图案例
这些贴图看起来怎么样?以下是一个布料材质的例子,最左侧是使用Materialise渲染出来的效果,然后往右依次是基础色、法线贴图、高光贴图、光滑度贴图和遮挡贴图。
您可以看出这块布料的质感粗糙,略带光泽,而且在褶皱处具有阴影。
现在,让我们将其与同一个材质球的金属物件部分进行比较。
您会发现它的高光贴图和基础色的中心区域都具备光亮的颜色,最终渲染的效果也非常平滑和光亮。请注意观察反射效果的颜色是如何传达金属质感的。
最终的渲染效果如下:
为标准着色器制作高光/金属度贴图
在使用 标准着色器(Standard) 时,推荐将 金属度贴图(metallic) 和 光滑度贴图(smoothness) 合并为同一个贴图文件。此外,遮挡贴图(occlusion) 和 细节遮罩(detail mask)也可以被整合为同一个贴图文件,这么做可以节省内存,是一个很好的优化方法。
作为参考,红色通道表示 金属度(Metallic),绿色通道表示 遮挡贴图(Occlusion),蓝色通道表示 细节遮罩(Detail Mask),透明通道表示 光滑度(Smoothness)。(译者注:这些贴图向着色器传达的强度信息只与像素的明度有关,与颜色无关)。
使用 标准(镜面反射)Standard (Specular) 着色器时,虽然也倾向于将高光贴图和光滑度贴图放在同一个贴图中,但这么做就将挤占掉其他贴图的位置。
使用 标准(镜面反射)Standard (Specular) 着色器时,注意不要混合遮挡贴图和细节贴图。
根据使用工具的不同,处理这个问题可能会遇到的麻烦有所不同。例如,通过 Photoshop 保存半透明图像时,透明像素会被替换为纯白色像素,这将会破坏高光贴图!另外,由于Windows中的一个古老的错误,许多图片处理工具也可能对导入的图像进行同样的处理。
使用 SmartTexture 创建组合贴图
利用 SmartTexture 插件,您可以轻松地将多个不同用途的贴图合并为单个贴图文件,而且这一过程完全自动化。只需将材质球内的各个贴图纹理单独保存,然后创建一个SmartTexture资源,将它们关联在一起。
要安装 SmartTexture,请遵照 这里的说明 进行操作。
一旦安装完成,您就可以在 Unity 中创建新的 SmartTexture 资源,并将单独的贴图一一拖入,实现贴图的合并,提高工作效率。
使用 chaiNNer 合并贴图
ChaiNNer 是一个非常便利的贴图操作工具,您可以使用它将多个贴图合并为一个,也可以利用神经网络来放大贴图的分辨率。
您可以 在这里下载chaiNNer。
您可以将贴图拖入窗体,然后使用 Seperate RGBA 节点 将其分解成各自的组成部分,最后通过 Combine RGBA 重新组合。此外, ChaiNNer 还支持各种类型的过滤器,并可批量处理图像。
使用ImageMagick合并镜面反射和光滑度
ImageMagick 提供了一种简单而有效的方法,在Unity之外,仅需几个简单步骤就可以合并您的贴图——只要您知道如何使用命令行。
首先,点击这里下载 ImageMagick(推荐兼容HDRI的版本)。
ImageMagick 是一个历史悠久的开源命令行工具集,用于编辑图像。人们使用IM和批处理脚本完成了许多奇妙的事情。虽然我们的脚本没有那么奇妙,但也同样实用。
以下是您需要使用的脚本:
magick convert %1 %2 -alpha off -compose CopyOpacity -composite PNG32:%1_result.png
此外,我们还准备了一个批处理文件:
下载并保存在待处理的图片文件目录中,然后选择两个相同尺寸的图片文件,将这两个文件拖放到批处理文件的图标上。例如,您可以选择您的高光贴图和光滑度贴图的文件,然后将它们拖放到批处理文件的图标上。最终输出将是这两个图像的合并结果,而第二个图像将被添加到透明通道中——这就为 Unity 生成了一个完全准备好的高光+光滑度贴图!然后,将生成的文件导入 Unity 项目中即可。
使用 Materialize 通过现有素材创建各种贴图
对于世界创作者来说,Materialize 是一个非常出色的工具。它能够通过简单的拖放图片素材,并进行一些点击和调整,即可创建出各种纹理贴图!
这些纹理贴图全都都源自同一张图像,超级神奇!您可以在Bounding Box Software网站上下载 Materialize,并且网站还提供了一些有用的教程,帮助您快速入门!并且,由于您已经读过了这篇文档,说不定已经掌握了使用 Materialize 制作贴图的能力呢!
Materialize 最适合创建世界场景中的平铺材质。虽然您仍可用于人物角色的制作,但千万别挤太大的深度参数,以免造成不自然的外观效果。
结论和其他提示
标准着色器在 VRchat 中被误解了。许多人抱怨该着色器产生的糟糕视觉效果,但实际上它只是一个复杂工具,很容易被错误使用。正确使用这个着色器,可以获得良好的效果,并且运行高效、易于调整。对于人物模型来说,它是比大多数人认为的更好的选择,对于追求 CG 风格和现实主义风格的项目来说,它肯定比平面着色器更好。
Filamented 着色器
值得注意的是,标准着色器早在2015年就已被引入 Unity,距今已过去了许多年。与此同时,着色技术和 GPU 硬件发生了许多变化(译者注:这里大概是指光线追踪、DLSS等渲染技术,相对于光栅化计算而言)。但这并不意味着我们应将其抛在脑后!这正是我开发 Filamented 的初衷,它利用来自 Google 的 Filament 渲染器的最新着色计算替代了标准的着色计算。同时,它为 VRChat 世界制作增加了一些有用的便利功能。
您可以从以下链接获取 Filamented 着色器:https://gitlab.com/s-ilent/filamented
Crosstone Cel Shading 着色器(SCSS)
此外,我还为虚拟形象的制作搓了一个新的着色器,Crosstone,支持高质量的动画风格着色,遵循行业标准规范。这使您可以获得类似于现代ACG风格游戏《异度神剑3》的伪PBR外观效果。
您可以从以下链接获取Crosstone:https://gitlab.com/s-ilent/SCSS
结论
一些聪明人会说,物理基础渲染应该被称为“物理启发渲染”,因为它并不完全遵从现实世界的物理规则。尽管许多材质都在专注于“现实世界中事物的运作方式”,但是,现实比我们所知道的要复杂得多。因此,请记住,不是所有的东西都能被标准着色器模拟出来!如果您有任何疑问,欢迎随时向我咨询。下次再见!