《晶体秘境》材质全解析:如何在UE中构建高效逼真的水晶着色器

AI3D 发表于 07-23 浏览 3 分类 创作分享

Breakdown:

引言

我叫 Anastaisa Gorban,是一名虚幻引擎美术师,目前担任技术灯光师。有些读者可能还记得我之前在这篇文章中分享的内容。此后,我一直在从事关卡和灯光方面的工作,但我也喜欢深入引擎更偏技术的方面,尝试在引擎中再现现实世界中的美丽事物。这正是我启动这个项目的原因。我想尝试从零开始构建一个更复杂的着色器,走出自己平时的舒适区,看看能把它推到什么程度。

水晶领域

最初,这个项目是我求职时的一项测试任务——我需要制作一张逼真水晶的图像,类似于亚历山大石,内部为双色性,外部为彩虹色。第一个材质要简单得多,专注于精确还原亚历山大石的外观。但我在三天内完成了任务后,决定把它变成一个主材质,能够覆盖不同的水晶变体,并在看起来可信的前提下尽可能优化。

我特意保留了不透明性——它比半透明更廉,但仍然可以看起来可信。至于 Substrate,我对它的经验更少,但它已经不算新功能了,所以我觉得这是个好机会来填补这个空白。还有 Lumen,因为我喜欢探索它的能力。我的目标是在实时中达到接近艺术家在其他引擎中离线渲染的效果,但完全不使用离线渲染。宝石是一个自然的主题;它们的光影变化令人着迷,而且每颗石头都是独一无二的。

主材质设置

Substrate 对我来说是全新的领域,我直言不讳:这个特定的材质严格来说并不需要它,因为这里的一切都是用普通的着色器数学计算输入到单个 slab 中构建的,类似的不透明结果也可以用标准表面材质复现,成本更低。我希望彩虹色存在于水晶的外表面,独立于内部驱动。彩虹色是薄层在掠射角对反射进行着色,Substrate 允许我在不影响漫反射内部的情况下实现它,而基础着色模型不允许这样。

整个材质是迭代发展的,而不是事先计划好的。我为测试任务制作的第一个版本没有视差,只有两个内部颜色层,偏移固定距离,没有 bump/POM,边缘没有法线细节,没有内部辉光,也没有遮罩将水晶的纹理与基色分开。从远处看还行,但之后的每一次迭代都增加了更多物理可信度的层次,材质图也随之增长。

总的来说,最终的主材质结构如下:

  • POM vs. Bump Offset —— 深度阶段
  • 水晶内部 —— 双色性内部,通过每层调用两个共享函数构建——MF_InnerLayerUV 和 MF_ColorLerp
  • 彩虹色 —— 高光响应的视角颜色偏移
  • 外部法线 —— 表面划痕 + 边缘磨损
  • 外部粗糙度 —— 可控的抛光/磨砂范围
  • 内部辉光 —— 与内部关联的自发光通道
  • 最终合成 —— 所有模块汇聚到一个 Substrate Slab BSDF
Breakdown:

下面是每个模块的作用及其暴露的参数。

第1步:深度阶段(POM vs. Bump Offset)

在采样任何颜色之前,材质需要一个模拟深度的 UV 偏移。我构建了两种方法:真正的视差遮挡映射(精确,由专用的高度贴图驱动)和一个更便宜的 Bump Offset 节点。一个 Allow POM? 开关决定哪一个实际驱动下游的所有东西。这取代了我最初的方法,即每层只有一个固定的距离值,没有真正的视角变化行为。

Breakdown:

POM 在物理上更正确,但成本更高(步数、阴影步等),而 Bump Offset 在堆叠多层内部遮罩时缩放性更好。两个分支共享相同的高度源和相同的 Top Texture Tiling。高度源是顶层使用的 Top Diffuse Mask 纹理,该纹理稍后会在材质图的下游用于顶层。

