下面的 OSL 材质模拟了 Tony Reynolds 制作的皮肤着色器,它采用了由红、绿、蓝波长调制的分层次表面散射(layered subsurface scattering)。此外,着色器实现了一个 Dual lobe Specular (two-lobe spec,双叶瓣高光)来捕捉人类皮肤上高光的微妙变化。
不同波长的光穿透皮肤的深度不同。如果我们将可见光谱简化为三种颜色(红、绿、蓝),那么每一种颜色的平均自由路径(光子在被散射或吸收之前穿过特定物质的距离)的值就会不同。对于人类的皮肤来说,红色是最深的,然后是绿色,蓝色是相当浅的。
color Depth = getTextureDif(RGB_Scatter_Depth, color(0.8,0.2,0.1));
...
color SubColor = getTextureDif(Subsurface_Color, color(0.85,0.75,0.65));
...
color SubR = SubColor * color(1,0,0);
color SubG = SubColor * color(0,1,0);
color SubB = SubColor * color(0,0,1);
基于以上理论,着色器将主颜色纹理(次表面颜色)分离为红色、绿色和蓝色部分,并将这些部分输送到三个次表面着色器中,然后将它们组合在一起。这三个次表面着色器的深度(即平均自由路径)由相应的 RGB_Scatter_Depth
颜色的红、绿、蓝通道驱动。为了加快速度,将绿色和蓝色结合在一起,所以着色器将两个 SSS 闭包组合在一起(红+绿&蓝)而不是三个。
closure color SSS = vray_subsurface ( IOR, PhaseFunction, Depth * Depth_Scale * 0.5, SubColor * Subsurface_Amount, "subdivs", Subdivs);
closure color SkinR = vray_subsurface ( IOR, PhaseFunction, SubR * Depth[0] * Depth_Scale, SubR * Subsurface_Amount, "subdivs", Subdivs); closure color SkinGB = vray_subsurface ( IOR, PhaseFunction, ((SubG * Depth[1]) + (SubB * Depth[2])) * Depth_Scale, (SubG + SubB) * Subsurface_Amount, "subdivs", Subdivs);
所基于的想法是,所有人类的主要散射颜色是红色(因为我们在不同的肤色下都有红色的血液)。
换句话说,RGB 散射深度本身并不是一种颜色,而是分别代表红、绿、蓝三种波长的散射系数。因此,将波长 RGB 深度颜色的红色通道设置为 1.0 意味着红色波长的深度是 100% ,而将其设置为 0.7 意味着它是 70%,以此类推,对于所有三个 RGB 通道。
请注意,在下图中,红色通道比绿色或蓝通道更柔和,因为它有更多的深度。
这种方法的另一个好处是,当它设置的散射量较大时,它几乎消除了 SSS2
材质的薄部分可能出现的 “绿色误差”,因为它将多个次表面着色器线性混合在一起,而不像在 SSS2
材质将中次表面和散射颜色之间进行更复杂的相互作用,虽然更 物理正确,但对艺术家来说可能 不直观。
总的来说,这个着色器的 重点 是优先考虑 艺术控制 而不是 物理正确性 。像 VraySkinMtl
这样的分层皮肤着色器的一个 缺点 是,用户需要将不同(通常 不直观)的颜色混合在一起到达想要的皮肤颜色。