TiXL SDF 布尔运算进阶:StairCombineSDF 算子的楼梯与立柱合并技法
TiXL SDF 布尔运算进阶StairCombineSDF 算子的楼梯与立柱合并技法【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3StairCombineSDF 是 TiXLtooll3开源实时动态图形工具中Lib.field.combine系列的核心算子之一专门用于把两个或多个 SDF符号距离场的交界处改造成**台阶、立柱、木工槽口Groove与榫头Tongue**等结构化起伏效果。读完本文你将掌握该算子的全部 9 种合并方法、K与Steps两个关键参数的调参逻辑并能理解它如何通过IGraphNodeOp接口在 CodeAssembleContext.cs 中动态拼接 HLSL 距离函数——从而在自己的 Shader Graph 场系统中实现布尔运算 工业感细节的实时造型。一、算子定位Lib.field.combine 家族的一员在 TiXL 的场Field系统中Lib.field.combine目录下的算子负责将多个已生成的 SDF 字段以不同方式合并。根据 combine 目录文档该家族包含四个成员算子文档描述BlendSDFWithSDF混合两个 SDFCombineFieldColor合并场颜色CombineSDF用指定混合方法合并两个及以上连接的场StairCombineSDF一组可将相交处变成台阶或凸起的 SDF 合并操作StairCombineSDF 的定位与普通布尔合并min/max不同它不再追求平滑的接缝而是刻意在相交区域生成离散化、阶梯化的结构细节非常适合齿轮、机械、电路板、折纸、几何装饰等风格的实时渲染。算子的官方描述定义在其 UI 元数据文件 StairCombineSDF.t3ui 中A set of sdf combine operations that will turn intersections into stairs or bumps.其算子实现位于 StairCombineSDF.cs对应实例配置文件为 StairCombineSDF.t3。二、输入输出参数全解原文档给出了该算子的完整接口签名下表在此基础上补充了源码中确认的默认值与类型细节默认值来自 StairCombineSDF.t3输入参数名称类型相关度默认值说明InputFieldsShaderGraphNode多输入Required 必需null待合并的场节点可连接多个少于 2 个输入时算子直接跳过合并见下文代码生成链路KSingle—0.5合并的半径/影响范围控制台阶、立柱、槽口的整体尺寸StepsSingle—3.0台阶或立柱的数量 n决定离散化密度CombineMethodInt32—3即UnionStairs合并方法选择共 9 种见第三节枚举表输出参数名称类型ResultT3.Core.DataTypes.ShaderGraphNode从 StairCombineSDF.cs 可以看到输出Result是一个SlotShaderGraphNode构造时即被初始化为该算子自身的ShaderNode[Output(Guid cb491f9b-837f-4e73-9ab8-8ce1e8abb46d)] public readonly SlotShaderGraphNode Result new(); public StairCombineSDF() { ShaderNode new ShaderGraphNode(this, InputFields); Result.UpdateAction Update; Result.Value ShaderNode; }InputFields在源码中声明为MultiInputSlotShaderGraphNodeStairCombineSDF.cs因此可以同时接入任意多个场节点合并按连接顺序依次进行。三、9 种合并方法枚举与 HLSL 实现CombineMethod输入在 C# 中是一个int槽运行时通过CombineMethod.GetEnumValueCombineMethods(context)映射为私有枚举StairCombineSDF.csprivate enum CombineMethods { UnionColumns, // 0 DifferenceColumns, // 1 IntersectionColumns, // 2 UnionStairs, // 3 ← 默认值 IntersectionStairs, // 4 DifferenceStairs, // 5 Groove, // 6 Tongue, // 7 }枚举按声明顺序映射因此默认值3对应UnionStairs。下面逐一解析每种方法的 HLSL 实现全部内嵌在 StairCombineSDF.cs 的AddDefinitions中。1. UnionColumns并集立柱在 45 度对角线上放置 n-1 个圆柱形立柱来连接两个物体。代码注释明确指出The Columns flavour makes n-1 circular columns at a 45 degree anglefloat fOpUnionColumns(float a, float b, float r, float n) { if ((a r) (b r)) { float2 p float2(a, b); float columnradius r*sqrt(2)/((n-1)*2sqrt(2)); pR45(p); p.x - sqrt(2)/2*r; p.x columnradius*sqrt(2); if (mod(n,2) 1) { p.y columnradius; } // At this point, we have turned 45 degrees and moved at a point on the // diagonal that we want to place the columns on. // Now, repeat the domain along this direction and place a circle. pMod1(p.y, columnradius*2); float result length(p) - columnradius; result min(result, p.x); result min(result, a); return min(result, b); } else { return min(a, b); } }其思路是仅当两个场距离都小于r进入相交区时把 2D 距离坐标旋转 45 度pR45沿对角线方向用pMod1做域重复domain repetition从而生成一系列等距排列的圆柱非相交区域退化为普通min(a, b)。n越大立柱越细越多columnradius随之变小。2. DifferenceColumns差集立柱与 3. IntersectionColumns交集立柱两者共用一个代码块。DifferenceColumns先对a取反a -a再做类似计算最终返回-min(result, b)而IntersectionColumns直接复用差集实现float fOpIntersectionColumns(float a, float b, float r, float n) { return fOpDifferenceColumns(a,-b,r, n); }这与 SDF 布尔运算的经典等价关系一致intersection(a,b) difference(a,-b)。源码注释还指出快速路径会产生不连续discontinuityavoid the expensive computation where not needed (produces discontinuity though)4. UnionStairs并集台阶默认方法采用 paniq 的聪明得多的版本源码注释原话much less stupid version by paniqfloat fOpUnionStairs(float a, float b, float r, float n) { float s r/n; float u b-r; return min(min(a,b), 0.5 * (u a abs ((mod (u - a s, 2 * s)) - s))); }台阶高度为s r/n通过模运算把两个场的差折叠成锯齿波形从而在r范围内生成 n 级台阶。这是一个极其紧凑的三角波 min公式。5. IntersectionStairs 与 6. DifferenceStairs与立柱家族类似台阶家族也通过取反复用float fOpIntersectionStairs(float a, float b, float r, float n) { return -fOpUnionStairs(-a, -b, r, n); } float fOpDifferenceStairs(float a, float b, float r, float n) { return -fOpUnionStairs(-a, b, r, n); }7. Groove槽口给第一个物体在交界处切出一道木工风格的凹槽float fOpGroove(float a, float b, float ra, float rb) { return max(a, min(a ra, rb - abs(b))); }8. Tongue榫头与 Groove 互补给第一个物体在交界处长出一个凸榫float fOpTongue(float a, float b, float ra, float rb) { return min(a, max(a - ra, abs(b) - rb)); }注意Groove 与 Tongue 的 HLSL 签名中第二个半径参数名为rb但算子调用时传入的是K和Steps{n}K, {n}Steps即Steps在槽口/榫头模式下扮演第二个尺寸参数的角色——这与其他方法中台阶数的语义不同调参时需要留意。方法速查表CombineMethod 值方法HLSL 函数效果0UnionColumnsfOpUnionColumns并集45° 斜向立柱连接1DifferenceColumnsfOpDifferenceColumns差集立柱镂空2IntersectionColumnsfOpIntersectionColumns交集保留立柱骨架3默认UnionStairsfOpUnionStairs并集n 级台阶4IntersectionStairsfOpIntersectionStairs交集台阶5DifferenceStairsfOpDifferenceStairs差集台阶6GroovefOpGroove第一物体切出槽口7TonguefOpTongue第一物体长出榫头这些算法来源于开源 SDF 库 hg_sdfMercury该算子的 StairCombineSDF.t3ui 的 Links 元数据中明确标注了引用来源合并相关的辅助函数pR45、pMod1、mod、sgn定义在 ShaderGraphIncludes.cs 的CommonHgSdf常量中。四、核心原理算子如何变成一段 HLSL 距离函数StairCombineSDF 之所以能无代码地在图编辑器中工作是因为它实现了IGraphNodeOp接口IGraphNodeOp.cs。该接口定义了 Shader Graph 节点参与代码生成的四个钩子方法AddDefinitions注册全局函数、TryBuildCustomCode、GetPreShaderCode、GetPostShaderCode。1. AddDefinitions把 C# 字符串注入 HLSL 全局区IGraphNodeOp.AddDefinitions在遍历连接场之前被调用一次用于把纯函数注册进CodeAssembleContext.Globals字典CodeAssembleContext.csvoid IGraphNodeOp.AddDefinitions(CodeAssembleContext c) { c.Globals[Common] ShaderGraphIncludes.Common; c.Globals[CommonHgSdf] ShaderGraphIncludes.CommonHgSdf; switch (_combineMethod) { case CombineMethods.UnionColumns: c.Globals[fOpUnionColumns] ...; ... } }StairCombineSDF 固定引入CommonPI/TAU/mod宏定义与CommonHgSdfpR45、pMod1等随后按当前CombineMethod只注册对应的那个函数——因此切换方法会触发代码重生成。2. 方法切换与脏标记在Update方法中算子会读取CombineMethod枚举值一旦与上次不同就调用ShaderNode.FlagCodeChanged()强制重建着色器StairCombineSDF.cs。这是 TiXL 运行时参数变更 → 代码热更新机制的体现ShaderGraphNode.Update()会统计结构、代码、参数三类变更标记见 ShaderGraphNode.cs供上层决定是否重新编译 HLSL。3. GetPostShaderCode按输入顺序逐层合并真正写入距离函数主体的是GetPostShaderCodeStairCombineSDF.cs它在每个输入字段求值后回调输入不足InputNodes.Count 1时只追加一行注释// skipping combine with single or no input...直接透传第一个输入inputIndex 0f{pc} f{c};保留初始场值后续输入按当前方法调用对应的fOp*函数合并到父上下文c.AppendCall($f{pc}.w fOpUnionStairs(f{pc}.w, f{c}.w, {n}K, {n}Steps);); ... c.AppendCall($f{pc}.xyz f{pc}.w f{c}.w ? f{pc}.xyz : f{c}.xyz;);这里f.w保存距离值f.xyz保存颜色最后一行确保颜色取自距离更小更靠近表面的那个场与min合并的距离语义保持一致。上下文编号取自ContextIdStackCodeAssembleContext.csPushContext会为每个子场生成独立的p{sub}、f{sub}局部变量从而支持任意深度的嵌套连接。五、实战调参指南K默认 0.5语义合并影响半径r即台阶/立柱生成的过渡带宽度影响UnionStairs中台阶总高rr越大过渡越宽、台阶越明显UnionColumns中它同时决定立柱粗细columnradius与r成正比和存在范围仅当ar br时生成立柱建议先固定Steps从小到大扫描K观察交界处细节的扩张速度。Steps默认 3.0语义台阶级数 / 立柱个数 n影响UnionStairs中每级台阶高r/nn 越大台阶越密越细腻UnionColumns中生成 n-1 个立柱n 越大柱体越多越细在 Groove/Tongue 模式下它作为第二半径rb使用建议Steps取 26 通常视觉最清晰过大时台阶会趋近于普通布尔运算过小则只剩 1 级或退化为倒角。CombineMethod默认 3 UnionStairs想要齿轮感立面 →UnionStairs/IntersectionStairs想要铆钉/管柱连接 →UnionColumns想要榫卯结构拼装感 →GrooveTongue组合使用一个物体切槽、另一个出榫可形成互锁效果注意切换方法会改变着色器结构同一参数下不同方法的效果差异极大建议在参数面板上快速轮播预览。与其他算子协同与同目录的 CombineSDF 对比CombineSDF提供平滑/圆角/倒角/管道/雕刻等 13 种光滑过渡合并而StairCombineSDF专攻硬朗的离散结构两者可按需在一条链上串联使用输入字段通常来自field目录下的 Shape SDF 算子Box、Sphere、RoundBox 等多路输入按顺序累积合并顺序会影响差集/交集的结果方向InputFields的 UI 相关度标记为Required见 StairCombineSDF.t3ui未连接任何场时节点输出为空。六、注意事项与已知限制仅单输入不合并连接数 ≤ 1 时GetPostShaderCode直接跳过不会报错但也没有任何合并效果立柱快速路径不连续源码注释明确提示fOpDifferenceColumns的快速分支会引入距离场不连续在需要严格 Lipschitz 连续的场合如后续再做平滑偏移、法线计算需谨慎使用Steps 语义随方法变化Groove/Tongue 中Steps不再是数量而是尺寸跨方法复用时需重新审视参数颜色取近原则合并后颜色取自距离更小的一方f{pc}.w f{c}.w ? f{pc}.xyz : f{c}.xyz若希望两场颜色混合应改用带GetColorBlendFactor的CombineSDF之类的混合算子代码按需注册只有当前选中的方法会被注入 HLSL未使用的方法函数不会进入最终着色器编译负担很小。七、参考与延伸阅读算子文档StairCombineSDF.md、combine 目录 README算子实现StairCombineSDF.cs、实例配置 StairCombineSDF.t3、UI 配置 StairCombineSDF.t3ui框架机制IGraphNodeOp.cs、CodeAssembleContext.cs、ShaderGraphIncludes.cs、ShaderGraphNode.cs同类算子CombineSDF.cs【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考