在两个模块中使用相同的纹理和相同的平铺参数,使得对顶层的任何更改都会应用到用于视差的高度。这样,伪深度总是精确地落在它置换的颜色上,两者永远不会漂移。POM Height Ratio(默认 0.1)控制效果的深度。调高它会加深错觉,但会在掠射角出现游泳伪影。细节:我取 POM 的 Offset Only 输出,并将其叠加在平铺 UV 上,平铺 UV 是在 Crystal Insides 模块中单独构建的。使用完整的 Parallax UVs 输出会引入视差平铺并导致两次缩放。

Breakdown:

POM 的一个注意事项:为了使效果全力工作,顶层希望尽可能靠近表面,这意味着 Top Distance 应设置得比平时低。

Bump Offset 是更便宜的备选方案。其深度由 Bump Depth(默认 0.1)设置。由于它采样漫反射纹理本身而不是专用的高度贴图,我首先将其转换为亮度(RGB 的加权点积),然后通过 Power 节点提高对比度,从而加深偏移。

Breakdown:
Breakdown:

第2步:水晶内部

这个模块承载了大部分错觉效果。我从两个内表面开始:顶层和底层。两层而非一层是刻意选择的。

Breakdown:

对于像亚历山大石这样的双色性石头,内部必须在不同深度显示真正不同的颜色,而单层颜色 lerp 无法令人信服地模拟这一点——颜色必须位于不同的表面上,以便视差在视角移动时揭示一个表面在另一个表面之后。对于更简单的石头,一层可能就足够了,并且当水晶远离相机时,单层也作为更便宜的路径,不需要额外的深度。

Breakdown:

在那条管线中,有两个部分构建了每个层的UV:距离偏移(该层被推入内部的深度)和扭曲(这种推入的不规则程度,模拟晶体内部的折射)。这些过程被封装到一个函数 MF_InnerLayerUV 中,以 Distance、Noise Texture、Texture Tiling 和 Distortion Scale 作为其四个输入,而不是在图表中留下三个几乎相同的副本。

Breakdown:

1— 在切线空间中从摄像机向量构建一个反射向量——这是整个偏移所依赖的视角相关方向,因此偏移方向实际上表现得像在宝石内部反弹的东西。

2— 扭曲——反射向量的平面内(X/Y)分量被噪声纹理参数扰动,由 Distortion Scale 参数缩放。这使其看起来不规则,更接近真实石头内部光线破碎的方式,因此每个层看起来像天然的裂缝,模拟石头内部的折射。每个层都有自己的噪声纹理,因为折射根据层内部几何结构的不同而不同,并且这个参数可以进一步推高以模拟像光玉髓或琥珀这样的石头。

Breakdown:

3— 该扰动方向被反射向量的深度(Z)分量除,这保持了偏移的稳定性,而不会在掠射角时爆炸。

4— 距离——此时,结果被层的 Distance 值缩放——顶层 Distance 使用 200,底层 Distance 使用 400。Distance 决定了当摄像机旋转时每个层的 UV 移动多远,两个值之间的差距在视觉上分离了顶层和底层,而不是坍缩成平坦的混合。对于不需要很多深度的石头,可以降低 Distance 值,使顶层更靠近表面,这也是依赖 POM 的石头的推荐设置。

5— 最后,缩放的偏移被加到层自身的平铺 UV 上,乘以该层的 Texture Tiling 输入。这样,顶层和底层接收到它们自己的平铺,例如,在需要晶体内部更紧密晶格的情况下。如前所述,在深度阶段引入的顶层 Texture Tiling 就是缩放顶层漫反射的相同值,因此两者不会漂移分开。

Breakdown:

每个层的 MF_InnerLayerUV 输出然后被加到步骤1(POM vs. Bump Offset)的 UV 偏移上,将每个层的深度偏移和扭曲与基础视差阶段组合成一个最终的 UV。该 UV 用于在 MF_ColorLerp 函数中采样层的漫反射遮罩纹理。

在颜色方面,材质经历以下管线。漫反射遮罩的红色通道被分离出来并输入到 MF_ColorLerp,该函数在 Main Color 和 Veins Color 之间进行 lerp。

Breakdown:

