TiXL(t3) ShaderGraph:用节点图可视化构建 Field 场,从连线到光线步进渲染
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
TiXL 是一款开源的实时动态图形(Realtime Motion Graphics)制作软件,其 ShaderGraph(着色器图)功能是文档 ShaderGraph.md 的主题:不写一行着色器代码,而是把一个个小的 Field 算子像节点一样连线,就能搭建出带符号距离场(SDF)的形状、颜色场和向量场,最终交给 RaymarchField 或 Render2dField 渲染成图像。读完本文,你能理解 TiXL Field 场的四类节点构成、节点图到 HLSL 着色器的编译机制、RaymarchField 全部输入参数的默认值与物理含义,以及同一 Field 场驱动粒子力与点选择的复用路径。
什么是 ShaderGraph:把 Field 场当节点来搭
官方帮助文档 .help/references/topics/ui/ShaderGraph.md 对 ShaderGraph 的定义是:"一种可视化的方式,通过把小节点连线(而不是写着色器代码)来构建 Field 场——带符号距离的形状、颜色和向量"。
理解这个功能的前提是理解 TiXL 的 Field(场)概念。帮助文档 Field.md 将其解释为:一个对空间中任意点回答问题的函数——"离最近表面有多远?""这里的颜色是什么?""这里的流向指向哪?"。大多数 Field 返回带符号距离(SDF),用于光线步进出看起来立体的形状;但 Field 也可以返回颜色或方向向量,向量场可以和距离场一样参与乘法与空间变换。
文档强调的关键设计点是:一个 Field 的定义,多种用途。同一个 Field 除了渲染成图像,还可以:
- 驱动粒子受力(帮助文档提到 FieldDistanceForce、VectorFieldForce 等算子);
- 为网格着色(ColorVerticesWithField);
- 选择点集(如 SelectPointsWithSDFExample 所示的用 SDF 筛选点)。
在编辑器中,每个参与连线的节点就是一个 ShaderNode:它贡献 Field 的一块——一个球体或盒子形状、一次扭转或重复变换、一个颜色、或两个输入场的合并。选中节点后可以在参数窗口(Parameter Window)中像编辑其他算子一样修改其参数。文档特别指出:整条节点链会被编译成一个着色器,增加节点是让着色器"变深",而不是增加独立的渲染通道(render pass)——这一点对理解其性能模型至关重要。
四类节点与完整节点库
ShaderGraph 文档把 Field 算子归纳为四种类型:生成器(generators)创建形状、空间算子(space operators)弯曲或重复其周围的空间、调节算子(adjust operators)重塑数值、合并算子(combine operators)融合两个场。
对照源码,这些算子实际集中存放在 Operators/Lib/Symbols/field/ 目录下,每个算子都是.cs(C# 算子类定义槽位)+.t3(序列化的默认值与子图)+.t3ui(UI 布局)三元组。从目录结构看,实际节点库比文档的四类更丰富,此外还有render/、use/、analyze/三个子目录:
生成器(generate):创建基础形状
位于 Operators/Lib/Symbols/field/generate/,分三个子族:
- SDF 生成器(generate/sdf/):
SphereSDF、BoxSDF、BoxFrameSDF、CylinderSDF、TorusSDF、CappedTorusSDF、CapsuleLineSDF、PlaneSDF、RotatedPlaneSDF、PyramidSDF、PrismSDF、OctahedronSDF、ChainLinkSDF、FractalSDF,以及HeightMapSdf、Image2dSDF(从高度图/2D 图像构建 SDF)和CustomSDF(自定义); - 纹理型场(
generate/texture/):Raster3dField、SubDivPattern3d; - 向量场(
generate/vec3/):ToroidalVortexField(环形涡流向量场)。
空间算子(space):变换场所在的坐标空间
位于 Operators/Lib/Symbols/field/space/,共 12 个节点:Translate(平移)、RotateField/RotateAxis(旋转)、BendField(弯曲)、TwistField(扭转)、ReflectField(反射)、TransformField(整体变换)、RepeatAxis/RepeatField3/RepeatFieldAtPoints/RepeatFieldLimit/RepeatPolar(各种方式的重复平铺)。这类算子不改变场本身,而是"弯曲或重复其周围的空间",是做出重复阵列、极坐标图案等效果的常用手段,示例见 TwistFieldExample。
调节算子(adjust):重塑场的数值
位于 Operators/Lib/Symbols/field/adjust/:AbsoluteSDF(取绝对值)、InvertSDF(反转符号,内外翻转)、NoiseDisplaceSDF(噪声扰动)、PushPullSDF(推拉表面)、SpatialDisplaceSDF(空间置换,示例 SpatialDisplaceSDFExample)、SetSDFMaterial(设置材质参数)、TranslateUV(平移 UV)。
合并算子(combine):融合两个或多个场
位于 Operators/Lib/Symbols/field/combine/:CombineSDF(SDF 合并,示例 CombineSDFExample)、BlendSDFWithSDF(带过渡宽度的混合)、StairCombineSDF(阶梯式合并)、CombineFieldColor(颜色场混合)。
渲染、消费与调试(render / use / analyze)
- render/:
RaymarchField(光线步进渲染)、Render2dField(2D 渲染)、SampleFieldPoints(对点采样场),以及底层的 GenerateShaderGraphCode; - use/:把场用于非渲染用途,如
ApplyVectorField(向量场推动对象)、RaymarchPoints、SdfToVector、SDFToColor、SdfReflectionLinePoints; - analyze/:
VisualizeFieldDistance,把场的距离值直接可视化,用于调试场是否正确。
编辑器侧的节点浏览分类与目录一一对应:在 SymbolBrowsing.cs 中,节点浏览器按adjust、analyze、combine、generate.sdf、generate.texture、generate.vec3、render、space、use九个分组展示所有ShaderGraphNode类型节点;着色器图在界面上使用专门的品紫色标识 UiColors.cs 中的ColorForShaderGraph (0.82, 0.26, 0.7),并通过 UiRegistration.cs 将ShaderGraphNode类型注册到对应的属性 UI。
节点图如何编译成一个着色器
"整条链编译成一个着色器"这句话在源码里的落点,是 ShaderGraphNode 与 GenerateShaderGraphCode 两个类型。
ShaderGraphNode 是节点图的运行时表示。它维护一个变更标志CollectedChanges(ChangedFlags 枚举),区分三种变更:结构变更(增删节点,Structural)、代码变更(节点内嵌着色器代码修改,Code)、参数变更(Parameters)。图遍历入口 CollectAllNodeParams 会沿输入递归遍历所有节点(inputNode?.CollectAllNodeParams(...)),把每个节点的浮点参数收集进floatValues列表、把需要嵌入着色器的代码参数收集进codeParams列表——这意味着整张图的所有参数最终打进一个统一的参数缓冲,着色器只需读取一个结构。
GenerateShaderGraphCode 是执行"图 → 代码"转换的算子,它对外的槽位是:
ShaderCode(输出,字符串):生成的完整着色器源码;FloatParams(输出,Buffer):收集到的全部浮点参数;Resources(输出,Object):附加着色器资源。
其更新逻辑(L99-L131 一带)体现了增量编译思想:若节点图没有Code/Structural变更且模板文件未变化,则跳过重新生成;否则调用_graphNode.CollectEmbeddedShaderCode(...)收集各节点内嵌的 HLSL 代码并注入模板,再拼接_additionalDefines生成最终代码。参数声明通过CollectAllNodeParams的结果逐行生成({ShaderTypeName} {Name};形式,见 GenerateShaderCode)。
所有节点共享的 HLSL 基础设施定义在 ShaderGraphIncludes 中,从源码结构看它内嵌了三段公共代码:
Common:基础常量与宏,PI、TAU、PHI以及mod(x, y);CommonHgSdf:源自 Mercury SEO 的 HG_SDF 库的辅助函数,如sgn、square、pR(绕轴旋转)、pR45(45 度旋转快捷)、pMod1(沿轴重复空间)——SDF 生成器节点大量复用这些原语;GetColorBlendFactor:两距离值在过渡宽度k内的颜色混合因子,服务于BlendSDFWithSDF这类带平滑过渡的合并。
配套的上下文类型还有 CodeAssembleContext 与 ShaderParamHandling,负责代码组装与参数处理。
RaymarchField:把 SDF 场光线步进成图像
文档说,图的末端放一个 RaymarchField 或 Render2dField 就能把组装好的场变成图像。RaymarchField 是其中参数最多的算子,其输入槽在 RaymarchField.cs 中定义,输出为DrawCommand(Command,实际绘制指令)和ShaderCode(string,可复用/检视生成代码)。
SdfField输入的类型是ShaderGraphNode——这正是你连线进去的那张节点图。其余参数的默认值定义在序列化文件 RaymarchField.t3 中:
| 输入 | 类型 | 默认值 | 说明 |
|---|---|---|---|
SdfField | ShaderGraphNode | null(必接) | 待渲染的场节点图 |
Color | Vector4 | (1, 1, 1, 1) | 基础颜色(白色) |
AmbientOcclusion | Vector4 | (1e-6, 1e-6, 1e-6, 1) | AO 颜色,默认近乎纯黑 |
AoDistance | float | 1.0 | 环境光遮蔽采样距离 |
TextureScale | float | 1.0 | 纹理采样缩放 |
UVMapping | int(枚举) | 1 | UV 映射模式,见下 |
NormalSamplingD | float | 0.002 | 法线差分采样偏移,过小易噪声、过大失细节 |
MaxSteps | float | 100.0 | 光线步进最大迭代次数 |
MinDistance | float | 0.002 | 终止判定的最小距离 |
MaxDistance | float | 300.0 | 射线最大行进距离 |
StepSize | float | 1.0 | 步进缩放 |
DistToColor | float | 0.15 | 距离到颜色的过渡宽度,决定表面到背景的边缘抗锯齿强度 |
WriteDepth | bool | true | 是否写深度缓冲 |
SpecularAA | float | 0.5 | 高光抗锯齿强度 |
UVMapping的实际取值由 RaymarchField.cs 中的MappingModes枚举定义:Global_Triplanar(0)、Local_Triplanar(1,默认)、Local_XY、Local_YZ、Local_XZ,即三平面纹理映射(全局/局部)与三个正交平面投影。
从 RaymarchField.t3 的子图连接可以看到它的完整渲染管线:
ReadFile读取像素着色器模板Lib:shaders/img/generate/RaymarchSDFFieldWithMatTemplate.hlsl(带 PBR 材质的步进模板);GenerateShaderGraphCode节点(模板路径同上)把SdfField输入的整张节点图编译注入模板,产出ShaderCode、FloatParams与着色器资源;VertexShader使用RaymarchSDFFieldTemplate.hlsl(入口vsMain4)生成全屏四边形顶点(6 个顶点的三角形带);SetPixelAndVertexShaderStage把顶点/像素着色器、PBR 参数、Srv、上下文缓冲(变换矩阵等)组装为渲染阶段;Draw(VertexCount=6)→Execute产出DrawCommand;- 混合状态
BlendOnWhites/BlendState、深度状态DepthStencilState(受WriteDepth控制)决定合成方式; UVMapping通过PickStringPart从一段#define MAPPING_*字符串中挑出对应宏,传给着色器代码生成,切换 UV 映射方式;- 所有浮点参数经
FloatsToBuffer打包后进入像素着色器缓冲。
这套结构也印证了 ShaderGraph 的性能模型:每多接一层场节点,步进循环里每像素要多执行一次距离求值,而不是多一次 draw call。
性能与走样提示(文档的实操建议)
ShaderGraph 文档最后一句是明确的操作提醒:"留意输出中的性能与走样提示——嵌套多个场做光线步进会很快变贵,尽量简化图"。结合参数表,对应的调优抓手是:
- 性能:
MaxSteps(默认 100)与MaxDistance(默认 300)直接决定每像素最坏情况下的距离求值次数;StepSize放大步长可以减少迭代,代价是薄特征可能跳过;节点链越长(嵌套越深),单次距离求值的开销线性叠加; - 走样:
DistToColor控制表面边缘过渡,值偏小会出现锯齿;NormalSamplingD控制法线估计的差分距离,过小在高曲率处闪烁;SpecularAA控制高光抖动。这些正是"输出中的走样提示"所指向的旋钮; - 简化策略:能用
Render2dField出平面图案就不要上光线步进;能合并的场用CombineSDF/BlendSDFWithSDF提前融合,减少末端嵌套深度;调试时先用VisualizeFieldDistance确认场本身正确,再谈渲染参数。
Render2dField 与场的非渲染复用
Render2dField 是同目录下的另一条渲染出口,面向 2D 上下文渲染场(而非三维步进),与RaymarchField一样以ShaderGraphNode图作为输入,文档将其并列为"把组装好的场变成图像"的末端算子。
ShaderGraph 文档还强调,同一张场图不止能渲染:它可以驱动粒子受力或选择点。仓库中的示例符号展示了这些复用的实际形态:
- ApplyVectorFieldExample:把
generate.vec3的向量场应用到对象; - RaymarchPointsExample 与 SdfReflectionLinePointsExample:把 SDF 场用于点集(采样、反射线);
- MoveToSDFExample、SelectPointsWithSDFExample:用场修改/筛选点;
- Image2dSDFExample:从 2D 图像生成 SDF 再参与图形搭建的完整链路。
小结与延伸阅读
ShaderGraph 是 TiXL 把"程序化场"从写 HLSL 降维成连节点的操作层:四类节点(生成/空间/调节/合并)覆盖场的构造,ShaderGraphNode+GenerateShaderGraphCode负责把整图增量编译为单个着色器,RaymarchField/Render2dField提供渲染出口,use/算子则让同一份场定义复用于粒子与点集。关键源码入口:
- 算子库目录:Operators/Lib/Symbols/field/
- 节点图运行时:Core/DataTypes/ShaderGraphNode.cs
- 图到代码的编译:Operators/Lib/Symbols/field/render/_/GenerateShaderGraphCode.cs
- 公共 HLSL 注入:Core/DataTypes/ShaderGraph/ShaderGraphIncludes.cs
- 帮助文档:ShaderGraph、Field、ShaderNode
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考