1.2 程序化建模的核心范式


1.2 程序化建模的核心范式

本节摘要:程序化建模是声明式范式——描述"结果满足什么规则"而非"每一步怎么操作"。Houdini 用节点依赖图实现它:每个节点是纯函数,改参数只触发受影响路径的重算。本节用一个"返工实验"对比命令式与声明式的差异,讲清非破坏性、可迭代性与版本化能力。

一个返工实验

沿用 1.1 的山体网络。现在假设美术总监说:"山脚太平了,压一点下去。"

命令式做法(传统雕刻软件的思路):进入点级别,框选山脚区域,手动下拉几百个顶点,缝合、修法线。总监第二天说"还是放回去吧"——你重做一遍,这次往上调。

声明式做法(你现在的网络):在 Mountain 后插一个节点,按高度做映射——高于阈值保持,低于阈值往压。总监反悔?删掉这个节点。前后十秒。

第二种做法里,你没有"操作山",你修改了山的定义。这就是声明式建模:网络是一份可执行的规格说明书,几何体只是它某一次求值的结果。

命令式:操作序列 → 最终状态(历史丢失,返工=重做操作) 声明式:规则网络 → 每次求值出结果(历史即网络,返工=改规则)

依赖图:非破坏性的机制

为什么改 Mountain 的参数,Scatter 会自动重算,而 Grid 不动?Houdini 内部维护一张依赖图:每个节点记录自己吃谁的数据、喂谁。参数一改,该节点被标"脏",脏标记沿下游传播,被标脏的节点在下次显示时重算,上游没脏就不碰。

图 1.2-1 脏标记传播

这个机制解释了三个日常现象:

  1. 改上游,下游全刷——脏标记只向下游传播;
  2. 改下游参数,上游不重算——Scatter 换种子不会重算 Mountain,所以很便宜;
  3. 回放任意历史版本——每个节点都缓存自己的输出,把显示flag 移到中游,就看到中间形态。网络本身就是无限长的撤销历史。

💡 关键直觉:节点不是"操作的记录",是"函数的组装"。你会用函数式的眼光看它:同样的输入+参数,永远得到同样的输出。

声明式带来三种工程能力

能力 在 Houdini 里的样子 没有 it 时的代价
非破坏性迭代 任何阶段都能改参数回上游 返工即重做
规模化 种子/参数扫一遍,出 100 座山 手做 100 次
协作与交接 网络即文档,别人能读懂你的意图 靠口头与截图传递

第三点常被低估。一个结构清晰的网络,接手的人从左到右读一遍就知道你做了什么、在哪改。这也是第 7 章 HDA 能成立的前提——封装的前提是逻辑可见

范式的代价

声明式不是免费午餐。两条代价要心里有数:

  • 求值粒度粗:改一个参数,整条下游路径重算。模拟类节点(第 5 章)重算极贵,所以有缓存与锁定的设计;
  • 心智负担前移:你得在动手前想清楚规则的分层——哪些是"形状规则"、哪些是"分布规则"、哪些是"随机规则"。想清楚了网络才不会长成一团意大利面。

⚠️ 常见坑:为了一个小改动把参数暴露得到处都是,网络变成"参数迷宫"。规则的分层要在设计时想好,而不是靠事后加旋钮弥补。

本节要点回顾

  • 声明式:网络描述规则,几何是求值结果;返工=改规则而不是重做操作;
  • 依赖图+脏标记:非破坏性与中间版本回放的机制基础;
  • 改下游便宜、改上游贵:顺手记下,第 8 章性能优化会反复用到这条规律;
  • 规模化是声明式的自然产物:换种子即换变体;
  • 封装的前提是逻辑可见:网络即文档。

下一节把镜头拉远:这套节点机制在整个软件里是怎么按车间分层的。

延伸:参数化裂纹的完整推导

范式三要素(规则、参数、随机性)的融汇可以用一个"碎裂"小实验检验:给定一块面板,让裂纹随种子与密度参数变化。先用 Voronoi Fracture 得到碎块,关键在后续的参数化边缘处理:

// Attribute Wrangle (Run Over: Primitives) —— 碎块按"距中心衰减"缩放 vector c = getpointbbox_center(0); // 整体包围盒中心 vector pc = prim(0, "P", @primnum); // 用 centroid 更稳: 逼近即可 float d = distance(c, pc); float shrink = fit(d, ch("inner_r"), ch("outer_r"), 1.0, ch("gap")); f@shrink = shrink; // 传给 Transform Pieces 的 scale

用 Transform Pieces 按 @shrink 缩放每块,gap 参数立刻控制裂缝宽度,seed 改变裂纹形态。注意范式的分工:Voronoi 是规则、gap/inner_r/outer_r 是参数、seed 是随机性——三者任何一方缺失,资产都无法进入迭代流程。

延伸:非破坏性与"编辑即声明"

范式对照实验 破坏式(传统): 直接改网格顶点 -> 上游一变, 修改全部蒸发 程序式: 修改记录为序列节点 -> 上游变化时, 序列重新作用于新数据 验证法: 在裂纹实验上游换一个不同形状的面板(圆盘->六边形), 全链不重搭, 结果自动适配 —— 这就是"声明优于命令"的工程含义 边界: 非破坏性有代价(内存/依赖追踪), 何时"冻结"(Bake)成 破坏式快照, 是第八章性能工程要回收的问题

关于范式的常见误解也要趁早澄清:程序化不是"自动生成",参数不是"随机按钮"。一个健康的程序化资产里,随机性占比通常不超过两成,其余八成是确定性的规则与映射——随机只负责打破完美对称、制造个体差异,从不负责决定结构本身。判断一个资产范式是否健康的简易标准是"导演测试":需求变更(山往西、路加宽、房子少三层)到来时,你是改参数、改规则,还是重搭网络?前两者占比越高,范式越成熟。这个测试把"程序化"从工具问题提升为设计问题:你在设计的不是某个结果,而是一族结果的生成空间,参数轴的选取本身就是创作。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U