Main Color 越暗,半透明错觉越强,因为接近黑色的漫反射几乎没有贡献,看起来像空体积。在双层设置中,顶层最好保持较暗,以便底层颜色能透过它显现。如果整块石头倾向于半透明,则两层都应较暗。颜色越浅,层变得越乳白和不透明。 

Breakdown:

我在此基础上给底层增加了第二个颜色通道,因为真实晶体内部的颜色以及纹理不会随深度保持一致——分带、多色性和色散都会使石头根据观察角度变化颜色。每层单一的 Main/Veins 对无法完全重现这一点,因此底层获得了第三个颜色区域,带有自己的 Veins Color 2 和 Diffuse Mask 2,通过一个低指数的菲涅尔项混合,该菲涅尔项在直视表面时接近零,并在接近轮廓时升高。

Main Color 与第一个通道共享。混合主体颜色在这里毫无意义,因为实际上是纹理携带了内部的颜色;填充只是它们所处介质。这样将额外颜色集中在石头中心并向边缘淡出,而不是均匀分布在图层上。

Breakdown:
Breakdown:

至此,两个图层保持分离。顶部图层的结果是其输出“Top Layer”。将“Top”和“Bottom”相加得到“Two Layers”输出。然后,“Allow Second Layer?”开关在两者之间进行选择。

Breakdown:

关于纹理本身的一点说明:我在这里使用的大多数Diffuse贴图和遮罩都是用Nano Banana生成的。好的免费水晶纹理很难找到,而生成它们给了我正好需要的图案,并且可以完全控制它们如何呈现,而不是将就于任何已有的资源。

Breakdown:

步骤 3. 虹彩

我的亚历山大石需要一层虹彩涂层,因为这种色彩变幻是该石材的一个显著特征,但可以将其关闭以用于没有此特征的石头。像石英、红宝石或蓝宝石这样的透明单色宝石没有表面虹彩,而欧泊、拉长石、月光石和菊石则有——因此将其作为一个可选层可以使主材质适用于多种水晶类型。

Breakdown:

内部效果完成后,我为外部构建了一个独立的视图角度驱动的颜色偏移,将其输入到镜面反射响应(F0)中,使其表现为薄膜涂层。相机向量被转换到切线空间并与像素法线点积,得到一个标准视角依赖项——直视表面时为1,掠射角时降至0——经过饱和和乘方(虹彩混合强度)来塑造衰减。

然后乘以一个波动缩放(默认6.28 ≈ 2π)并通过正弦函数:薄膜干涉在视角上是周期性的,因此正弦代表这种周期性,将平滑渐变变成重复的波段,更高的波动缩放会产生更多波段。正弦被重新映射到[0,1]并作为两个虹彩颜色参数之间的Lerp的Alpha值,再乘以总体虹彩强度。

Breakdown:
Breakdown:

此设置中的虹彩通过其自己的开关“Allow Iridescence?”来控制。

步骤 4. 外部法线和外部粗糙度

这些与虹彩一起引入,使表面看起来真实,带有抛光宝石上的细微磨损和划痕。两个法线来源被混合:外部法线纹理(由外部法线强度缩放)携带整个表面的细微划痕,以及边缘法线纹理(具有边缘法线强度)仅集中在切面交汇处,使边缘的高光更锐利。

Breakdown:
Breakdown:

对于边缘遮罩,我复用了来自Fab的免费水晶资源附带的发光贴图纹理——它的发光正好沿着几何边缘分布,因此我提取其绿色通道直接用作几何边缘遮罩。对于这个特定网格,它本质上是一个免费的曲率贴图;代价是它烘焙到这个资源上,不能转移到任意几何体上(真正的曲率/凹陷烘焙,或者来自法线导数的运行时曲率项,才是通用版本)。

Breakdown:

粗糙度是单一的外层粗糙度纹理,重新映射到美术可控的最小/最大粗糙度范围。

Breakdown:

步骤 5. 内部发光

水晶会散射光线,使其穿过内部并发生折射,因此光线似乎会在石头内部聚集和反弹,而不是简单地反射出去。在不透明材质中,没有真正的透射可依赖,因此自发光通道代替了内部光线,营造出光线在水晶内部折射和聚集的错觉。

