Houdini中的植物生成
介绍
大家好,我叫Kilian Baur,是来自德国的 CG 通才。
我一直对传统艺术技术很感兴趣,比如绘画、粘土雕刻或造型/铸造物体。在高中的时候,我对编程产生了兴趣,并使用 java 编写了许多非常小的程序。想要一份有创意的工作,我尝试了建筑学和计算机图形学。原来,CG 对我来说是艺术和技术工作(如编程)的完美结合。
在学习期间,我尝试了 3D 中的许多不同学科,例如动画、角色雕刻或纹理。但我一直最喜欢的是建模。我也开始学习 python 来自动化Maya 中的一些重复过程。因为我的两个朋友真的很喜欢Houdini并且制作了一些非常棒的东西,所以我也决定尝试一下。我做了一些项目,比如对棋盘进行程序建模,并生成了经典 8×8 网格以外的不同棋盘尺寸。
在RISE Visual Effects Studios实习并参与 Mike Flanagan 的 Doctor Sleep 工作期间,我真的学会了喜欢 Houdini 的程序工作流程。我开始在这个软件中做尽可能多的事情。
程序方法
虽然我喜欢 3D,但有些任务在一段时间后会变得非常重复。有时,听音乐和移动一些多边形是很放松的,但我发现程序方法更有吸引力。这就像一个谜题,您正在解决问题并试图找到一种方法来使某些事情完全程序化。这就是我非常喜欢 Houdini 和编程的原因。他们都奖励更具技术性的思维方式。
由于程序设置通常比破坏性方法花费更多时间,因此在电影制作期间使每个资产完全程序化并不总是正确的决定。在家里做个人项目,我真的没有时间限制,可以挑战自己。
在创建一个新项目时,大多数时候我对如何处理它有一个松散的想法。每个项目的方法都不同。一般来说,我将项目拆分为更小的具体任务,然后尝试逐一解决。
有时,我已经知道如何在 Houdini 中实现某些效果(来自教程或以前的项目),或者我可能会想到一种方法来实现它。然后,我必须弄清楚是否已经有节点可以解决我的问题,或者我是否必须使用 Python 或 Houdini 的表达式语言 VEX 来构建自定义解决方案。
程序化工作非常有趣,因为有很多方法可以解决每个问题,而每个艺术家可能会以不同的方式解决它们。与其他艺术家交流知识是学习新技术和工作流程的好方法。
即使某些方法没有按预期工作,您也可以后退几步并尝试另一种方法。因为一切都是程序性的,所以尝试一个想法并不会真正失去任何东西。
2 中的1
关于程序性多肉植物项目
在实习期间,我学到了很多关于 3D 的知识,但没有做个人项目。我想要一些较小的项目,我可以在几天内完成并展示我的一些新技能。
目前,我对植物的形状以及如何在 3D 中生成它们感兴趣。我学到了很多关于 L-Systems 的知识,它是描述植物生长的好方法,我想用它们做一个项目。在为这个项目寻找参考资料时,我发现了两张非常酷的多肉植物照片。
2 中的1
创造多汁植物似乎是一个有趣的挑战。起初,我只想创造“经典”多肉植物,但完成后,我决定测试我可以从我的设置中得到多少不同的形状。
另外,我想测试一些其他渲染引擎。虽然Houdini自己的“Mantra”有很多很酷的节点和着色功能,但它也以不是特别快而著称。尤其是渲染无噪声次表面散射 (SSS) 可能会非常痛苦。对于这个项目,我为 Houdini选择了Arnold,因为 Arnold 标准表面着色器是我的最爱之一,而且 GPU 渲染看起来很有希望。
数学部分
每个项目所需的数学和脚本量是不同的。有时,很难找到可以构建其他进程的规则或依赖项。一些项目可能需要大量的向量数学,比如使用两个向量之间的角度或使用旋转矩阵/四元数来旋转对象。
该部门的多肉植物非常简单。他们不需要任何复杂的数学。大多数数学由简单的乘法、除法和加法组成,我计算每个叶子的偏移量。这样每个级别的叶子均匀分布,然后我将它们稍微抵消一些变化。
另外,我计算了叶子的一些属性。它们基于控制植物整体形状的几个坡道。这样就很容易对植物的外观进行广泛的改变。
叶子生成
一般方法涉及创建单个叶子作为第一步。然后,我根据每个级别的叶子数复制并旋转叶子。最后,我对每株植物的级别数重复此操作。
每个级别都有一些不同的叶子生成设置。这样,我可以创建有趣的形状。为了控制形状,我有一些参数。除其他外,我可以设置级别数、每个级别的叶子数或单个叶子的长度。
每个工厂级别的长度、宽度、角度等都不同。为了轻松控制这些属性,我有一个斜坡参数和一个浮点参数(浮点数)。渐变控制每个属性的形状。因为斜坡只能在 0 到 1 的范围内轻松控制,所以我还使用浮动参数来更改每个斜坡的幅度。
为了使用坡道,我将它们细分为工厂的层数。我读取每个步骤的值并将它们保存为数字数组。在生成叶子时,它们从与当前植物级别匹配的位置读取值。
使用这种方法,我可以根据需要添加尽可能少或尽可能多的级别,而无需做更多工作。每株植物的层数越多,它就越接近坡道的形状。
我通常采用坡道底部的叶子很小的方式。它们变得更高,在最后几个级别,它们再次变短。此外,每片叶子的弯曲在级别之间都非常剧烈。在较低的水平上,叶子几乎是平的,但弯曲度随着每一层的增加而增加,直到它们几乎形成一个封闭的形状。
在这个例子中,植物有 9 层,每层有 6 片叶子。第一层叶片弯曲10°,弯曲量达到110°。
为了生成叶子,我从一条简单的线开始。我重新采样以获得更多分辨率并生成“curveu”属性。该属性的根值为 0,尖端为 1。使用这些值,我可以定义形状并最终为叶子添加一些颜色。
基于斜坡,我将每个点在 Z 方向移动一定量以形成一般形状。我添加了一条中心线并使用“扫描”节点来创建叶子的一半。之后,我向上弯曲两侧并镜像它以获得完整的叶子。
我使用“polyExtrude”并稍微平滑位置以增加厚度。点位置上的噪声用于在每个叶子上添加一些变化。这样,即使它们在同一级别内,每片叶子看起来也有点不同。
在我弯曲叶子之前,它们通过简单地进行平面投影来获得它们的 UV。
为了添加更多细节并在背面中央创建一个可见的脊椎,我将中心线沿着它们的法线移动了一小部分。
在程序上找到所需的点并不困难。当我镜像两侧时,我使用了“熔断器”节点来组合两侧。熔断器节点能够输出一个只包含被修改点的组。这些是我用于中心脊柱的点。
使用从根到尖端的颜色渐变添加颜色。起初,我只想用颜色来形象化不同的植物。但我最终渲染了这个颜色属性,因为它已经足够好了,尤其是在添加了一些 SSS、凹凸和光泽之后。
整个叶子生成设置在两个循环内。内部的绿色循环重复进行,直到生成一层的叶子。外循环负责总级别的数量。使用当前级别,叶子从先前生成的数组中读取它们的特定参数(例如长度、角度等)。此外,我使用当前叶和当前级别为某些参数生成一些随机性。这样,每片叶子看起来都有点不同。
花盆和土壤
锅主要是程序性的。我不需要能够在建模后大幅改变其形状。这就是我为某些操作明确选择特定边的原因。
另一方面,土壤是完全程序化的,可以改变其高度。我采取的第一步是在所需高度剪裁锅几何。然后,我删除了所有不在里面的东西。我使用了“polyfill”节点并删除了除结果之外的所有内容,以获得正确高度的完美拟合平面。最后,我将几何体重新划分为许多偶数三角形并添加了 UV。在渲染过程中,我将该平面细分了几次,并使用Megascans中的一些纹理进行着色器和置换。
为了添加更多细节,我在土壤上撒了一些来自 Megascans 的鹅卵石。我能够实例化花盆和土壤 12 次,以减少渲染时的内存占用。重复是不可见的,因为它的大部分都被植物隐藏了。另一方面,每个锅的鹅卵石都是随机的,位置、大小、旋转和石头数量各不相同。
工作流的优势
按程序做所有事情的最大优势是能够相当快速地进行更改。我能够尝试很多不同的植物形状。我什至测试了 Houdini 的 PDG 以创建许多变化并了解我的英雄植物应该是什么样子。
使用过程依赖图 (PDG),我为植物生成创建了许多具有不同属性的楔形。每个植物都以极小的分辨率使用 OpenGL 渲染。渲染完所有植物后,它们会自动组合成一个巨大的图像。
最终的 12 个工厂中的每一个都基于相同的设置,只是一些不同的参数。唯一需要额外工作的工厂是带织带的工厂(见下文)。
处理与几何相交的线
我首先尝试使用“连接相邻部分”节点,但这个节点有一个大问题。创建的线与植物几何体不切实际地相交。为了避免这种行为,我创建了一个新工具,用于在添加线之前检查潜在连接是否会与另一个几何体相交。
创建线条后,我将它们弯曲以使它们不太直,同时确保我不会添加许多新的交叉点。
这个工具的构建相当简单,因为我能够重用来自原始节点的大量代码。我添加了一些小功能,例如删除与几何相交的点,因为对于这些点,每条可能的线也会与某些东西相交。另外,这样我就不会创建完全在几何内部的线。否则,仍然会创建这些线,因为从技术上讲,它们不会与几何体的表面相交。
为了检查连接是否会与几何体相交,我使用“相交”VEX 函数从起始位置向另一个点的方向发送光线。如果我得到一个交叉点,那么我不会创建一条线。