第十五章 次表面散射效果的思路与实现
什么叫次表面散射?简而言之就是在物体内部P产生的漫反射、反射、折射和吸收所形成的半透明效吊,例如翡翠、玛瑙、蜡烛以及人皮肤所表现出的通透效果。
我不想在此用长篇大论讲述半透明物体在物理学中是如何通过介质来过滤光波的波长等原理性的东西。因为这些对于我们在MAYA中实现次表面散射效果没有任何用处,我们似乎只能模拟出类似的效果。目前次表面散射在渲染技术领域仿佛又成了新的衡量标准,例如Brazil等渲染器以渲染此效果见长。
次表面散射英文译为sub surface Scattering,人们习惯于称之为3s效果,可以生成这种效果的材质被称为3s材质。对于三维模型来说,它们都只是一个“空壳”,都是由曲面包装成的实体。因而在模型中更谈不上有什么介质一类的东西。所以要制造真实的3s效果就耍采用光能传递的光子过滤挂术来实现了,不幸的是Maya中的MentalRay尽管可以模拟这种效果,但其渲染速度慢得惊人,实用介质几乎为零。
看起来3s效果在Maya中实现似乎有点望尘莫及。其实,也不完全是这样。我们在实现一种效果时往往有两种途径。—种是技术途径,大多表现为功能以及程序方面的研发,另一种是艺术途径,即是通过观察而来用特殊或取巧的办法来实现。
下面我们就一步一步的研究如何在Maya中实现真实的3s效果。值得注意的是,本章中最终完成的3s效吊完全是通过笔者的直觉想象出来的,属于首创。
常规技术与思路
使用特殊或取巧的方法来实现某种效果也不是一件容易的事,它需我们反复的思考和实验。想到3S半透明效果,我们首先就会想到Maya材质中的半透光属性Translucence。Translucence属性可以很好的表现光源处于物体背面时的透光效果,例如阳光穿过树叶的透光效果。
global proc subSurfIllum ()
{
string $shadSel[] = `ls -sl -type lambert`;
string $lSel[] = `ls -sl -type transform`;
string $lightSel[];
if (`size $lSel` == 0)
{
$lightSel = `ls -sl -type light`;
}
else
{
$lightSel = `listRelatives -s $lSel`;
}
if ((`size shadSel` == 0) || (`size $lightSel` == 0))
{
warning "You need to select at least one shader AND one light...!!!";
return;
}
string $testLight;
for ($testLight in $lightSel)
{
if (`attributeExists "lightDirection" $testLight` == 0)
{
warning ("Attention: " + $testLight + " is not a light...");
return;
}
}
string $shadItem;
string $lightItem;
for ($shadItem in $shadSel)
{
if ((`objExists ("pmaLI_" + $shadItem)` == 1) && (`objExists ("pmaLD_" + $shadItem)` == 1) && (`objExists ("pmaLDCl_" + $shadItem)` == 1) && (`objExists ("pma_blndCol_" + $shadItem)` == 1))
{
delete ("pmaLI_" + $shadItem) ("pmaLD_" + $shadItem) ("pmaLDCl_" + $shadItem) ("pma_blndCol_" + $shadItem);
string $pmaLI = `shadingNode -au plusMinusAverage -n ("pmaLI_" + $shadItem)`;
setAttr ($pmaLI + ".operation") 3;
string $pmaLD = `shadingNode -au plusMinusAverage -n ("pmaLD_" + $shadItem)`;
setAttr ($pmaLD + ".operation") 3;
string $pmaLDCl = `shadingNode -au plusMinusAverage -n ("pmaLDCl_" + $shadItem)`;
setAttr ($pmaLDCl + ".operation") 3;
string $pmaColMix = `shadingNode -au plusMinusAverage -n ("pma_blndCol_" + $shadItem)`;
string $cl = ("subS_cl_" + $shadItem);
string $lu2 = ("subS_lumLightDir_" + $shadItem);
string $vp = ("subS_vpLightDir_" + $shadItem);
string $bld = ("subS_bld_" + $shadItem);
connectAttr -f ($pmaLDCl + ".output3D") ($cl + ".input");
connectAttr -f ($pmaLI + ".output3D") ($lu2 + ".value");
connectAttr -f ($pmaLD + ".output3D") ($vp + ".input1");
connectAttr -f ($pmaColMix + ".output3D") ($bld + ".color1");
int $noum = 0;
for ($lightItem in $lightSel)
{
connectAttr -f ($lightItem + ".lightDirection") ($pmaLDCl + ".input3D[" + $noum + "]");
connectAttr -f ($lightItem + ".lightIntensity") ($pmaLI + ".input3D[" + $noum + "]");
connectAttr -f ($lightItem + ".lightDirection") ($pmaLD + ".input3D[" + $noum+ "]");
connectAttr -f ($lightItem + ".lightIntensity") ($pmaColMix + ".input3D[" + $noum + "]");
$noum++;
}
}
else
{
string $r = `shadingNode -at ramp -n ("subS_rinterp_" + $shadItem)`;
string $rout = `shadingNode -at ramp -n ("subS_rout_" + $shadItem)`;
string $mp = `shadingNode -au multiplyDivide -n ("subS_multInt_" + $shadItem)`;
string $mp1 = `shadingNode -au multiplyDivide -n ("subS_multLightI_" + $shadItem)`;
string $vp = `shadingNode -au vectorProduct -n ("subS_vpLightDir_" + $shadItem)`;
string $si = `shadingNode -au samplerInfo -n ("subS_si_" + $shadItem)`;
string $lu = `shadingNode -au luminance -n ("subS_lumInt_" + $shadItem)`;
string $lu2 = `shadingNode -au luminance -n ("subS_lumLightDir_" + $shadItem)`;
string $sr = `shadingNode -au setRange -n ("subS_sr_" + $shadItem)`;
string $cl = `shadingNode -au clamp -n ("subS_cl_" + $shadItem)`;
string $bld = `shadingNode -au blendColors -n ("subS_bld_" + $shadItem)`;
string $pmaColMix = `shadingNode -au plusMinusAverage -n ("pma_blndCol_" + $shadItem)`;
setAttr ($r + ".type") 1;
setAttr ($rout + ".type") 1;
setAttr ($r + ".interpolation") 4;
setAttr -type double3 ($sr + ".max") 1 1 1;
setAttr -type double3 ($cl + ".max") 1 1 1;
string $pmaLI = `shadingNode -au plusMinusAverage -n ("pmaLI_" + $shadItem)`;
setAttr ($pmaLI + ".operation") 3;
string $pmaLD = `shadingNode -au plusMinusAverage -n ("pmaLD_" + $shadItem)`;
setAttr ($pmaLD + ".operation") 3;
string $pmaLDCl = `shadingNode -au plusMinusAverage -n ("pmaLDCl_" + $shadItem)`;
setAttr ($pmaLDCl + ".operation") 3;
connectAttr -f ($pmaLDCl + ".output3D") ($cl + ".input");
connectAttr -f ($cl + ".output") ($lu + ".value");
connectAttr -f ($lu + ".outValue") ($r + ".uCoord");
connectAttr -f ($pmaLI + ".output3D") ($lu2 + ".value");
connectAttr -f ($lu2 + ".outValue") ($mp + ".input2X");
connectAttr -f ($lu2 + ".outValue") ($mp + ".input2Y");
connectAttr -f ($lu2 + ".outValue") ($mp + ".input2Z");
connectAttr -f ($mp + ".output") ($mp1 + ".input1");
connectAttr -f ($pmaLD + ".output3D") ($vp + ".input1");
connectAttr -f ($si + ".normalCamera") ($vp + ".input2");
connectAttr -f ($vp + ".output") ($sr + ".value");
connectAttr -f ($sr + ".outValueX") ($rout + ".uCoord");
connectAttr ($pmaColMix + ".output3D") ($bld + ".color1");
//int $sizeL = `size $lightSel`;
int $noum = 0;
for ($lightItem in $lightSel)
{
connectAttr -f ($lightItem + ".lightDirection") ($pmaLDCl + ".input3D[" + $noum + "]");
connectAttr -f ($lightItem + ".lightIntensity") ($pmaLI + ".input3D[" + $noum + "]");
connectAttr -f ($lightItem + ".lightDirection") ($pmaLD + ".input3D[" + $noum + "]");
connectAttr -f ($lightItem + ".lightIntensity") ($pmaColMix + ".input3D[" + $noum + "]");
$noum++;
}
// adding subScattering extra attributes
if (`attributeExists "translucenceColor" $shadItem`)
{
return;
}
else
{
addAttr -ln translucenceColor -at float3 -uac $shadItem;
addAttr -ln translucenceColorR -at "float" -p translucenceColor $shadItem;
addAttr -ln translucenceColorG -at "float" -p translucenceColor $shadItem;
addAttr -ln translucenceColorB -at "float" -p translucenceColor $shadItem;
setAttr -type double3 ($shadItem + ".translucenceColor") 1 1 1;
addAttr -ln translucencePower -at double -min 1 -max 10 -dv 1 $shadItem;
addAttr -ln lightColorMix -at double -min 0 -max 1 -dv 0 $shadItem;
addAttr -ln density -at double -min 0.01 -max 1 -dv 0.01 $shadItem;
addAttr -ln opacityFactor -at double -min 1 -max 10 -dv 1 $shadItem;
addAttr -ln interpolation -at long -min 1 -max 6 -dv 4 $shadItem;
addAttr -ln oldAmbientColor -at float3 -uac $shadItem;
addAttr -ln oldAmbientColorR -at "float" -p oldAmbientColor $shadItem;
addAttr -ln oldAmbientColorG -at "float" -p oldAmbientColor $shadItem;
addAttr -ln oldAmbientColorB -at "float" -p oldAmbientColor $shadItem;
// re-connections
connectAttr -f ($shadItem + ".translucenceColor") ($mp + ".input1");
string $con[] = `listConnections ($shadItem + ".ambientColor")`;
int $size = `size $con[0]`;
if ($size > 1)
{
string $outputT[] = `listAttr -st "outColor" -st "outValue" -st "output" -st "outRgb" -st "outHsv" $con[0]`;
disconnectAttr ($con[0] + "." + $outputT[0]) ($shadItem + ".ambientColor");
connectAttr -f ($con[0] + "." + $outputT[0]) ($shadItem + ".oldAmbientColor");
connectAttr -f ($shadItem + ".oldAmbientColor") ($r + ".colorEntryList[0].color");
}
else
{
float $oldAmbient[] = getAttr ($shadItem + ".ambientColor");
setAttr ($shadItem + ".oldAmbientColorR") $oldAmbient[0];
setAttr ($shadItem + ".oldAmbientColorG") $oldAmbient[1];
setAttr ($shadItem + ".oldAmbientColorB") $oldAmbient[2];
connectAttr -f ($shadItem + ".oldAmbientColor") ($r + ".colorEntryList[0].color");
}
connectAttr -f ($shadItem + ".interpolation") ($rout + ".interpolation");
connectAttr -f ($shadItem + ".opacityFactor") ($sr + ".oldMaxX");
connectAttr -f ($shadItem + ".opacityFactor") ($sr + ".oldMaxY");
connectAttr -f ($shadItem + ".opacityFactor") ($sr + ".oldMaxZ");
expression -s ("" + $sr + ".oldMinX = -(" + $shadItem + ".opacityFactor);\r\n" + $sr + ".oldMinY = -(" + $shadItem + ".opacityFactor);\r\n" + $sr + ".oldMinZ = -(" + $shadItem + ".opacityFactor);") -o $sr -ae 1 -uc all ;
expression -s ("" + $rout + ".colorEntryList[2].position = 1 - (" + $shadItem + ".density);\r\n") -o $sr -ae 1 -uc all ;
connectAttr -f ($shadItem + ".translucencePower") ($mp1 + ".input2X");
connectAttr -f ($shadItem + ".translucencePower") ($mp1 + ".input2Y");
connectAttr -f ($shadItem + ".translucencePower") ($mp1 + ".input2Z");
setAttr ($r + ".colorEntryList[2].position") 0;
setAttr ($r + ".colorEntryList[0].position") 1;
setAttr ($rout + ".colorEntryList[0].position") 0;
connectAttr -f ($mp1 + ".output") ($bld + ".color2");
connectAttr -f ($bld + ".output") ($r + ".colorEntryList[2].color");
connectAttr -f ($shadItem + ".lightColorMix") ($bld + ".blender");
connectAttr -f ($r + ".outColor") ($rout + ".colorEntryList[0].color");
setAttr -type double3 ($rout + ".colorEntryList[2].color") 0 0 0;
connectAttr -f ($rout + ".outColor") ($shadItem + ".ambientColor");
}
}
}
}
国外有一位专门研究Maya材质及渲染的大师名叫Emmanuel Campin,他在光影表现方面有很多突出的研究成果。针对次表面散射的3s效果他也提出了一个解决方案,并写了一小段Mel脚本程序用于专门生成他所创造的复杂节点连接关系网,我们现在可以使用他的方法来试一试。
首先,将下列代码输入到Maya的Script Editor中:
由SubSurflllum产生的节点连接关系图。
我们从图中可以看到的却要比默认的材质效果通透一些,但这也绝不是半透明的3S效果。
经过反复初中,笔者发现SUBsURFILLum的作用竟与Translucence属性的作用十分相类似,都是在背光时可以产生很好的半透光效果,而不能在正面光源时产生好的半透明效果。所以这个程序并不实用。
真实3s效果的思路与实现
实现3s效果的方法有很多,我们可以一一尝试,但首先应该放弃使用光能传递(Radiosity)和光线跟踪Raytrace)的想法。因为使用这两种方法就算可以制作出相对真实的3s材质地果也有很大的局限。首先就是渲染速度的问题,过慢的速度无疑会大大降低它的实用性,其次,这两种方法都需要很多条件才能正确产生3s效果,它们对光的方向、大小,对材质的折射等都有特定的要求。所以,我们最好还是通过默认的渲染器来模拟。
一次偶然的机会使笔者发现,原来半透明的物质(例如翡翠)都由远及近明度渐变的特点。
观察一个翡翠的工艺品,试想一下,如果将高光去掉,剩下的部分应该就是明度渐变的效果了。这使得笔者不由自主得想起了模拟深度通道的材质。如果将深度通道材质叠加上高光点将舍怎样呢?
下面让我们来试一试吧
首先,我们要创建深度通道材质。在第十二章使用工具节点中,在讲述Distance Between工具节点部分我们阐述了制作深度通道材的三种方法,大家可以到前面查询。
现在我们就使用最快捷的表达式创建方法来制作一个深度通道材质。
制作深度通道材质
◆在HyperShade中创建一个samplerInfo节点和一个surface shader材质。
◆为了表达式输入方便,将samplerInfo重命名为si,将surface shader重命名为ss。
◆选择ss材质,按ctrl+A键,打开它的属性编辑器。在属性编辑器菜单中选择attributes>Add Attributes,打开添加属性的设置窗口。添加一个名为Depth的浮点属性,如图15.8所示。
[page]
◆在顶部菜单中选择Window>Animation Editors>Expression Editor,将如图15.9所示代码输入,然后点击Create按钮创建表达式。
渲染深度通道效果
◆在顶部菜单中选择File>Import,将光盘中的Chapter01_face_01d.mb文件导入此场景中。
◆将Ss材质赋予头像模型。
◆将摄像机推到头像模型近处,进行渲染,效果如图15.10所示。
3s半透明的效果虽然制作出来了,可是我们必须清楚还存在的问题。首先,由于此半透明效果材质是右深度通道材质构建的,这就导致明暗由摄像机的远近决定,无法固定。其次,半透明效果只是用表达式生成的从0到1的数值来呈现灰度效果,还不能加之以色彩。
第二个问题还是很好解决的,用一个Blend color节点在表达式和材质之间作为关连即可将其它颜色融合。关键在于第一个问题是个难点。我们先来分析一下,如图15.14所示,摄像机到采样点之间的距离控制了材质的明暗,而摄像机的位置又是不固定的。这样,在三维动画的制作中,材质势必会产生忽明忽暗的效果,这是我们不想看到的。
正常的状态应该是材质的明暗等一切效果有自身特定的属性控制,而不应受摄像机的影响。那么,我们应该为摄像机到采样点求出一个固定的距离。准确的说,不应该是摄像机,应该是从摄像机到被采样点之间取一个固定点,该固定点到摄像机之间的距离是随着摄像机位置的变化而变化的,而该固定点到被采样点之间的距离是固定不变的。然后再自此固定点到被采样点之间的远近来确定材质的明暗。这样,材质的明暗就舍相对固定了。
固定点需要满足两个条件。第一,该点必须始终保持在摄像机;被采样点两者的连线上。第二,固定点是相对固定的,它必须可以由一个属性来控制,用以确定它控制材质的明暗,如图15.15所示。简而言之,我们是耍将摄像机远近来控制明暗的局面转变成由自定义属性来控制,而与摄像机无关。
要达到这样的目的我们必须要从材质工具节点入手。让我们先来分析深度通道材质形成的决定性因素。如图15.16所示,数据是由SAMPLERiNFO节点的PointCamera属性输出。
Pointtcamera属性代表的是被采样点在摄像机坐标空间中的位置。我们必须找到点到被采样点距离的测量载体。在第十二章使用工具节点中我们了解到,light Info节点的sample Distance属性具有与Pointcamera相类似的作用,它可以获得摄像机、光源或其它物体到被采样点之间的距离,如图15.17所示。
值得注意的是,light Info节点的sample Distance属性具有最大的优势,其主要体现在目标点是采样点,而起始点可以是摄像机和摄像机以外的任何物体。那么,我们可以随便创建一个Locator或NuRBs球体来作为固定点的标识。
[page]
由此,我们决定用light Info节点的sample Distance来代替sample Info节点的Pointcamera属性。
下面是关于固定点如何定位在摄像机与被采样点之目连线上的问题。
准确的说,没有办法可以精确定位。
但是通过特殊手段可以近似的定位。例如固定点是一个Locator,我们可以将Locator的中心放置在物体中心上,并应用Aim cotrain目标约束让Locator始终看着摄像机。笔者认为这种定位方法完全可行,它与精确定位之间的偏差在渲染效果的影响上是肉眼难辨的。 技术难点分析完毕,我们可以开始制作了。
实现次表面散射的3S效果
1 制作Light Info节点的固定连接结构
Light Info节点的固定连接结构是将一个物体矩阵输出,再经过一个动画曲线节点输出。在maya中动画曲线节点(animcurve)包含TL、TA、TT、Tu、UL、UA、uT、uu共8种娄型。这种节点很特别,它没有常规属性,它的属性就是在Graph Editor中被编辑的动画曲线。anim curveUU的分类是按着输入输出的数据类型安排的。它之所以分类如此详细完全是为了满足各种数据类型的转换,与Light Info连接的是anim curveeUU节点。
通常,light Info节点将sample Distance数据传递给anim curceUU节点的Input属性,再经过由anim curveuu控制数据传递给一张Ramp纹理。
总之,anim curveuu可以在采样距离和幅度之间进行非线性控制,这是固定用法,大家需要记住它。创建这种固定用法的方法有两种,一种是通过spotlight聚光灯的Intensity curve来创建,再打断与聚光灯Intensity属性的连接,代替为我们需要的对应属性。另一种方法是直接用Mel脚本程序创建。使用第二种方法创建灵活性较大,并且使用一次性输入的脚本也较方便。
下面,我们就来制作这种固定方法。
◆从随书光盘中将sss_start.mb场景文件打开。这是一个包含头像模型和灯光的场景。
◆将下列代码输入到script Editor中:
createNode animcurveUU
setkeyframe-float 0 -value 1;
setkeyframe-float 1 -value 0;
hypershadePanelGrapMand(“hyershadePanell”addselected”);
按ctrl+Enter键执行程序。于是我们便在脚Hypershade中看到有一个anim curveuu节点被创建出来,如图15.18所示。
该动画曲线节点有两个关键帧组成。选中该节点,再选择顶部菜单Window>Animatiion Editors>Graph Editor,打开动画曲线编辑窗口,可以看到由这两个关键帧组成的动画曲线,如图15.19所示。
◆在HyperShade中创建一个Light Info节点、一个Surface Shader材质和一个Ramp纹理。
◆将Light Info节点的Sample Distance属性与anim CurveUU节点的Ihput 属性连接,再将anim CurveUU节点的Output属性与Ramp纹理的v Coord 属性连接。
◆将Ramp纹理改成上白下黑的色块过渡模式。再将Ramp纹理的OutColor属性与Surface Shader材质的OutColor属性相连接,形成如图15.20所示的节点连接关系。
2 创建采样距离的固定点
◆在顶部菜单中选择create>Locator,创建一个Locator定位器,并将其移动到头像模型的上方约1.5个单位,如图15.21所示。
◆选中Locator,按ctrl+G键,为其创建一个组,并将此组重命名为GroupL。
现在,我们将这个Locator看成是定义被采样点距离的固定点,而在它上面的组则是这个固定点所在的中心轴。
[page]
◆选择头像模型,将其重命名为oldMan。
◆将下列代码输入Script Edit 0r中:
float $plv[]=xform -q -a -piv oldman;
setatr groupL.tx $piv[0];
setatr groupL.ty $piv[1];
setatr groupL.tz $piv[2];
按Ctrl+Ent er键执行程序。
此程序先将头像模型的中心位置获得并存储在变量$piv中。再将数值分配给固定点所在的中心轴(即Locator上面的组),使固定点所在的中心轴;头像 模型的中心轴重叠。
◆选择顶部菜单create>cameras>camera,创建一个摄像机。我们假设此摄像机就是被渲染摄像机,将其重命名为camera—sss。
◆在Top顶视图中选择视图菜单camera_sss视图,并将该视图从左上方看物体,调整其适台的角度和构图,如图15.22所示。
◆选择顶部菜单Window>Outliner,在打开的Outliner列表中选择Camera_sss再配合Ctrl键同时选择Groupl,注意选择顺序不要弄错。
◆在Animation菜单模式下选择顶部菜单Constrain>Aim。这样,我们就用Camera_sss摄像机对Grouph进行了目标约束,使Grouph总是看着Camera_sss摄像机。
但是,我们经过观察后发现,目标约束的轴向错了。默认状态下的目标约束是X轴指向目标体,而我们应该让Y轴指向目标体才对。
◆在0utliner列表中选中处于GroupL_aim constrain节点,按CtrI+A键打开它的属性编辑器,将AimVector属性的X轴和z轴均设为0,将Y轴设为1,如图15 23所示。这样就使得GroupL的Y轴指向Camerasss摄像机了。
现在场景中的Camera_sss摄像机无论怎样运动,Locator总是用Y轴指向它,并目Locator的位置始终是处在摄像机;头像模型中心点的连线上,不会脱离轨道,如图15.24所示。
选中locator,在script editor中输入下列代码:
[page]
hypershadePanelGrapMand(”hyershadePanel1”addselected”)按ctrl+Enter键执行代码。我们可以看到Locator被载入Hypershade的工作区域中了。将Locator节点的WorldMatrix[0]属性与Light Info节点的WorldMatrix属性相连。
不知大家有没有发现,其实这一系列的节点连接同样是为了创建一种深度通道材质的效果,只是实践的手段不同,最终所形成的控制方式不同,渲染的结果也不同。现在完成的深度通道效果不会因摄像机的远近而改变明暗,明暗的改变完全由Locator的位置所决定。下面我们就对这种深度效果进行调试吧
3 调试深度效果
◆将surf…shader赋予头像模型物体,并渲染效果,如图15.25所示。
我们看到头像是一片漆黑。这主要是由于采样距离与实际情况不符造成的。我们可以使用ipr渲染实时观测效果。
◆打开anim curveUU节点的属性编辑器,将locator到头像模型中心的大概估计距离输入到第二个关键帧TIME中,我们看到采样距离趋于正确的时侯和,IPR立刻渲染出深度的效果,如图15.26所示。
打开anim CurveUU节点的属性编辑器,将Locator到头像模型中心的大概估计距离输入到第二个关键帧的Time栏中,我们看到采样距离趋于正确的时侯,IPR立刻渲染出深度的效果,如图15.26所示。
将Locator沿Y轴向内移动到1.2个单位,我们发现深度效果整体变亮了,如图15.27所示,由此我们知道Locato的TranslateY属性可以控制半透明效果的深度明暗。
打开Ramp纹理的属性编辑器,将色块过渡调整成如图15.28所示的样子,并观察渲染效果。我们由此知道RAMP纹理的色块过渡可以影响由白到黑的深度对比。
[page]
通过调试,我们明确了各个节点在深度效果产生中的作用,唯独没有控制颜色变化的节点,下面我们就来进行颜色的控制。
4 添加颜色控制
在Hypershade中创建一个Blend Color节点。
将Ramp纹理的Out color属性与Blend Color节点的Color1属性相连,再将Blend Color节点output属性与surface shader材质的out color属性相连,替换原有的连接。
打开Blend Color节点的属性编辑器,调整color2属性的颜色。我们由此得知,Blend Color节点的Color2属性可以控制深度效果的颜色。
最后形成的节点连接关系以及颜色调整如图15.29所示。
5 叠加高光和反射
在ypershade中创建一个blinn材质,并将其属性设置成如图15.30所示。
再创建一个layeredshader材质,打开它的属性编辑器,分别将blinn材质和surtace shader材质用鼠标中键拖动到layered shader attribute中。blinn材质置于左侧,layeredshader置于右侧。
综合一切可调整因素,利用ipr渲染观察效果,最终获得如图15.31所示渲染效果。
为了制造更加光滑的表面,我们可以利用第十三章材质运用技术中创建的metal maker金属材质生成器脚本程序创建金属材质,并利用反射。
[page]
使用metal maker.mel金属材质生成器脚本程序创建金属材质节点连接网。
将名称为lkmetal的phonge材质删除。并将原来连接到lkmetal材质的ramp纹理和envball环境纹理以同样的方式分别连接到blinn材质的reflectivity和reflected color属性上。
最终形成如图15.32所示的节点连接关系。
从材质样本球中我们也不难看出,反射效果过于强烈。我们可以通过控制反射两个ramp纹理来调整反射的强度。
最终渲染效果如图15.33所示。
我们还可以将所有可以控制3S半透明效果的属性都统一的整合到最终的层材质中,以extra attribute额外添加属性的形式予以方便的调整控制。通过这些控制我们还可以调整出各种不同的3S半透明效果。
最终效果如图。