BACK TO ARCHIVE
houdini karma materialx rendering lookdev sss dcc mechanics

Karma 里用 MaterialX 做皮肤 SSS:XPU 下位移与散射的关键调参

02.26.2024 ADUCG RESEARCH

我最近收到一个关于 Karma 里皮肤着色的问题:在 XPU 里它是怎么工作的?怎样才能把位移(displacement)和次表面散射(subsurface scattering)调到正确的程度?

在这篇文章里,我希望能帮助你在 Karma 中为皮肤着色并获得更好的效果。当然实现方式不止一种,但我希望能给出一个扎实的基础,你可以在此之上构建自己的角色着色方案。

这篇教程会比我之前的一些文章更偏基础,但希望你仍然能从中学到一些有用的东西!

Karma XPU 在渲染 SSS 时速度很快,我认为它能以相对少的工作量输出很棒的效果。不过你需要了解其中一些“坑点”(gotchas)。

本教程我会使用 3D Scan Store 提供的优秀资源 Free 3D Head Model。它的模型与贴图质量都很扎实;如果你想跟着做,欢迎直接下载。

文章的前两节会先概述皮肤着色器中会用到的关键特性,随后进入更偏实操的皮肤着色教程。

让我们开始吧!

最终转台(带皮肤着色器)。

Karma 中的次表面散射(Subsurface Scattering)

💡

本文中我会交替使用 SSS 与 Subsurface Scattering 两个说法。如果你不熟悉,SSS 只是 Subsurface Scattering(次表面散射)的缩写。

次表面散射是一种现象:光线进入物体内部后在内部发生散射。对皮肤着色来说,这个效果至关重要,因为它模拟了皮肤的半透明特性。

来自维基百科的示例:手指上的次表面散射。

本教程我们会使用 Karma XPU,因此必须使用新的 MaterialX 着色器。总体而言,即使你使用的是 Karma CPU,我也建议直接用 MaterialX,因为 SideFX 已经表示这是 Houdini 着色的未来方向。

另外请注意:本文的所有操作都发生在 Solaris(也就是 /stage 上下文)中。

要搭建一个 MaterialX 着色器,你需要在 Material Library LOP 里创建一个 MaterialX Material Builder

MaterialX Material Builder 内部。

进入这个新建的子网络后,你会看到一个 MtlX Standard Surface——它相当于 Mantra 里的 Principled Shader,并提供了你制作 PBR 材质所需的大多数选项。

在我们开始搭建真正的皮肤着色器之前,我想先覆盖一下 MtlX Standard Surface 中 Subsurface Scattering 部分最关键的参数:

Subsurface

第一个要改的设置叫 Subsurface。它表示你想在着色器里加入多少 SSS。若你把它设为 1,它会完全替代着色器里 “Base” 部分的 diffuse 设置。对大多数半透明材质来说你会把它设为 1;不过出于艺术目的,也可以把它稍微调低一点,这样你可以把 SSS 与 diffuse 混合在一起。

在 MtlX Standard Surface 中启用 Subsurface。

Color

Color 基本就是字面意思:SSS 的颜色。后面的皮肤着色器里,我们会使用一个略作调整的 albedo/diffuse 贴图。

调整 SSS 的颜色。

Radius

Radius 很可能是你在调 SSS 时最常会去动的参数。它表示光线在网格内部传播多远之后才会发生散射。更高的数值会带来更强的半透明效果;更低的数值则会更弱。你甚至可以分别控制每个颜色分量(R/G/B)的半径,这在我们开始做皮肤着色时非常有用。

调整 SSS 的 Radius。

Scale

Scale 参数可以看作对 Radius 参数的乘数。由于 Radius 强依赖场景尺度,因此这个参数对不同场景单位非常有用。比如你在着色一个原本以厘米为单位的角色,后来场景改成米,那么你需要把 Scale 设为 0.01 才能获得与之前相同的半透明效果。(因为 1m = 100cm)。

Anisotropy

Anisotropy 表示次表面散射的方向性:0 是均匀散射(默认);正值会产生前向散射;负值会产生后向散射。下图是一个示例:

调整 SSS 的 Anisotropy。

Karma 中的位移(Displacement)

这一章我想覆盖两个对 Karma 新用户来说可能有些困惑的概念:细分(Subdivision)与位移(Displacement)。

在 Karma 里启用细分有两个前提条件:

  1. Mesh primitive 必须设置 Subdivision Scheme
  2. 必须把 dicing 设到合适的值

