TiXL 图构建实战指南:子图封装、上下文变量与流程控制
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
本文是 TiXL(Tooll 3)中关于构建 Operator 图的实战技术指南,围绕官方 FAQ 文档 FaqBuildingContent.md 展开,系统讲解子图(subpatch)的拆分时机、基于 Evaluation Context 的全局变量机制,以及时间条件、分支切换等流程控制的四种实现方案。读完本文,你将掌握如何在实时图形项目中把重复的 3D 场景、特效、排版与数学逻辑封装为可复用算子,并学会用粒子年龄驱动缩放等典型技巧。
何时创建子图(Sub-Graph)
“是否应该把一段图封装成子图”本质上属于个人偏好问题,但以下信号可以作为判断依据:
- 重复出现超过 2 次:当你发现图的某一部分被重复放置多次(两次以上)时,这通常是最强烈的抽象信号。常见的可泛化对象包括:
- 场景:例如一个反复出现的 3D 元素;
- 特效:例如一组组合使用的点修改器(point modifiers);
- 排版元素:例如开场标题中反复显示的名字;
- 数学逻辑:例如计算某个元素尺寸的公共表达式。
- 单个嵌套算子太小:一个仅含 1 个算子的“子图”大概率过小了。大多数算子的内部规模在2 到 30 个算子之间。
- 主输出即类型:绝大多数算子只有一个主输出,其输出类型直接决定了该算子在画布上的颜色;只有极少数算子带有额外输出(例如第二张贴图纹理)。
- 参数化成本极低:为封装后的子图添加参数(例如前面“标题”案例中的 Names 参数)非常快,你可以随时修改、重排或重命名这些参数,这进一步降低了抽象的门槛。
变量(Variables)机制
变量如何工作
在 TiXL 中,变量是Evaluation Context(求值上下文)的组成部分。从源码看,上下文内部按类型用字典存储变量,见 EvaluationContext.cs:
Dictionary<string, bool> BoolVariablesDictionary<string, int> IntVariablesDictionary<string, float> FloatVariablesDictionary<string, object> ObjectVariables(用于浮点、整数之外的对象)Dictionary<string, string> StringVariables
每次求值周期开始(Reset()),这些字典都会被清空重建,见 EvaluationContext.cs,因此变量是“每帧有效”的临时通信手段,而不是跨帧持久化存储。
赋值与读取:SetFloatVar / GetFloatVar
由于变量随求值上下文传播,你需要在图中尽早赋值——即靠近最终输出的“右侧”,这样位于图“左侧”(下游)的子图才能读到它。实际操作符位于flow/context目录,对应源码文件为:
- SetFloatVar.cs:写入浮点变量,输入包括
VariableName、FloatValue、可选的SubGraph(Command 输入)以及ClearAfterExecution。其实现逻辑是:若SubGraph有连接,则先写入新值、执行子图,执行完毕后再恢复此前保存的旧值(这正是“子图中覆盖变量后自动恢复”的来源);若子图未连接,则直接写入context.FloatVariables[name]。 - SetBoolVar.cs、SetIntVar.cs:分别对应布尔与整数变量。
- GetFloatVar.cs:读取浮点变量。读取器还实现了
ICustomDropdownHolder,在编辑器里会基于当前上下文中已存在的变量名生成下拉候选列表;同时提供FallbackDefault输入,作为变量不存在时的回退值,避免“取不到值”导致参数归零。
典型应用场景如文档所述:定义一批全局变量,让各个子图根据 MIDI 输入等信息选择不同的变体(variant)——用SetFloat/SetBool等提前写入,下游子图用GetFloatVar/GetBoolVar读取即可。
子图中的覆盖与恢复
文档强调“变量可以在子图中被覆盖(先前的值会被恢复)”。这一点在 SetFloatVar.cs 的实现中得到印证:当SubGraph有输入连接时,代码用TryGetValue保存previous,子图求值完成后,若存在旧值则恢复旧值,否则根据ClearAfterExecution决定是否移除该变量。这保证了变量赋值具有词法作用域的语义——内层子图临时改值不会污染外层图。
流程控制:条件逻辑的四种方案
文档以if(time >= 16.0 && time < 18.0) { ... }这类演出编排需求为例,给出了四种实现思路,按推荐程度排序:
方案一:TimeClips(最推荐)
TimeClips是最方便的条件控制方式,尤其是当你正确设置 BPM 并启用时间线的bar-raster(小节栅格)模式后,可以享受精确的吸附、剪切等时间线编辑能力。核心算子 TimeClip.cs 的求值逻辑为:
- 根据当前时间
LocalFxTime与 clip 的TimeRange计算归一化时间,并写入上下文变量_normalizedTime(供 clip 内部内容读取,实现区域映射); - 依次对连接的 Command 执行
PrepareAction、GetValue、RestoreAction,即只在 clip 时间窗口内激活其内容。
底层的时间映射由 Core/Animation/TimeClip.cs 提供:MapTimelineToSource/MapSourceToTimeline实现时间线与源时间区间的仿射映射,Speed与GetPlaybackSpeed处理变速播放,SourceUnit则区分源区间以 Bars 还是 Seconds 计时(音乐类内容用 Bars、音视频等墙钟媒体用 Seconds)。所以 TimeClips 不仅能做“开/关”,还能做时间重映射与变速。
方案二:Compare + Execute/Group 的 Enabled 参数
用[Compare]产生布尔结果,配合布尔逻辑去驱动[Execute]或[Group]的Enabled参数。当条件为假时,对应分支整体不被求值,效果等同于停用。
方案三:动画 [Switch] 的索引
[Switch]算子(见 Switch.cs)通过Index输入选择求值哪个分支,其行为有明确的边界值语义:
- 索引指向已连接图的序号:只求值该分支,其余分支不会被求值,这与“停用其他分支”等价;
-1:全部禁用(源码中index == -1时直接返回,不执行任何命令);-2:全部启用(源码中遍历所有 command 依次执行并统一做恢复)。
从源码看,Index为其它值时会取模(index %= commands.Count)以支持循环切换,并提供Count输出(已连接命令数)与OptimizeInvalidation(仅失效被选中索引,提升多分支下的求值性能)。
方案四:禁用算子(不推荐用于演出)
直接禁用算子(连同其完整子图)虽然简单,但无法被动画化或通过参数控制,因此不适合需要随时间切换的演出场景。
实战:用粒子年龄驱动缩放
文档给出了一个经典案例:把粒子年龄(age,从 0 增长到 1)直接作为缩放因子时,粒子会在“出生时尺寸为 0、死亡时尺寸最大”,这通常与预期相反。期望的行为往往是:粒子从 0 快速膨胀到最大尺寸,随后再淡出回 0。
推荐链路为:
[ParticleSystem] → [MapPointAttributes](Input Mode 设为 F1)MapPointAttributes.cs 的输入模式枚举(InputModes)包括BufferOrder、F1、F2与Random,把F1(粒子的第一个浮点属性通道,典型即年龄)作为驱动源。真正实现“快速膨胀再淡出”需要组合其映射与写入模式:
- Mapping(映射模式):
Centered(以 0.5 为中心)、ForStart、PingPong、Repeat、UseOriginalW。其中PingPong可以让 0→1 的输入折返为 0→1→0,天然形成“先增后减”的形状; - WriteTo(写入目标):可写回
F1、F2或Scale——要实现尺寸变化,应写入Scale; - WriteMode(写入方式):
Replace(替换)、Multiply(相乘)、Add(叠加),用于与粒子已有的缩放值组合; - MappingCurve:接受一个
Curve输入,可以自定义非对称的缩放包络(例如快速上升、缓慢衰减的 ADSR 式曲线),这是实现“很快膨胀到最大、再淡出到 0”最灵活的手段; - 其余输入如
Range、Phase、Strength、StrengthFactor、Gradient、ValueTexture可用于进一步调整映射范围、相位偏移与颜色输出。
粒子数据本体由 ParticleSystem.cs 承载,包含ParticleBuffer、SpeedFactor、IsReset、InitializeVelocityFactor等字段,MapPointAttributes 读取其缓冲并逐粒子改写属性,输出新的BufferWithViews供渲染使用。文档中所举的[ParticleSystem] → [MapPointAttributes]即是在粒子缓冲上做属性重映射的标准管线。
小结
构建高质量 TiXL 图的核心方法论可以浓缩为三点:用子图消化重复(2~30 个算子的封装粒度)、用上下文变量做跨子图通信(在靠近输出的右侧赋值,子图内覆盖自动恢复)、用 TimeClips / Compare / Switch 做时间与分支控制(牢记 Switch 的-1全关、-2全开语义)。在此基础上,粒子等数据对象的属性重映射(如年龄驱动缩放)只是 MapPointAttributes 这类算子对缓冲属性的常规操作,组合好 Mapping、WriteTo 与 WriteMode 即可得到丰富的动态效果。
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考