首页 > 经验 > 其他行业 > Maya渲染逼真的树木
2015
04-14

Maya渲染逼真的树木

渲染树木可以说是非常困难的一件事,因为树干和树叶有着不一样的着色需求,它们各自还需要连接到合适的动画和交互之上。

对于这个项目来说,非常重要的一点是同步动画和原始Paint Effects节点之间的变动,所以在生成树木的过程需要采用非破坏性的方法。你首先会注意到的是一个被命名为“ oakTree_LeavesUV”的隐藏节点,这是“oakTree_Leaves”的副本。该副本是用于将UV转移到原始的“oakTree_Leaves”节点的,因为Paint Effects会尝试生成每一帧的UV,这样实际上会重置每一帧树叶上的UV,但是我们需要每一帧的UV保持一致。

我也将橡树分成了3个独立的对象,这样可以尽可能高效地处理它们,这三部分分别是树叶、枝干和树干。我将树干和枝干独立出来是因为大部分的枝干都会被树叶遮盖,因此对于我们的镜头来说,不使用材质贴图来着色枝干也是可以接受的。树干成为了独立的几何图形之后,我们要处理的多边形数量就降低了,意味着我们可以高效地进行造型和绘图,而且文件大小也可以变得很小。

1

RMS的其中一个优势是它能够很好的处理PTEX文件。这些文件可以为不带UV的模型添加材质。通常来说材质填充器会在2D画布上填充像素,但是在PTEX文件可以在3D画布上填充Texel,因此模型本身就不再需要(UV)2D表示。有几个绘图和造型软件都可以很好地兼容PTEX,包括Mari和Mudbox。

为了实现合适的Mudbox工作流,我们在导入和导出时需要考虑某些属性的问题。还有一点很重要的是,素材在最终完成之后的拓扑结构不能更改,因为PTEX会对每个表面分配一个ID,所以如果更改拓扑结构的话,分配到的ID就会出错。

Mudbox的PTEX设置

我们首先要做的是先了解PTEX的工作流和向量置换(vector displacement)。为了提取准确的贴图,我们需要确保导入的基础网格在整个绘图和造型过程当中不会受到影响,所以就需要在一个副本网格中完成所有的操作。在一个新的图层中进行造型也是很好的做法,这样就可以避免影响到原来的几何图形。

为了准备好导入的几何图形,我们需要进入“Mesh”>“PTEX Setup”,然后你会看到下图所示的窗口。这个窗口可以对你的几何图形应用Texel分辨率,这个选项可以在调整的过程中随时改变。对于树木,我选择的是4百万Texel,相当于2K的材质。Texel的数量越多,文件的大小就越大。这是我们需要记住的一点,因为PTEX文件会比传统的光栅图像大得多。

2

Mudbox的PTEX向量置换

为了确保可以准确导出向量置换,请将原始模型设置成“Target Model”,并将副本网格(带有全部细节)设置成“Source Model”。这样做可以确保你会将VD贴图分配到Maya中没有改动过的几何图形。请不要选择“Smooth Target UVs”,因为你在细分和准备原始几何图形的时候已经完成这项操作了。

3

请不要改动Texel的“Density”,因为这样做会覆盖掉模型原来的Texel分辨率。最好是将“Use PTEX Setup”选择为“Texel Distribution”,这样就可以禁用前面的两个属性。你还需要确保将“Object”选择为“Vector Space”,这是PTEX文件唯一可以用于不含UV的几何图形的方法。通常我们在“Data Format”设置中都需要选择一种浮点图像格式,这样做是为了有足够的数值来保存细节。

你在导出文件之后就可以在“ptxview”中查看它,你会在里面看到带有3D几何图形信息的PTEX文件。

4

GP着色器向量置换

GP着色器拥有针对向量置换的内置设置。我们首先要做的是将“Displacement Mode”设置成“Mudbox Vector (Obj)”,这样可以将PTEX贴图分配到模型的局部坐标空间中。这个向量空间对于不含UV和变形的几何图形来说很有用。树干部分能够完美的适应这两种类型。“Displacement Scale”应该保持在“1.0”,除非你需要做出一些明确的改动。它能够对应Mudbox的准确置换量。正如我们在Car Chapter中所看到的,PTEX贴图必须连接到“Vector Displacement”属性的主输入中,如果你尝试将它连接到每个通道的话是不行的。

一般的Maya文件节点都能很好地适用于PTEX文件,不过请确保添加一个RenderMan材质属性,用于过滤和gamma控制。

5

PTEX Support

另外一个非常重要的属性是PTEX Support,它是添加在几何图形形状节点上的,具体位置在“Attributes”>“RenderMan”>“PTEX Support”,如果没有这个设置的话,渲染器不能渲染PTEX文件。请保持这些属性为默认状态,除非你明确需要补偿PTEX参数。

6

请通过使用SGA面板分配PTEX Support属性到多个形状节点上,这样可以帮助你追踪多个对象的嵌套属性。