下面我们展开讲讲。

Subdivision Scheme

要把你的 mesh primitive 标记为可细分对象,你需要用 Mesh Edit LOP 选中它,并覆写 Subdivision Scheme

这不是 Karma 或 Solaris 特有的功能,而是 USD 的一部分(如果你想更“考据”一点,它属于 USDGeomMesh 这个 class/schema——这是 stage 上所有传统 mesh primitive 都会使用的 schema)。

通过 Mesh Edit LOP 设置 Subdivision Scheme。

Dicing

Dicing 用来控制你的 mesh 会被细分到什么程度。最主要的调整方式是用 Render Geometry Settings LOP 选中你要细分的 primitive。这个节点有很多实用功能,我们要用的是 Dicing 部分。

在 Render Geometry Settings LOP 中调整 Dicing Quality。

这里最核心的设置 Dicing Quality,对应的是你的渲染中每个像素会生成多少“微多边形(micro polygons)”。值越低,细分越少;值越高,细分越多。我觉得这比很多其他渲染器的控制方式更优雅。

由于它基于像素,因此它本质上是视图相关的细分方式,有点类似你在 V-Ray 等渲染器里见到的那种“视图相关细分”。

如果你愿意,也可以进一步控制 Minimum 与 Maximum dicing。

调整 Dicing Quality。

创建一个皮肤着色器(Skin Shader)

现在我们开始搭建真正的皮肤着色器。

如前所述,我使用的是 3D Scan Store 的免费 Female Head 模型,你可以在这里下载。

本教程我只会用到 Textures/JPG/Face 文件夹中的贴图——它还提供了用于 micro bump 的额外贴图以及多张 mask,但我想展示的是:仅用一套最基础的 Diffuse、Displacement、Roughness 贴图,你也能做到什么程度。我认为皮肤着色的“魔法”更多在于:你如何让着色器去“解释”这三张贴图。我把其余探索留给你。

我们会用到的贴图:位于 Textures/JPG/Face 与 Textures/JPG/Displacement 文件夹。顺序为:Diffuse、Normals、Roughness、Specular、Displacement。

位移(Displacement)

我们先从位移开始。类似之前引言中的说明,我们需要通过一个 Mesh LOP 在头部网格上指定 Subdivision Scheme。记得要精确选中 mesh primitive 本身——不要选顶层组。

选中 Head 的 mesh primitive。

通过 Mesh LOP 设置 Subdivision Scheme。

接下来我们需要设置 Dicing Quality,确保位移与细分足够精细。做法是添加一个 Render Geometry Settings LOP,目标同样指向该 mesh primitive(这里就是头部),然后调整 Dicing。我把它设得相对较高(2),以获得更锐利的位移细节。

通过 Render Geometry Settings LOP 调整 Dicing Quality。

完成上述设置后,创建一个 Material Library LOP,进入内部,创建一个名为 skin_shd(或你喜欢的名字)的 Karma Material Builder。在其中你会看到标准的 MaterialX 与 Karma 节点组合。

Karma Material Builder 内部。

现在我们来添加 displacement 贴图。为此我们需要一个 MtlX Image 节点——这是 MaterialX 中用于加载纹理的标准节点。把 Textures/JPG/Displacement/ 里的 displacement 贴图加载到 Filename 参数。

在它之后你还需要接一个 MtlX Separate Vector 3。这么做是因为 displacement 贴图只使用红色通道(你可以参考文章前面的贴图 contact sheet)——这样我们就能把该通道转换为 float,并让这张贴图等效地作为灰度图来使用。

最后,把它接到 MtlX Displacement 节点,并把 Scale 调到与你场景尺度匹配的数值。这个值会因资产而变化很大。对这个资产来说,我发现 0.00165 的效果相当不错。

👁️

就这套 displacement 贴图来说,我发现眼皮会有点“肿”。如果你想进一步优化这套位移,一个不错的第一步是为眼皮做一个 mask,用它在该区域降低 displacement。

添加 MaterialX Displacement。

应用位移后的默认着色器。

高光与粗糙度(Specularity and Roughness)

在我们进入次表面散射之前,先快速看一下如何调整高光。这同样是皮肤着色中非常重要的一部分,而且它经常会受位移影响很大——这也是我为什么先调位移。

在配置 specularity 与 specular roughness 时,我喜欢先把 diffuse/base color 设为一个中性灰:0.18。这能给我一个相对中性的基准,便于观察灯光如何与着色器的高光成分交互。

