顶点着色允许烘焙复杂的纹理和渲染树信息为顶点颜色属性。与Render Map相似,但顶点着色是将表面的信息烘焙为顶点颜色(Color At Vertice,简称CAV) 的属性。因此,结果的质量大部分取决于多边形的密度。
顶点着色在游戏开发方面很有用,因为它允许你将基本的纹理信息和光照信息直接烘焙进场景物体。这样就可以删掉一些灯来减少计算量和整体场景的大小。
这种方法不倚赖于图片或者最终聚集,在某些方面优胜于传统的方法,但也存在一些局限性,就是设置繁琐。
在这里,我们使用一个简单的场景。这个场景只有一个大盒子(Box),盒子内是一辆没轮子的小车(小车多边形的密度比较大,墙脚多边形的密度相对小,大家可以注意两者的效果)。盒子的内壁已被指定了顶点颜色(名为lanlan_wall),但没有灯光和材质。我们将在盒子内顶部放置一个大的Light_Box。
首先,要为场景准确设置传统的光。每一个光源必须有一个反向的方形衰减,因此必须将它们的阴影本影设置为黑色,这就意味着场景物体的表面所反射的光要比它们接收的少。如果使用Phong,要确信Specular不会太亮,Ambient被设置为黑色。
然后,我们就使用Render Map(烘焙成CAV)把渲染树的信息烘焙成一个顶点颜色属性(CAVs)。
CAV表示原始光的第1次光反弹(bounce),并用于后来的渲染。此外,它还将用于在下一步骤中加速计算下一次光反弹。当这个光反弹不再重复影响原始光(直接光照),就使用另一个CAV表示原始光的第2次光反弹(bounce),然后添加到第1次反弹(以及添加到原始光)来增加场景的真实性。
创建灯光和材质
1.因为场景没有灯光和材质,所以要先创建这些要素。
在Explorer中删除默认的灯光。然后从Render工具栏中选取Get > Light > Light Box命令,创建一个Light Box,将它放置到盒子的内顶部上,设置它的大小为顶部的1/4左右。并且在打开的属性编辑器中设置相关的属性。如右图所示。
2.为物体指定一个phong材质。按7键打开Box物体的Render Tree,获取一个Map Lookups > Vertex RGBA节点,并将它连接到Phong材质的diffuse节点。双击Vertex RGBA节点打开它的属性编辑器,将Vertex Property设置为lanlan_wall(内壁的颜色属性),如右图所示。
3. 双击Phong节点,打开Phong属性编辑器,将Diffuse Ambient的RGB设置为黑色;将Specular Color的RGB都设置为0.05;将Specular Decay设置为23。如右图所示。
创建lightmap
如果没有使用大的区域光(Area Light),第4和5步骤可以省略。但在这个场景中,我们使用了一个大的区域光,因为它能加速第一个光反弹(bounce)的计算。这样就可以从区域光烘焙直接光照(dirct illumination)为一个新的CAV。
4.为Box物体创建一个RenderMap属性(选择Box物体,然后选取Render > Get > Property > Render Map命令)。如左图所示。
5.在打开的RenderMap属性编辑器中,将Basic页面中的Sampling设置为vertices only(RenderVertex);在Resulting CAV区域中单击New按钮,创建一个新的Color At Vertices(简称CAV),然后单击Edit按钮重命名为lanlan_light;勾选Disable区域中的Refraction和Reflection项以及Sampling区域中的Average colors around vertices项。
锁定RenderMap属性编辑器,使它处于活动状态,以便于下次使用。如右图所示。
6.单击Regenerate Map…按钮重建Render Map(这样就将渲染树的信息烘焙成lanlan_light)。
在Material属性编辑器中预览,它看起来与步骤3的渲染图像一样。如左图所示。
创建第1次光反弹(bounce)
7.在Render Map属性编辑器,创建一个新的CAV,并且命名为lanlan_bounce1;取消勾选Disable区域中的Reflections项。如右图所示。
8.在Render Tree视图中,从Nodes菜单获取Reflection_diffuse和Ray_type节点,将前者连接到后者的eye上,将Vertex RGBA节点连接到Ray type的reflection上,然后再将Ray type节点连接到Material的Surface上。
在Vertex_rgba属性编辑器中,将Vertex Property设置为lanlan_light。在Reflection_diffuse属性编辑器中,将Reflection的RGB都设置为1,设置Gloss为1,设置Samples为12。如右图所示。
注意:
通常,光泽反射会分配到被反射的eye light的采样点上,渲染它们而不用于GI计算。当使用Render Map,被反射的eye light就会指向表面法线的同一个方向,这是GI采样点的来源地。
Render Map会将光泽反射物体作为反射物体,因此通过Ray_type节点将一个标准的表面shader附加到reflections,将光泽反射shader附加到eye上。
9.在RenderMap属性编辑器中,单击Regenerate Map…按钮重建lanlan_bounce1。如右图所示。
注意:
RM/reflection diffuse shader有个bug,就是当多边形面与坐标平面正对齐的时候,会显示为黑色。所以在这里我们要稍微旋转一下Box物体(0.1,0.1,0.1),使多边形不再平行于正交平面(XY,YZ,XZ)。
创建第2次bounce
创建好第1次 bounce后,接着为直接光创建第2次bounce。这是来自第1次bounce的光。直接光照(lanlan_light)不被列入计算范围,因为它已经被反弹过了。在最终渲染中就不用重复渲染它了。
10.在RenderMap属性编辑器,创建一个新的CAV,并且命名为lanlan_bounce2。
11.在Render Tree视图中,从Nodes菜单中获取两个Vertex_RGBA节点(Map Lookup节点),分别命名为wallcolors和bounce。连接节点后,在wallcolors节点的属性编辑器中,将Vertex Property设置为lanlan_wall;在bounce的属性编辑器中,将Vertex Property设置为lanlan_bounce1;在Mix_2colors节点的属性编辑器中,将Weight color的RGB都设置为1,并且设置Mode为Hide/Reveal(Multiply)。如右图所示。
12.重建lanlan_bounce2。在Material属性编辑器中预览,它看起来有点黑。如右图所示。
创建更多的光反弹(bounce)
要产生一个真实的效果,最好创建一个总数大约为6-8次的bounce。在这里,因为bounce能很快地变黑,所以4个就足够了。否则,材质容易会出错。
13.打开Render Map属性编辑器,创建一个新的CAV,并且命名为lanlan_bounce3。
14.将渲染树的wallcolors节点的Vertex Property设置为上次产生的bounce (也就是lanlan_bounce2),然后重建lanlan_bounce3,它看起来会更黑。如左图所示。
15.重复13和14步骤,创建lanlan_bounce4,并重建它。如右图所示。
创建总光照的CAV
16.在Render Map属性编辑器中,创建一个新的CAV,并且命名为lanlan_total。
17.在Render Tree视图中,从Nodes菜单中获取4个Vertex RGBA节点(Map Lookup节点)和一个Mix_8colors节点。将这4个节点(在此重命名为bounce1、bounce2…)分别连接到Mix_8colors节点的color1、color2…,然后在它们各自的属性编辑器中,将Vertex Property分别设置为lanlan_bounce1、lanlan_bounce2,以此类推 。如左图所示。
18.在Mix节点的属性编辑器中,将Base Color的RGB都设置为0。将Layer1、Layer2、Layer3和Layer4设置为In Use,将这4层的Weight RGB都设置为1,将Mode设置为Add。如右图所示。
19.重建total,在Material属性面板中预览,效果如下图所示。如左图所示。
最终渲染
20.在Render Tree视图中,从Nodes菜单中获取两个Vertex RGBA节点(Map Lookup节点),分别将它们命名为lanlan_color和bouncetotal。在lanlan_color的属性编辑器中,将Vertex Property设置为lanlan_wall;在bouncetotal的属性编辑器中,将Vertex Property设置为total;在Mix_2colors属性编辑器中,将Mode设置为Hide/Reveal(Mutiply),设置Weight的RGB都为1;在Mix_2colors1属性编辑器中,将Mode设置为add,设置weight的RGB都为1;Phong节点的设置与步骤一相同。如右图所示。
21.最终的渲染效果如下图所示。大家可以看到,小车的效果比盒子的效果要好,那是因为小车的多边形密度比盒子的大。如左右图所示。