前阵子朋友在群里问,Blender几何节点里能不能做那种斜切拼花地砖——每个方块一半深一半浅、随机转90度,拼起来之后图案像水流又像迷宫。我一听就明白了,这不就是Truchet瓦片嘛。恰好我前两个月在项目里正儿八经用几何节点把Truchet节点组搭了一遍,从单格瓦片到整体铺装、再到镂空隔断都试过,踩了不少坑。这篇就把原理和实际做法一起交代清楚,想用节点做程序化拼花、地砖、装饰隔断的朋友可以直接照着抄。
Truchet这个概念本身不复杂,核心就是一张正方形瓦片,沿对角线划分成两个三角形区域,每个区域可以独立赋予颜色或材质。把一堆这样的瓦片放进网格里,每块瓦片随机旋转0度或90度,相邻边缘就会拼出千变万化的图案。它特别适合用节点来做,因为节点能把这些“随机旋转”、“网格排布”、“材质区分”全部参数化,改一个种子,整幅图案就换一张脸。
1. 核心原理:半个瓦片是怎么拼出整幅图案的
1.1 经典Truchet瓦片的长相与拼接逻辑
先看最经典的Truchet瓦片长什么样。取一个正方形,沿一条对角线切成两个三角形,两个三角形分别填上两种颜色,这就是一整块瓦片。把这块瓦片复制到网格上,每块独立旋转0度或90度,旋转之后你会发现对角线方向只有两种:从左上到右下,或者从左下到右上。
为什么只说0度和90度,不说180度和270度?因为180度旋转后两个三角形的位置互换,但拼出来的对角线方向和0度一样,视觉上等于没有变化;270度等于90度。所以真正起作用的只有两个方向。这个“两个方向切换”就是Truchet图案能产生随机感的核心:每一块瓦片都只有两种状态,但相邻瓦片之间会形成同色连续区域或对角交错,整体看起来像路径网络、花瓣纹路或者迷宫通道。
在实际拼接时,还有几个容易忽略但很关键的细节。第一,瓦片边缘必须严丝合缝,所以每块瓦片上的对角分割线不能超出正方形边界,三角形棱柱的底边要正好落在网格线上。第二,两个三角形的方向要保持一致,否则会出现某块瓦片正反面翻转导致的法线问题。第三,如果要做成实体几何,两个三角形棱柱的高度最好一致,这样拼出来的表面是平的;如果故意让一边高一边低,则会形成阶梯状浮雕效果,这反而是后面应用时很好用的变量。
1.2 为什么节点化是最顺手的方式
手动摆Truchet瓦片不是不行,我以前试过用阵列修改器加随机旋转,但那种方式有两个痛点:一是随机性不能精确控制,想固定某块瓦片的方向很麻烦;二是想换一种瓦片变体(比如把对角线换成圆弧)时,整套排布逻辑要推翻重来。节点图最大的好处就是把“排布逻辑”和“瓦片长相”拆开了。
用几何节点搭建时,瓦片本身的几何形状、瓦片在网格上的放置规则、随机旋转的种子、材质索引的分配,每一个环节都是独立的节点模块,改起来互不干扰。而且节点是实时预览的,拖一下Seed滑块,整个图案立刻变化,这种即时反馈在手动建模里几乎不可能实现。另外,节点组做好之后可以存成资产库,下次新建文件直接拖进来用,工程复用性很高。
这套思路也不只限于Blender,Houdini的VOP、Unreal的PCG、甚至Substance Designer里的平铺生成器,底层逻辑都是同一套:格网划分、单元随机状态、局部几何替换。所以看完这篇,哪怕你不在Blender里操作,换个工具也能把思路迁移过去。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 手把手搭建Truchet节点组
2.1 单格瓦片:两个三角棱柱的精确建模
搭建的第一步,不是急着铺网格,而是先把“单格瓦片”这个组件做出来。我的做法是在Blender里新建一个Geometry Nodes修改器,先不做任何外部依赖,纯在节点组里实现。
基础流程是这样:
- 用Grid节点,Size设为1米,Vertices X和Vertices Y都设为2,这样得到的是一个1×1的平面,只有一个四边形面。
- 接一个Triangulate节点,Quad Method选Fixed。这一步一定要用Fixed而不是Beauty或Shortest Diagonal,因为Fixed会把四边形固定切成我们想要的那条对角线,Beauty模式在网格优化时可能切换对角线方向,造成瓦片方向混乱。
- 三角化之后,这个平面上有两个三角形面。要分别给它们挤出成棱柱,得先把两个面区分开来。我的做法是用Position节点取每个面的中心点,然后用Compare节点判断X轴位置:中心点X坐标小于0.5的作为三角形A,大于等于0.5的作为三角形B。
- 选中三角形A,接Extrude Mesh,沿Z轴挤出一定厚度,比如0.08米;选中三角形B,同样接Extrude Mesh,挤出相同的厚度。如果你想要一个阶梯状的浮雕效果,可以把两个挤出厚度设成不同值。
这一步做完,得到的瓦片是一个完整的正方体实体,只是内部有一条斜向的分割面,两个半块还带不同的Material Index。材质索引我一般这么设置:三角形A的挤出体Material Index设为0,三角形B设为1,这样后续可以直接用Set Material节点分别赋材质,不需要再按位置判断。
这里有个容易踩的坑:直接对两个三角形面分别做Extrude时,生成的侧面和顶面可能法线朝向不一致,尤其是当挤出方向为负值时。最好在挤出完成后接一个Recalculate Normals节点,或者在挤出前就检查Input Mesh的法线方向。
2.2 整格铺开:点阵、随机旋转与种子控制
单格瓦片做好之后,把它变成一个可复用的子节点组。我习惯把“单格瓦片”这个节点组取名为Truchet Tile,输入参数只暴露Tile Size和Height,方便后面统一调整。
接下来思考整格铺开的逻辑。要做N×N的瓦片阵列,最简单的办法是用Mesh Line生成一个N×N的点阵:
- 用Mesh Line节点,Count设为N,在X轴方向生成一排点。
- 再套一层Mesh Line或直接用实例化,把这一排点沿Y轴复制N份。这里有个更省事的做法:直接用Grid节点,但把Vertices X和Vertices Y都设为N+1,然后用Mesh to Points,得到的点正好落在每个格子的顶点上。不过这个方案的点位坐标是整数,也就是说点的位置在格点而不是格子中心,需要通过坐标偏移把点挪到每个格子的中心。
- 我更推荐用两个Mesh Line配合Instance on Points来生成中心点阵,逻辑更直观。
点阵生成之后,用Instance on Points节点把Truchet Tile实例放到每个点上。紧接着的关键一步是随机旋转。接一个Random Value节点,DataType选Integer,Min设为0,Max设为1,Seed由一个Group Input暴露出来。这个0或1的随机整数,乘以90度,就是每块瓦片的旋转角。用Combine XYZ把旋转欧拉角组合好,输入到Instance on Points的Rotation端口。
这里还有一个细节:Instance on Points的旋转是绕着实例原点转的,所以瓦片组内部的原点必须落在瓦片中心。我在做Truchet Tile时,特意把Grid节点生成的平面中心设置在世界原点(也就是1×1平面中心在0,0,0),这样旋转时不会出现偏移错位。
2.3 收尾操作:Realize、整体挤出和倒角
实例铺好之后,节点图里你是能预览到完整图案的,但如果直接输出到材质或进行后续几何操作,会发现很多节点对实例不生效。原因很简单:实例(Instance)在Blender里是一种轻量引用,不是真正的网格数据,很多几何节点不认它。
所以需要加一个Realize Instances节点,把实例转换成真正的网格。这一步做完,瓦片才算“落地”。
为什么要强调这一点?因为我第一次搭的时候忘了加,结果挤出、倒角全都没反应,排查了半天才发现是实例化的问题。加完Realize之后,你可以继续做这些事情:
- 整体挤出:如果前面在单格瓦片里已经挤出过厚度,这里就不需要再挤出;但如果你选择在单格瓦片里只做平面三角面,全部厚度放在外层统一挤出,那就可以在这里接一个Extrude Mesh,把整个Truchet图案一次性挤出成实体。
- 倒角:用Bevel节点给所有硬边加倒角。Truchet图案的边缘如果太锐利,渲染时高光会显得很生硬,尤其是地砖场景。我一般给0.02到0.05米的倒角量,视觉上会柔和很多,当然这取决于你的场景尺寸。
- 合并重合点:如果后续要导出到其他软件,建议接一个Merge by Distance,把瓦片之间共享的顶点焊接起来,避免出现破面或重面。
到这里,一个基础的Truchet几何节点组就完成了。你只需要两个外部输入:Grid Size(格数)和Seed(随机种子),就能得到一整面随机拼花。
3. 从装饰平面到复杂变体
3.1 圆弧瓦片:把简单对角线换成四分之一圆
经典对角线瓦片做出来之后,很多人的下一个想法是:能不能让图案更柔和一点?这就触及到Truchet瓦片的一个重要变体——圆弧版。
圆弧版Truchet瓦片最早也来自Truchet的理论体系,图案不再是两个三角形,而是一个正方形里两个四分之一圆或曲线块。拼接起来后,图案会呈现连续流动的曲线感,而不是硬朗的斜线。要做这个变体,关键是把“单格瓦片”里的几何从三角形棱柱换成圆弧棱柱。
在Blender几何节点里做一个四分之一圆弧棱柱,我试过几种方案。最直接的是用Curve Primitive里的Arc节点,生成一段90度圆弧,再通过Curve to Mesh用一个矩形截面挤出成实体。但这样得到的弧形块边缘不好控制,和正方形边界贴合时容易有微小的接缝。更稳的办法是:仍然用Grid平面做底,然后用一个“圆弧数学”去判断点是否在圆弧区域内,再用Selection布尔运算切出弧形块。
具体来说:在1×1平面内,以某个角为圆心、半径为1画一个四分之一圆弧,落在圆弧内侧的点属于块A,外侧属于块B。用节点实现就是取平面上的坐标,计算到圆心的距离,用比较节点生成选择器,然后Split Edge或Delete Geometry把平面分成两部分,再分别挤出。圆弧版瓦片的拼接逻辑还是两个方向旋转0度或90度,但视觉上会比对角线版柔和很多,非常适合做地面水波纹、墙面软包纹样。
3.2 材质分配与随机配色
很多教程到挤出几何就结束了,但真正要让Truchet图案出效果,材质分配比几何本身更重要。我在项目里常用两种配合方式。
第一种是双色经典方案:两个三角形区域各给一种材质,颜色上形成强对比。这种情况下,你只需要在Truchet Tile节点组里直接给两个半块的Material Index分别设为0和1,外面用Set Material按索引给材质就行。这样操作的好处是,无论每块瓦片怎么旋转,两个半块的颜色始终能对得上,不会因为旋转而出现同一图块的颜色混乱。
第二种是随机配色方案:在双色Truchet的基础上,再按格子索引生成一个随机色相偏移,让每块瓦片的主色也产生变化。实现方式是在实例化时用Random Value基于Index生成一个Float,连到Set Material的ColorRamp或HSV节点上。我的经验是色相偏移不要超过0.15,否则整体图案会显得太花,失去Truchet那种“有序中的随机”的秩序感。
还有一种很出效果的做法,是把高度信息应用到材质上。例如三角形A挤出厚度比三角形B高,然后用一个Attribute节点读取Height,连接到粗糙度或自发光上。这样渲染出来的表面既有凹凸又有明暗变化,不需要额外做贴图。
3.3 轻量方案:在材质节点里做纯纹理版
如果你的需求只是给平面模型铺一张Truchet纹理,不需要真的挤出实体,那完全不用跑几何节点,直接在Shader Editor里用材质节点就能实现,性能还更好。
思路是这样的:
- 用UV坐标做输入,取Floor得到每个格子的整数索引,取Fract得到格子内的小数坐标。
- 用索引作为种子,生成一个随机整数0或1,决定这个格子旋转0度还是90度。
- 把小数坐标按旋转角度做旋转变换,得到局部坐标。
- 用局部坐标判断当前像素位于对角线哪一侧,输出黑色或白色。
用材质节点实现的Truchet纹理有个天然优势:它是无缝的,可以任意平铺,不需要担心网格边界。而且改一个Value节点的数值就能实时调整密度。缺点是没有几何厚度,做不了实体倒角或物理拼花效果。
我在实际项目里通常两条路线都做:近景或需要实体感时用几何节点版本,远景或大面积铺贴时用材质节点版本,依据相机距离做LOD切换。这算是比较实用的工程做法。
4. 实际应用场景拆解
4.1 拼花地砖:密度、厚度与缝隙
Truchet节点最容易上手也最出效果的应用就是拼花地砖。我做过一个室内项目,公共区域地面需要一种既有几何感又不呆板的拼花,最后就用了这个方案。
参数上,以3米×3米的一块地面为例:
- 单格瓦片尺寸1米,Grid Size设为3×3,这样正好铺满。
- 挤出厚度设为0.02米,预留地砖铺贴的胶层和找平层空间。
- 为了让接缝清晰,我给每个瓦片加了0.005米的缝隙。实现方式是:在单格瓦片组里把Tile Size设为0.99米而不是1米,这样瓦片之间天然留出0.01米的缝。
- Seed值我一般会随机多试几个,找一个花型分布比较均衡的,比如不要让大面积同色区域集中在某个角落。
地面铺完之后,接缝处的高光处理很关键。我建议在倒角之后,用Bevel节点生成的边缘数据连接一个ColorRamp,让缝隙处产生轻微的暗部,配合粗糙度贴图使用,真实感会提升不少。
4.2 镂空隔断:Truchet图案做遮罩挤空
Truchet图案不只可以做凸起的地砖,反过来做镂空效果也很有味道。把每个格子的一个半块保留为实体,另一个半块不做挤出甚至删除,得到的就是一片带随机斜向镂空的隔断板。
我在实际项目里是这样做的:在单格瓦片组里,只给三角形A做挤出,三角形B完全删除;外层布置一个完整的薄板作为底板,用Truchet图案作为遮罩做差集,形成一个既有结构强度又有装饰性的镂空面板。
这样做出来的隔断透光率由瓦片旋转的随机种子决定。理论上,每块瓦片有约一半面积保留,整体镂空率接近50%,但实际光线穿过时会因为图案的连续性形成有趣的光影斑驳效果。如果想要更高的透光率,可以把瓦片尺寸调大或把挤出截面的宽度收窄。
这个镂空隔断方案用3D打印也很适合,输出STL之前注意把法线统一朝外,厚度最好不低于0.4厘米,否则打印容易断裂。
4.3 大面积铺装与资产复用
对于几十米上百米的景观铺装或建筑幕墙,直接用高密度网格会非常吃性能。我的建议是分两个阶段处理:
- 概念阶段:用材质节点版本做快速预览,密度可以调得很高,实时拖动种子没问题。
- 出图或制造阶段:把高密度网格用实例化方式生成,作为独立文件处理,避免和其他模型混在同一个场景里。
几何节点组做好之后,一定要记得存为资产。Blender 4.x开始支持资产库目录,把Truchet Tile节点组存进去,之后任何项目都可以一键拖入。资产命名我习惯带上参数说明,例如“TruchetTile_1000x1000_H80”,方便团队里其他人调用时一眼看清尺寸。
5. 常见坑位与排查速查
5.1 接缝错位:常见原因与修复
Truchet图案最怕的就是接缝错位。如果你发现瓦片之间出现裂缝、重叠或者对角线没对齐,排查顺序应该是:
- 检查单格瓦片节点组的原点是否在中心。如果原点偏了,旋转后瓦片会围绕错误的位置转,接缝必错。
- 检查Grid Size和实例化点阵的间距是否一致。比如瓦片是1米,点阵间距就是1米。
- 检查Triangulate的Mode。如果你改成了Shortest Diagonal,某些四边形可能切成另一条对角线,导致相邻瓦片交界的三角形方向不匹配。
5.2 挤出无效:忘掉Realize的后果
这是新手最容易卡住的一步。Instance on Points生成的实例,你直接接Extrude Mesh或Bevel,会发现毫无反应。原因我前面说过,实例不是真实网格。解决办法就是在做任何几何修改之前,加Realize Instances。
但Realize之后也有个副作用:所有瓦片从实例变成独立网格,如果瓦片数量很多,合并后的网格顶点数会暴涨。这时建议先Merge by Distance,把相邻瓦片共用的顶点合并,能显著减少顶点数。
5.3 性能与随机性的平衡
网格密度超过30×30以后,Blender的实时预览会开始变卡。我实测过,40×40的实例化Truchet在普通笔记本上调整种子大约有半秒延迟,如果再做Realize加Bevel,延迟会明显拉长,严重影响调节手感。
我的做法是:预览阶段把Grid Size降到8×8或10×10,确认图案风格OK之后再调高密度输出。另外,Bevel的Segments不要给太多,2到3段就够,再高对视觉效果提升有限,但对性能影响很大。
5.4 随机分布太均匀或太乱
如果你觉得Truchet图案的随机感不够,比如某一区域出现了大面积的同色连续块,看上去像贴图瑕疵,不要急着改种子,可以换一种随机源。默认的Random Value是基于全局Seed的伪随机,分布比较均匀。如果你想制造局部聚集的效果,可以用White Noise纹理节点配合坐标生成随机值,或者叠加一层Voronoi噪声的索引去驱动旋转,这样能在局部区域形成有节奏的“团块”,视觉上更有设计感。
反过来,如果觉得太乱,可以把随机范围从0到1改成0到0.8,也就是让一部分瓦片不做旋转或旋转幅度减小,图案会呈现更多秩序感。
5.5 法线翻转导致黑面
这个问题在渲染阶段才会暴露。尤其是用网格顶点法线去驱动材质效果时,一旦法线方向不一致,着色会出现明显分界。排查方法很简单:进入Mesh Display面板打开Face Orientation,检查法线方向。如果发现有翻转的面,加一个Recalculate Normals节点,或者在挤出时把Extrude的Offset方向统一。
说到底,Truchet节点组的搭建并没有多高深,核心就是“一个瓦片+两种状态+随机旋转”,但把它做成一套可控、可复用的参数化资产之后,能玩出的花样确实不少。地砖、隔断、幕墙、浮雕、甚至动画里的过渡纹理,都能靠这一套节点组快速出方案。我自己在项目里最大的体会是:先把单格瓦片这个组件做到足够稳定可靠,后续所有扩展都轻松很多;反之如果基础瓦片有问题,后面越改越乱。建议你也从最基础的1×1对角线瓦片开始,跑通了再往圆弧、镂空、随机配色这些方向迭代。