它通过菲涅尔项进行遮罩,使用边缘阴影指数作为内部的边缘暗化,使发光集中在水晶内部。该遮罩乘以发光颜色和自发光强度。

Breakdown:

是否允许内部发光?开关选择发光的来源:

  • 开启时,光线来自底层,表现为从内部向上折射的光线;
  • 关闭时,光线仅来自顶层,为纯表面发光。
Breakdown:

是否允许第二层?上述描述是独立的;水晶可以携带两层而无内部发光,而是否允许内部发光?则不然——内部发光源自底层,因此启用它本质上要求该层存在。即使是否允许第二层?未勾选,开启内部发光也会有效将第二层拉入结果,因为没有该层,光线无处来。

步骤 6. 最终合成

所有内容汇聚到一个Substrate Slab BSDF – Simple节点:漫反射反照率来自水晶内部结果(单层或双层,取决于开关),F0来自平坦的Specular值或虹彩,粗糙度和法线直接来自各自的模块,自发光颜色来自发光。BSDF上的其他所有参数保持关闭。材质是不透明的,通过分层漫反射伪造内部深度,而不是为真正的半透明和次表面散射付出代价。

Breakdown:

在当前设置中,开关功能严格来说并不是优化工具。它们确实削减了部分指令,但主要目的是保持参数集有序,避免材质实例中的混乱。

这使我们能够剥离特定水晶类型根本不需要的控制项,这样配置粉水晶的美术师就不必处理不适用于它的虹彩和内部发光参数。

Breakdown:

性能与优化

Substrate材质运行大约在445条指令(所有开关关闭)到517条(全部开启)之间。一个空的Substrate Slab BSDF本身就耗费了-326条指令。我在标准的非Substrate材质上重建了相同的设置,结果仅为291-369条指令。因此,如果纯粹以最低成本交付这个不透明水晶为目标,标准材质是正确的选择。

失去的是纯形式的虹彩,因为标准着色模型不允许直接为电介质的镜面反射着色,所以驱动Substrate中F0的薄膜效果无处安放。你可以通过将虹彩色混合到基础颜色中来近似,但那只是染色表面,而非反射上真正的彩色高光。调整Specular和Metallic等参数也有助于实现类似效果。

总结

整个流程大约花了我两周时间,其中三天用于最初的测试任务,那奠定了基础。如果从一开始就有清晰的计划,可能会更快,但我是在过程中不断发明新的逻辑层。不少时间也花在了灯光上。为了达到这个效果,我需要多个带有可控灯光通道和遮光片(gobo)效果的光源,并且必须修改默认的 Megascans 岩石材质,以添加闪烁和置换细分。

还有一个小型的 PCG 设置,用于将水晶散布到另一块岩石表面。主要挑战是不要迷失在逻辑块堆叠中,并找出哪种“造假”手法最贴近现实。这样的材质其实就是一堆代替真实光学效果的“作弊”手段,难点在于选择哪些“作弊”值得添加,并在堆叠时保持所有层的可读性。

我的建议是,先规划好你希望在材质中看到的效果,然后大致构思如何构建,但对意想不到的方法保持开放态度,因为往往是那些方法才能帮你得到想要的视觉效果。始终考虑不同的使用场景,不要执着于单一的变体。

与此同时,一定要把第一个具体版本做好,因为它能为你提供成长的基础。不断测试并质疑你的节点图,在叠加新的节点之前,验证某个节点是否真的在按你的预期工作,不要害怕删除没有贡献的工作。

差不多就是这样。非常感谢 80 Level 给我机会详细讲解这个材质的运作方式——将某个最初只有三个节点图的东西拆解开来,确实很有成就感。祝大家的项目顺利!

Anastasia Gorban,关卡与灯光艺术家

采访人: Gloria Levine

相关链接

原文链接:https://80.lv/articles/breakdown-how-to-create-an-optimized-and-realistic-crystal-material

喜欢这篇内容吗?