本节包含有关使用分层着色器进行皮肤渲染的更高级示例。它更加概括,没有通过小的 .mi 代码段列出各个步骤,而只是简单地描述。实际上,这与在不同上下文下应用的教程第一页中完成的“操作”相同。
通常,这些着色器会取代和替换大多数旧 misss_ 着色器执行的操作。这么做的原因有如下几个:
由于 misss_* 着色器和分层着色器存在巨大差异,实际上它们之间任何方面都不具有可比性。misss_* 着色器编写用于一个不同时代,当时的计算复杂度是可以应对的,并且对着色器的预期适合当时的需求。这些着色器多年来一直很好地为我们提供服务,但是它们现在已陈旧过时,需要新一代着色器的出现。
misss_* 着色器的旧皮肤着色教程中有一些课程和想法仍可以使用,但存在以下所述的一些差异。
我们先从一个简单的头部开始。注意,本教程将使用一个多边形相对较少的头部模型,大部分为纯色,并且除了一些程序纹理,没有纹理贴图。毋庸置疑,真正的产品级着色器会将纹理应用到下面列出的几乎所有参数,以获得真正照片级效果。但考虑到通过简单的纯色可实现的着色效果,这是非常鼓舞人心的。
头部由用作灯光卡的两个入口灯光照明,即相当柔和的照明。
以下图像是仅仅将简单的默认 mila_diffuse 层置入插入到 mila_material_std 中的 mila_layers 所实现的结果。我们获得的图像如下:
现在,皮肤凹凸不平,而凹凸是皮肤总体外观的一个极为重要的部分。实际上,您无法渲染没有凹凸的皮肤。因此要做的第一件事就是应用凹凸贴图,只需将简单的程序凹凸贴图附加到刚刚创建的漫反射层的“凹凸”输入。
这些凹凸比现实生活中的凹凸略大,这样是为了更清楚地显示本教程中介绍的效果。
上面显示的图像是凹凸不平的,但看起来很像石头,因为凹凸非常粗糙。尽管采用软照明,但凹凸之间阴影中的暗色很深,而在真实皮肤中,灯光中会在皮肤下方溢出一点。
如果为蒙皮提供很好的蒙皮颜色,可得到以下结果:
现在我们来看一下 Scatter 组件着色器。我们添加 mila_scatter,在漫反射下放置一个层,并将前向散射和后向散射的着色器 R、G 和 B 散射半径都设置为 30mm。
我们还将凹凸贴图设置为漫反射层上使用的凹凸贴图,并(临时)完全关闭漫反射层以仅显示散射效果。这是通过对所有颜色采用 30mm 散射所获得的渲染:
是否注意到上图仅有散射,并且我们应用的凹凸贴图没有效果?就是这样;次表面散射位于表面的下方,而凹凸应用在表面上。
此散射看起来与旧 misss_* 着色器实现的效果非常相似,只是没有通过光照贴图等进行巧妙的设置。但是,它实际上与此处的行为略有不同;衰减呈指数级,而不是遵循像旧着色器那样的固定幂函数。这种差异很微小,但确实存在。
这意味着尽管在旧 misss_* 着色器中指定为散射半径的值真正为半径且散射仅发生在此半径内,但对于这些着色器实际上并非如此。
指数衰减从不终止,只是变得越来越小。由于没有“终止”,您设置的半径并不是散射“停止”的半径,该半径实际上是散射半径权重减少到 10% 的位置的半径。
由于我们不希望计算机对整个场景进行采样来得出要散射的灯光的潜在贡献,因此对于实际执行采样的半径大小存在限制,这就要用到 sampling_radius_mult 参数。该参数使用其他任何半径参数中指定的最大半径,并且实际上会考虑(采样)该半径中的灯光乘以半径的值。在我们的示例中,所有半径都是 30mm,并且 sampling_radius_mult 的值为 2(默认值),因此将在半径为 60mm 的范围内进行采样。
通常,默认值 2 即已足够,因为每个半径距离都表示降为 10%,半径乘以 2 表示 1%,半径乘以 3 表示 0.1%,以此类推。仅在当足够强烈的灯光照射到对象上,以致于低于 1% 的灯光将影响最终图像时,才可增加该参数。不必要地增加该参数只会增加渲染时间,并会添加更多噪波。
尽管散射效果具有示范效应,但是对所有颜色只进行单一距离散射不如按色带散射有用。通常,材质会吸收灯光,波长越短(灯光越偏蓝色),吸收的速度越快。
我们尝试将红色散射半径设置为 20,将绿色设置为 10,将蓝色设置为 5,从而得到以下结果:
上面的图像沿着蒙皮外观的方向步进!
半径值越大,效果越清晰:
上图清晰地显示了散射不同距离的不同颜色组件。请注意穿过耳朵的灯光如何根据厚度进行从黄色到橙色再到红色的各种着色变化。新着色器自动带有所有这些效果。在旧 misss_* 着色器中,穿过耳朵的散射仅为红色,因为有人使用散射颜色使其变为。此处的散射颜色仍为白色!
过去,获得接近皮肤的效果都需要使用表层和皮下散射层的多层散射。尽管为不同的皮肤层使用单独的散射仍然非常有用,但仅用一个层即可获得更好的效果!
我们将散射值调整为合理的值,如对红色采用 30mm,对绿色采用 10mm,对蓝色采用 5mm。这将得出以下结果,我们从现在起将使用该结果:
上图看起来是合理的散射扩散,但是颜色太白。但这实际上是一个重要的特征!
misss_* 着色器存在的一个问题是每个层都具有截然不同的颜色,使其很难用于指定的“最终”颜色,而且更改层之间的平衡会丢失颜色。
使用新的着色器则简单得多,因为 R/G/B 散射的总和仍趋于总体散射颜色。因此在距对象足够远的距离处不会看到散射,它将准确地呈现散射颜色,在上述示例中即为白色。稍后进行上纹理操作时,这会非常有用。
但我们希望得到更加真实的肤色而不仅仅是白色,因此将前向散射颜色和后向散射颜色都更改为漫反射层所使用的皮肤颜色。我们得到以下结果:
现在您会发现上图的颜色与漫反射渲染具有相同的总体色调。这非常适合上纹理操作。现在请记住,散射是模糊灯光,因此将纹理映射到具有大量精细细节的散射参数并不合适。一个常见的错误是将纹理映射到在裂缝中包含绘制阴影的散射组件;这是错误的,因为这使灯光无法散射到这些裂缝,违背了次表面散射的意图!
现在,由于这些总体色调非常相似,我们只需调整各个层的权重即可轻松地平衡散射量和漫反射量!
因此,我们重新打开漫反射层,并将它的权重设置为 0.5,从而得到以下结果:
上图显示的是漫反射和散射按照 50/50 混合的结果。我们可以看到,总体颜色几乎相同,只有表面的外观柔和度发生了更改。与使用旧着色器相比,这样制作外观要简单得多!
现在,我们要介绍反射,但如果没有反射对象,就不会发生什么有趣的事情。因此我们将环境贴图添加到场景,并启用“最终聚集”(Final Gathering)从上述环境照亮对象。
上图看起来很好,但很像一个极为“干燥”的面部。由于具有油滑的表层以及一些其他因素,真实皮肤的反光效果很好。
因此,我们只在顶部放置 mila_reflection 层,并为其提供与其他层相同的凹凸。结果将如下所示:
哎呀,我们忘记了几乎任何类型涂层的反射率都遵循菲涅尔曲线。但这清楚地说明了分层的能量守恒规则;在顶部添加 100% 的反射时,下层就不会通过任何灯光。由于对层的智能处理,这实际上会渲染得更快,因为此渲染不会执行任何次表面散射计算!
我们将反射层的 angular_mode 更改为 1,并将 fresnel_ior 设置为 1.4,从而得到以下结果:
哇,这个人不是出了太多的汗就是刚从浴盆里出来。
当然,上面的渲染使用的是默认完全镜面反射层。但皮肤反光非常模糊。我们将反射层的光泽度值降为 0.42,从而得到以下结果:
上图显示的皮肤表面光泽更加真实。
现在,皮肤大体上已具备了各种类型的光泽。底部有油脂,顶层有汗液等等。由于分层着色器不会仅仅因为层上的堆叠而给我们造成不利影响,因此我们就执行该操作,添加第二个光泽层。
将另一个 mila_reflection 添加到顶部,将其光泽度设置为 0.6,将层 angle_mode 设置为 1,将其 fresnel_ior 设置为 1.5,从而得到以下渲染效果:
显然,上图看上去很少有人造痕迹,因为新的光泽层完全均匀一致。实现真实效果的技巧在于通过纹理打断反射,修改表面的光泽度等。但是,对于两个完全一致的光泽层,它看上去很好。这个人物可能需要洗去一些油,但看起来很合理!
为什么在此停止呢?目前仅有几个层。
真实的皮肤上可以覆盖各种物质。同样,自动分层逻辑在此可为我们提供很多帮助。例如,我们可以尝试通过简单地在顶部添加其他彩色漫反射层,从而添加一些类似于彩装的材料。
只需贴上绿色的 mila_diffuse,为该层提供与其他层相同的凹凸贴图,并应用一些纹理作为遮罩,我们会得到类似下图所示的效果:
在实现类似上图的效果时,考虑在现实世界中的效果非常重要。彩装实际上是覆盖在皮肤上。因此,与其将它绘制到皮肤的漫反射颜色中,为什么不将它作为真正的覆盖层?
当然,此图案使我们更多地想到士兵使用的油彩,那么我们就在油彩上添加另一个菲涅尔权重的光泽反射层,使用与之前相同的凹凸和遮罩……我们得到以下结果:
上图是非常合格的战纹……
但您是否注意到我们如何开始到处重复应用遮罩和凹凸贴图?在这里,分层着色器能够彼此层叠,从而开始呈现光泽。
实现与上图完全相同的渲染的一个更佳设置是,将组成皮肤的层分组在一个 mila_layers 中,将组成战纹的层分组在另一个 mila_layers 中,然后将两个组放在第三个层 mila_layers 中,大致如下:
Reflection __
\
Diffuse _____"warpaint" layers ___
\
"overall" layers ---> material ---> mental ray material
Reflection ____ /
\ /
Reflection ___ "skin" layers __/
//
Diffuse _______//
/
Scattering ___/
此设置能让我们在较少的位置应用凹凸。我们可以在“总体”层应用凹凸,并通过一个操作将其应用到整个“皮肤”和“战纹”层。而且,我们用于遮住“战纹”的遮罩仅需要应用到整个“战纹”层一次,而不是分别应用到“漫反射”和“反射”层。
当我们要向混合材质中添加其他材质时,这种合理分割就显得愈发强大。
我们知道这是一个很好的方法,因此创建了另一个为“污垢”的 mila_layers 并将其插入“总体”层的顶部,然后为其指定特定的纹理作为权重。在该层节点中,我们添加 mila_diffuse,并将其设置为灰色。我们得到以下结果:
现在,我们有了灰泥的效果。您注意到了么,我们故意不在污物层上放置凹凸贴图,从而使其显得“平坦”,就像是覆盖在皮肤毛孔上一样。另外,污垢还遮挡了耳朵的散射,效果非常棒。
如果现在要将凹凸添加到“污垢”,我们已经知道,将此凹凸应用到“总体”层中的“污垢”层比直接应用到漫反射节点上更加明智。因此,我们添加一些(不同的)凹凸,然后将颜色更改为棕色,从而得到以下出色渲染效果:
上图是出色的干泥渲染效果。杂乱的凹凸使其看起来像干结在面部的厚泥。
现在,当我们决定将干泥变湿并更改其颜色来尝试模拟血液时,嵌套材质的优势就变得非常明显。我们只需将漫反射颜色更改为红色,在漫反射(在“污垢”层内部)顶部应用 mila_reflection,然后将其 angle_mode 设置为 1,并将 fresnel_ior 设置为 1.4,从而得到以下结果:
看!通过将材质放在嵌套的 mila_layers 中,我们可以轻松更改特性,并添加其他“子层”,而不必重复应用凹凸贴图和遮罩。我们通过一个非常简单的方法就直接将泥变为了血液。
当然,该血液看起来有点浓,我们可以简单地减小“污垢”层的权重……然后得到以下结果:
……现在,我们可以“透过”血液看到一些东西。
现在,我们用四个层容纳 8 个单独的层着色器,而且实际上对于可叠加的层没有上限。同样,上图显示了一个具有比较幼稚的程序纹理的简单模型,它看起来仍然合格。想象一下,如果每个纹理都通过艺术家创建,这会变得……
仅为提醒大家,分层是逻辑层面而不是物理层面上的,我们在“总体”层中的其他层顶部添加 mila_transparency,并使用棋盘格纹理,从而得到以下结果:
我们在上图中创建了一个全局裁切!现在,我们正在凝视这个沾满血液而且涂着战纹的可怜家伙的(空)头部。
这样可以清楚地展现层的逻辑。透明度贴在顶部,权重值为 100%,使其 100% 透明,就是这样。下面沾满泥和血液并且涂着战纹的士兵也没什么不同,也是 100% 透明。此外请注意,如果使用 mila_material(而不是透明图层)的“可见性”输入,该裁切将正确显示在 Z 深度缓冲区中和通过将输入指定到 extra_color 缓冲区而创建的蒙版中。
这样可应用许多强大的效果。而且对层进行排序可实现很多控制。例如,将 mila_reflection 层的“透明”着色器与栅格凹凸贴图交换,从而得到以下结果:
啊,现在这个家伙不再让我感到不舒服了。我想他开始有点像阿诺德·施瓦辛格了。但是,如果金属片上面也加上血迹是不是更合理些?
简单地交换“污垢”(其实是血液)以将其放置在反射金属层的顶部,从而得到以下结果:
……依此类推。如我们所见,确实不存在任何硬性限制。而且甚至不像在渲染时间进行堆叠。是的,400 个层会耗用大量时间,单单是管理如此大量的层就会非常耗时(而且,如果顶层是不透明的漫反射,不会执行其他任何层),但大量的设计人员控制以及外观制作的无限可能性还是使其成为了非常吸引人的着色器软件包。
分层着色器是最全面的库,适用于 Mental Ray 着色,并且轻松支持硬和软的组织性及非组织性表面特性。可混合能力是无限的。
继续并开始创建!