置换属性(Displacement Attributes)

另外一个重要的属性是对象的Displacement Bound。RenderMan里面所有的对象都有一个相关的边界框(bounding box),它能够高效地将对象读取到内存当中。为了保留这种高效性,Displacement Bound属性会向渲染器指示表面边界框的扩展程度,这样的话它就能包围表面的置换点。通常来说,你可以将Displacement Bound设置成“Displacement Scale”乘以“Float Displacement”(或者“Vector Displacement”)的结果,然后如果你看到任何的置换警告或者画面假象的话,可以适当增加Displacement Bound。如果设置值太高的话就会占用大量的内存,所以要尽可能地取一个准确的值。GP着色器有一个用于Displacement Bound的自动估值器,不过我认为手动设置这个值会更安全一些,特别当你的置换贴图较大的时候。

这些单元代表的是标准的Maya单元,而且会随对象的大小改变,所以在没有锁定变形的情况下,请谨慎调整对象的大小,因为你有可能会得到置换量和不正确的Displacement Bound。请点此了解更多相关信息。

一个非常重要的属性是将光线追踪设置为“Trace Displacements”。在默认状态下,RenderMan不会对置换进行光线追踪,这是为了避免计算每个有置换贴图产生的细节的反射和阴影。虽然这种做法在深层阴影工作流中可以快速做出优秀的结果,但是会在对阴影进行光线追踪时会在负置换值上增加许多不必要的假象。

如果将Trace Displacements设置成“None”,置换就会被忽略,这样可能会造成不必要的阴影和反射假象,因为光线没有考虑到置换,所以只会追踪原始的形状。如果将该属性设成“All”,光线会追踪置换贴图生成的每个多边形,这样的话成本就会很高,但这是最准确的的方法。另外一个有趣的选项是将Trace Displacements设成“FIne”,这样的话光线就会只追踪光源或者光线变窄的位置。

7

着色器的网络非常简单,它独特之处在于带有Maya 3D Brownian材质的高光分散(specular breakup)。它可以在光线照到的树干边缘添加一些微光。不用害怕空白的材质预览和样本,这是Maya对PTEX和某县光栅化文件的限制。即使着色器看起来没有经过编译,但是它渲染起来不会有问题。请使用脚本编辑器重复检查可能的错误。

8

树叶

对于渲染器来说,渲染树木是一项成本高昂的工作。树叶需要有透明度(transparency)和半透明度(translucency),所以如果我们没有准确理解GP着色器的话,对成千上万的树叶进行光线追踪会消耗大量的时间。

我们的视觉发展需要的是秋季的大树,上面长满各种颜色的树叶,这样就可以柔和的背景产生良好的对比。这种树叶会造成一些技术方面的挑战,包括树叶变化和恰当的半透明着色。为了做出树叶变化,我利用djPTFXUVs这个来自David Johnson的优秀脚本,将它们的UV随机分成4个UV壳。我也能够通过使用primvas随机化每片叶子的材质查找来实现这点,不过这样做可能会给叶子生成数千个节点,然后会让Maya(更不要提RIB生成了)的速度变得非常慢。

9

SideMask

我们的树叶着色器使用了一个叫做SideMask的节点,来自RMS4。这个节点可以使用表面的前后法线,你可能会问为什么不使用带有Maya节点的翻转法线(flipped normal)呢?其实原因很简单,RenderMan Pro Server 17改变了表面定位的方法,它使用全新的光线追踪遮蔽器来准确定义背面剔除。你可以点此了解相关信息。

为了做出每片树叶应有的细节,我在叶子的两面使用了不同的材质。我也添加了一个multiplyDivide节点,加倍材质的数值,不过只是针对般透明度,所以能够毫无障碍接收光线的树叶会比其他树叶更加明亮。

10

透明度

开始时我尝试了一些折中的方案,希望加快渲染的速度,比如说不使用透明度。我觉得深色的阴影会是一个很好的折中方案,但在经过一些测试之后,我决定采用一个更加细致和真实的方法,就是使用半透明度来做出透明的树叶。这种做法会牺牲一些渲染时间,你们可以在下面的例子看到这点,但是树叶看起来会变得自然得多,特别是在动画当中。

11

透明度只有在oakTree_Leaf_Shader当中的Computes Opacity设置准确的时候才能正确使用。为了做出准确的阴影,我们需要选择“Compute”(用于透明表面)或者“View Dependent”(用于类玻璃表面)。对于树木我选择的是“Compute”,因为对于如此大量的树叶来说,选择“View dependent”的成本太高了,而且它也不会带来额外的好处。后者最适合与GP Glass着色器结合使用,利用Shadow Darkness属性来模拟玻璃和彩色的阴影。

12

在开始进行透明度计算之前,请先研究树叶的类型。某些干燥和厚重的树叶的透明度较低,所以它们不需要进行透明度计算。

半透明度