之后我把 Specularity 打开(如果还没开的话就设为 1),并用 MtlX Image 加载 Textures/JPG/Face/Face_Specular.jpg。我把它接到 Specular Color,并用 MtlX Remap 重新映射,因为它原本非常暗。我把 Inhigh 设为更低的值,压缩取值范围,让原本的 0–0.07 被映射到 0–1,从而得到更亮的贴图。

使用 MtlX Remap 重映射 Specular 贴图。

接着我用另一个 MtlX Image 加载 Textures/JPG/Face/Face_Roughness.jpg,并同样用 MtlX Remap 做重映射。之所以这么做,是因为我对默认 roughness 贴图不太满意:我觉得它不够“粗”,所以我把低值抬高了一些。

使用 MtlX Remap 重映射 Roughness 贴图。

我还把 IOR 设为 1.44,因为它通常是皮肤的一个不错起点。

MtlX Standard Surface 的 Specular 部分。

得到如下结果:

带 specularity 且 diffuse 设为 0.18 时的着色器渲染结果。

次表面散射(Subsurface Scattering)

现在我们进入着色器最核心的部分:次表面散射。和大多数着色一样,这是一个创作过程;找到合适的平衡会因资产而异。我会尽量给你一个好的起点,剩下的就交给你继续探索。别怕试一些离谱的数值——如果你想更深入理解,主动“把东西搞坏”是非常重要的学习方式。

我们从 Subsurface 参数开始。如前所述,它控制着色器中 SSS 的强度。通常你会把它设为 1.0,但就我这个案例,我把它调到了 0.7。这样我可以混入一点 diffuse 着色,让皮肤显得更不那么通透、稍微更“实”一些。

接着我把 diffuse 贴图同时接到 Subsurface Color 参数,以及(着色器顶部的)Base Color 参数,以便利用这套资产自带的优秀皮肤纹理。

Albedo 贴图连接。

我用一个 MtlX MultiplySubsurface Color 乘以 [1, 0.975, 0.975],让它略微偏红。这有助于强化皮肤内部在光照下呈现出的红润感。

用于 Subsurface Color 的 MtlX Multiply。

对于 Base Color,我也做了一点调节,用来抵消 Subsurface Color 中增强的红色。这里我使用了一个 MtlX Color Correct,把 Saturation 设为 0.5,做了一个简单的去饱和。对一些人来说这可能会觉得去饱和太多,但我发现它与其他着色部分组合起来,会呈现非常自然的观感。

用于 Base Color 的 MtlX Color Correct。

在其他类型的着色器里,你可能见过三层工作流:Deep、Mid、Shallow 三层 SSS(例如 AlSurface)。这对获得正确的皮肤外观非常重要。对于只能使用一层 SSS 的着色器(例如 MtlX Standard Surface),你可以通过把 radius 的 R/G/B 通道设为不同的数值来模拟更复杂的散射效果。

对皮肤来说,我建议使用 [1.0, 0.35, 0.2]。这个值我毫不掩饰地“借鉴”自 Arnold 文档,但它确实非常好用。

Subsurface Radius 设置。

最后你需要调整 scale。对于这个 Female Head 模型,我发现 0.001 的效果相当不错。再强调一次:这强依赖你的场景尺度。

Subsurface Scale 设置。

到这里,我们就完成了最终的皮肤着色器!如我之前提到的,你还可以继续在此基础上做很多事情,例如添加一层 micro-bump 来模拟更小的毛孔。但我认为这套着色器已经是非常好的起点,而且即使在特写镜头下也能站得住。

💡

我的转台灯光由一个 Dome Light 组成,并加载了来自 Polyhaven 的 HDRI。你可以在这里获取

最终转台(带皮肤着色器)。

结语(Conclusion)

以上就是:在 Karma 中搭建一个基础皮肤着色器。它比我过去两三篇文章更短一些,但希望你读得开心。我发现关于“如何在 Karma + MaterialX 中做正确的皮肤着色”相关资源并不多,所以我希望这篇文章能为刚接触该渲染器的艺术家提供一些可参考的资料。

一如既往,如果你在评论区有任何问题,或者你希望我覆盖某个主题,欢迎留言。我们下次见!

我还计划了更多内容;如果你感兴趣,可以订阅我下面的 newsletter,这样每篇新文章都会直接发到你的邮箱里。

本文采用 Creative Commons BY-NC-ND 4.0 协议进行授权。

BY-NC-ND: 署名-非商业性使用-禁止演绎

End of Article