Blocking Out City With Houdini PDG | 使用Houdini PDG生成城市白模

Houdini PDG是17.5版本新增的一个任务管理模式,方便最终结果的分步生成。笔者当前使用的17.5.258版本,鉴于这个功能刚刚出现,目前似乎是还有些bug,其后的版本可能会修复的。

到目前为止(~2019.6,确实没看到什么houdini engine + pdg的教程,只有Kenny Lammer的一套PDG for Indie Game Dev。

笔者尝试将之前道路生成,地块生成文章整合进一个PDG,生成一个小的城市,体验一下PDG的使用。那自然是有很多坑。

个人感觉PDG的主要优势:

  • 显式化分步操作,方便每步参数调整,避免整体生成时间过长。
  • 多线程生成,PDG中有一个任务调度器,自动根据依赖关系给空闲CPU指派workitem。
  • 方便程序互操作,可以调度maya/p4v等等,其实用以前可以py自己写,这次显式地增加了这个功能。

但目前还有个问题是Dirty模式有点奇怪或者有bug,你永远不知道一个节点是否recook,用了哪次生成的cache。

分布操作这个事情,其实以前很多用户都有这种操作习惯:前一步生成文件cache起来存在硬盘上,比如粒子/物理渲染的逐帧模型,然后直接从文件读取cache进行下一步操作。PDG封装了这个模式,每一个HDAProcessor都会自动缓存文件并交给下一步操作,使得整个程序是流程更自动化。

多线程呢是比较好用的,但问题是为什么需要那么多的同样种类不同参数的资源?就算生成了,游戏里为了资源优化考虑,也没必要这么多变化,倒是可以理解成方便挑选参数,从参数空间中多生成一些,人肉梯度下降,从这个意义上讲,可以一定程度上提高生成资源的质量。另一个问题是,多线程不会导致生成时间倍数缩短,比如terrain分成四块处理,笔者的感觉也就每块提高了1倍的速度。并且还有线程调度和开销和cache存储的开销,每个item都会有常量时间的浪费。

对于游戏开发为什么需要PDG?个人感觉还是indie小团队的场景生成比较需要。当前版本的houdini engine在unity内的交互实在是难受,大厂可能会有自家的引擎或者编辑器,并且有人力开发引擎内与houdini交互的组件。至于HDA的任务调度?在引擎内做其实也可以啊,有钱就多加点build机好了。而与maya/p4v互操作呢,引擎里一般都集成了。所以也就是对没有精力重写引擎与houdini交互的小厂开发者,使用houdini engine + PDG会方便很多。

以下是一些Houdini Engine的注意:

1. Workitem与Input

一个HDA可能有1~9999个input

一个HDA Processor只有一个Input,但是可以有多个work item(绿色的点)

一个work item执行一次HDA,因此如果一个HDA需要3个input,那么每个work item都需要3个input那么问题来了,当前work item的input怎么对应前面的哪个work item?如果前面workitem数量都一致,很好办,用partition by index。但是当前HDA Processor的输入的work item数量可能不一致,怎么办?如果只有2个input,partition by index的模式中secondary input打成all就行,但是3个input就挂了。

比如这里,最下面的HDA Processor需要连三个input,上面三个input分别有4,1,1个work item。我希望下面HDA processor有4个work item,第i个对应上面的,i,1,1号work item.只好自己写python partitioner。在partitioner中,work_items是输入的所有workitem,我们需要把他们加到partition_holder中。

注意这个api,partition_holder.addItemToPartition(workitem_i, index)

index是后面workitem的id,没有显式给出如何设定这个workitem_i成为下面workitem的几号input id,因为它把workitem_i设成了第index个workitem的下一个input。

总之相当的绕

2. Cache与Dirty,粒度选择

每个HDA Processor会自动cache文件的。一般来讲,如果上游的文件dirt了或者重新生成了,下游的应该重新生成的。但是有时候,下游的直接去读cache了。。。。这样上游的修改就没进来。只能强行一个一个dirty and recook。有一个Workitem Generation的模式选择,感觉static就是只能手动重新生成,dynamic是每次下游一cook都自动cook一遍,笔者也并没太绕清楚。。。。

因为有可能有会有dirty不到的问题,笔者建议PDG中的HDA越少越好,粒度要达到一组输入一个HDA,不要为了重用做太多HDA。如果太多的话哪个一没dirty后面就全坏了,笔者最后才意识到这个问题然而为时已晚。

3. HEngineData

HEngineData

这个好像只跟HEU有关,可以看HEU_PDGObjects.cs中的TOPNodeTags定义。用这个原因是

  1. 不然的话TOP中所有节点都会显示在unity中,很乱
  2. 不然的话,PDG一次只cook一个东西出来,会想让它自动加载一些东西。

使用方法是top中的节点自定义加一个string类型的henginedata,填show就是unity能看到,填show,autoload就是能看到且能自动加载。HEU会加载时自动读到这个参数的。

至于有关项目的一些原理:

道路

主要是这篇文章 Procedural Street Modelling In Houdini 1 | Houdini中程序式街道生成 I 使用的技术,用tensorfield创建道路。

需要输入的是

  1. population mask,人密度图
  2. seed points,一些产生道路的点,一般不用太多
  3. Grid guide,用于生成方格网络的引导线

地块

主要是这篇的技术 Procedural Parcel Modelling In Houdini | Houdini中程序式生成街区地块

别墅

这里用了L-system生成基底。

这里只是白模block out,也就没考虑模块组装的问题

后记:路的一部分HDA开源在我Github的这个仓库

参考资料

Procedural Street Modelling In Houdini 1 | Houdini中程序式街道生成 I

Procedural Parcel Modelling In Houdini | Houdini中程序式生成街区地块

3 thoughts on “Blocking Out City With Houdini PDG | 使用Houdini PDG生成城市白模

发表评论

电子邮件地址不会被公开。 必填项已用*标注