GP Shader的Translucency属性在模拟灯光吸收时可以起到很大的帮助,它的成本要比SSS低得多,而且能够做出很好的超薄几何图形,如果采用次表面散射的话,计算量会非常浩大。不过要记住的一点是Translucency只在启用Transparency和Computes Opacity设置成“Calculate”的情况下有效,不然的话你不会看到任何的效果,除了一些奇怪的噪点之外。还有一点要注意的是半透明度只在现有的表面上可见,你不会在表面的前方看到这种效果。

我们使用的是着色树叶的韦恩图,我们使用分层材质在颜色贴图上叠加这个韦恩图。这样就可以更加真实地实现半透明的效果。

13

RibArchive工作流

我们在RMS18中最有趣的功能之一是全新的RibArchive工作流,尤其是当它结合到Alembic缓存的时候。使用RibArchive的好处有很多,因为它能够将大量的数据(比如说我们的树木)转换成单个.zip格式的RIB文档,这个文档能够作为单个边界框来读取,因此能够在Maya上释放大量的内存,减少所需的计算量,并大幅提升RenderMan的速度,因为它不需要在表面上进行ribgen操作。例如,你可以想象场景里面有1000棵树木,每棵树都有几千个节点,但你可以预览1000个表示树木的边界框,这样就不会导致Maya崩溃。接下来我们再想象同一个场景,但是边界框换成了Alembic缓存,这样你就可以看到带有动画的完整树木!Alembic缓存和RibArchive结合起来可以达到很强大的功能。

除了能够带来视窗和ribgen的大量加速之外,你在制作流程方面得到很多好处。你可以对原始素材进行重新着色,而且RibArchive可以理解重新编译的着色器,并一下子将其应用到整个制作流程!RibArchive也能够很好地适用于Dynamic Binding系统,你可以在这个系统中重新着色一个RibArchive,甚至完全不会影响到原来的着色器。我们会在以后的章节中进一步探讨这方面的内容。如果想了解深入的解释,请观看RibArchive docs。

GPU Alembic缓存

针对我们的橡树,我使用了结合RIbArchive的GPU Alembic缓存。为了实现这点,我们需要确保选中主要的oakTree组,并进入Animation > Pipeline Cache > GPU Cache > Export Selection选项框。确保“Optimization Threshold”有较高的取值,这样我们就可以预览树木大部分的细节,大概40000个顶点就有很好的效果了。请保留其他所有属性为默认值,这样我们就可以估计每一帧的动画。一个比较方便的工作流是将Alembic Cache和RibArchive命名为准确对应的名字(区分大小写)。

14

GPU Alembic缓存会存放在显存当中,它的大小会比系统内存更低。有时候使用传统的Alembic缓存来保存GPU资源会更好。

RibArchive

现在我们的橡树可以被转换成一个RibArchive。要做到这点,我们需要选中主要的oakTree组,然后使用RenderMan > Rib Archives > Create Node and Write Archives选项框。我们需要确保选中“Start/End”,这样就可以保存带有动画的RibArchive。很重要的一点是要记得启用“Render Globals”中的“Motion Blur”,这样会稍微降低ribgen的速度,但是我们可以灵活地启用和禁用最终场景的Motion Blur。

RMS完成ribgen之后,它会在$PROJ/renderman/ribarchives路径中保存文档,这是所有RibArchive保存的位置。着色器也会以同样的文件结构保存,你在保存RibArchive时产生的GPU缓存也会保存在同一位置。这样的话文件之间的传输会方便得多。RibArchive会限制于$PROJ/renderman/ribarchives/objectRibArchiveShape/shaders路径下的着色器,不过你可以在该文件夹覆盖任何的新着色器,不会影响到RibArchive。

Alembic + RibArchive

想要整合新生成的素材,我们可以采用如下的几个工作流:第一个是将GPU Alembic Cache导入到一个新场景中,并在选中Alembic节点的同时生成一个RibArchive节点。这样可以生成一个自动带有同一命名的GPU缓存节点的RibArchive节点。(我之前说过将两个节点命名为同一个名字会很方便!)在默认状态下,RibArchive会通过Content属性的“Siblings”与Alembic缓存交换数据,因此可以在渲染期间使用RibArchive覆盖Alembic文件。

15

第二个的步骤跟前面的一样,但是这次没有使用“Siblings”,而需要使用Content属性中的“Exisiting RIB Archive”。这样可以确保RibArchive不会跟父文件交换数据。不过这种方法的缺点是需要将Archive放到它们各自的分组,并手动从RibArchive中分离Alembic Cache。这时我们明显需要隐藏Alembic的节点(或者将它们变成模板)来避免渲染它们。

16

第三种工作流是在编写RibArchive的时候勾选Export GPU Cache。这样可以同时做出RibArchive和GPU缓存,并自动将它们整合到Maya场景中。值得注意的一点是,新生成的GPU缓存不会保存到标准的Maya位置中,而是在上面所说的RenderMan文件夹结构中。请确保时刻跟踪这种情况,避免出现重复的文件。

17

 

文章来自:www.pixar.com