今天刷到这个作品,我盯着屏幕看了好几遍——一个半透明的球体里,无数分支像血管一样蔓延、爆开,烟雾从里面涌出来,循环往复,停不下来。
做这个效果的人叫 Karlis Stigis,一位常驻纽伦堡的 3D 与动态设计师,平时做产品演示、广告和品牌传播的视觉动画。他有纯艺术、视觉传达和平面设计的背景,按他自己的说法,是把艺术思路和技术实验混在一起用。
![]()
而这个作品的起点,说出来有点扎心:他的 Instagram 账号被盗了,后来被封。
一个被封的账号,和一个"重生"的念头
他提到,那段时间他一度以为自己再也不会开新账号了。理由很朴素——如果花了几年攒起来的东西可以一秒消失,那还重新开始干嘛?
但他说自己骗不了自己,还是想看看别的创作者在做什么,也想把自己的东西发出去。
于是回归后的第一条内容,他想做点能和"重生"在视觉上押韵的东西,一个新开始。他自己也不确定这个念头是动手前就有的,还是做着做着冒出来的——有时候潜意识会先走一步。
最后出来的,是一个类似循环系统的分支结构。里面流动的不是血,而是一种抓不住、留不久的东西:创造力的力量。
这个烟雾球是怎么搭出来的
他把整个效果拆成了几块:分支路径、从路径方向推导出的速度、从选定发射点得到的密度、用 Pyro 做的烟雾模拟,以及在 Solaris 和 Karma 里渲染。
技术部分的灵感来自 Entagma 的 Houdini VEX 教程《Space Colonization》,以及 2007 年的一篇论文《Modeling Trees with a Space Colonization Algorithm》,作者是 Adam Runions、Brendan Lane 和 Przemyslaw Prusinkiewicz。
他的实现和原思路有个区别:不是从平均吸引方向生成新的生长位置,而是把已有的点连接起来。
先定形状。他用 Labs Cylinder 几何节点做了一个简单的圆柱体,再用 Points from Volume 节点把它填满。点的间距决定了分支能长多密。
接下来是核心循环,重复三步:
- 搜索:活跃点在固定半径内寻找还没被用过的邻居。
- 连接:每个邻居挑出离自己最近的提议父点,两者之间连一条线。
- 推进:新连上的点变成活跃点,上一代停止搜索。
每个子点只有一个父点,但一个父点可以有多个子点。分组会记录未使用、活跃和已选中的点,候选父点列表用来解决多个点抢同一个连接的情况。当没有可达的未使用点时,生长就停了。
颜色上也有讲究:绿色是起点,橙色是活跃点及其搜索半径,红色是之前已连接的点,白色是还没用到的点。
调参就是在调"长成什么样"
改变搜索距离和候选数量上限,会长出完全不同的结构。半径越大,连接可以越长;候选上限则控制每个活跃点能提议多少个邻居。
他在同一套点布局上做了四组分支规则的变体,用来对比效果。
实现层面,这个循环用了四个 wrangle:INIT、find_neighbours、connect_logic 和 set_groups。INIT 只跑一次,另外三个反复执行。
INIT 把起点标记为活跃,其余点标记为空闲。每个点一开始都有自己的 __id,之后连上的子点会继承父点的 ID。
find_neighbours 负责记录候选父点,并把它们提议的邻居标记为已选中。这个版本请求的是 Pts Max + 1 个候选,所以界面上显示 3 的时候,实际允许最多四个。
connect_logic 挑出最近的候选父点,继承它的 __id,并生成连接线段。
最后一个 wrangle 是 set_groups,它遍历 __infected 和 __selected,让当前活跃点退休、清空它们的父点列表,再把选中的点设为下一轮的活跃点。
把这套逻辑套进圆柱体里的点上,就会从每个起点长出成簇的结构。按 __id 上色,就能区分不同的簇,也能单独拎出某一簇来看。每个簇都继承它起点的 ID。
从点到路径,再到方向
结构长好之后,用 Edge Transport 几何节点测量从起点组沿分支走的距离,存成 dist,并开启全局归一化。这样就能区分哪些点离根部更近、哪些点在分支更远处。
这个 dist 属性可以用颜色可视化出来。
到这一步,每两个相连点之间的线段还是独立的 primitive。PolyPath 把它们接成连续的路径,然后重采样、融合重合点、用 Group Transfer 恢复起点组,再对网络做平滑,让形状更有机一点。
处理链的最后是 direction_calc,它写出速度属性。做法是比较相邻点的 dist 值,确定朝外的方向;在 direction_calc 里,把指向 dist 更大那个邻居的向量归一化,写进那个邻居的 v 属性。
Edge Transport 提供 dist,wrangle 把顺序关系转换成朝外的方向向量。
十次循环,十个变体
为了省心,他把这套东西打包成了一个 HDA,加了几个额外控制项。分支逻辑没变,只是让下一步更好管理。
然后他把 Space Colonization 放进另一个循环里,每次迭代随机选一个不同的起点组。内层循环长出一张网络,外层循环生成十个变体,每个单独打包,方便之后挑选。
说真的,从"账号没了"到"做了个会呼吸的烟雾球",这个转折挺妙的。技术上看是一堆节点和 wrangle 的排列组合,但那个循环系统一样的结构,确实把"重新长出来"这件事讲明白了。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.