TiXL AnimVec2 算子完全指南:用双通道 BPM 同步 LFO 驱动 2D 动画向量
2026/9/21 19:08:37 网站建设 项目流程

TiXL AnimVec2 算子完全指南:用双通道 BPM 同步 LFO 驱动 2D 动画向量

【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3

AnimVec2 是 TiXL 开源实时动态图形软件中位于Lib.numbers.anim.animators家族的动画算子,它生成与当前 BPM 速率同步的重复 LFO 类信号,并同时输出两个相互独立的波形通道(Vector2),非常适合驱动二维位置、缩放、UV 偏移等需要"两路同源但可独立调节"的动画参数。本文将以仓库内该算子的官方文档为骨架,结合其 C# 实现、默认配置、图形化交互 UI 与配套的 SetSpeedFactors 机制,完整讲解 AnimVec2 的输入参数、输出语义、底层数学原理与现场 VJ 使用技巧。

AnimVec2 是什么:双通道 BPM 同步 LFO

官方文档对 AnimVec2 的定义是:Generates a repetitive LFO-like signal synced to the current BPM rate. It supports various shapes, modes, and forms.(生成与当前 BPM 速率同步的重复 LFO 类信号,支持多种形状、模式与形式)。

从实现看,它本质上是把单个 LFO(即同家族的 AnimValue)扩展为两个分量:源码 AnimVec2.cs 中,两个通道共用一套输入参数(速率、相位、振幅、偏移),但各自拥有独立的 Vector2 分量值,最终合并输出为System.Numerics.Vector2。因此你可以在一个算子节点内同时获得"X 轴快、Y 轴慢"或"X 正弦、Y 锯齿"这样的混合动画,而不需要并联两个 AnimValue。

输出:Result(Vector2)

AnimVec2 只有一个输出:

名称类型
ResultSystem.Numerics.Vector2

该输出在源码中标记为DirtyFlagTrigger.Animated(见 AnimVec2.cs),意味着 TiXL 的求值系统会将其视为"动画信号":只要时间在推进,输出就会被标记为需要重算,从而持续刷新下游节点。这一点与静态参数(如固定颜色、常量)形成关键区别——接入 AnimVec2 的下游算子每帧都会收到新值。

核心数学原理:信号如何被计算

AnimVec2 的每一帧更新逻辑集中在Update方法中(AnimVec2.cs),理解它等于理解了整个算子的行为:

_normalizedTimeX = (time + phases.X) * masterRate * rateFactorFromContext * rates.X _normalizedTimeY = (time + phases.Y) * masterRate * rateFactorFromContext * rates.Y

其中time优先取OverrideTime的连接值,未连接时使用context.LocalFxTime(本地效果时间);masterRate来自RateFactorrateFactorFromContext来自 AnimMath.GetSpeedOverrideFromContext,由AllowSpeedFactor决定;rates.X/Y来自Rates输入的对应分量。

随后两个通道分别计算最终值:

Result.X = CalcValueForNormalizedTime(shape, _normalizedTimeX, 0, bias, ratio) * amplitudes.X + offsets.X Result.Y = CalcValueForNormalizedTime(shape, _normalizedTimeY, 1, bias, ratio) * amplitudes.Y + offsets.Y

即每个通道都是"波形采样值 × 振幅 + 偏移"的线性组合,而波形采样值由 AnimMath.CalcValueForNormalizedTime 根据形状、归一化时间、通道索引、Bias 与 Ratio 计算得出。

值得注意的是源码中的注释// Don't use vector to keep double precision(AnimVec2.cs):归一化时间特意用double而非 Vector2 存储,以避免长时间运行后大数值累加导致的精度损失——这是长时间演出场景下的一个实用细节。

波形形状(Shape)与底层实现

Shape输入映射到AnimMath.Shapes枚举(AnimMath.cs),共 13 种,每种在_mapShapes映射表(AnimMath.cs)中有对应的数学实现:

枚举值名称行为说明(依据_mapShapesCalcValueForNormalizedTime
0Endless输出 = 整数部分 + 小数部分的 SchlickBias,可产生"不断增长"的阶梯延续值
1Ramps线性斜坡,0→1 重复
2Saws反向锯齿,1→0 重复
3KickSaws快速回落并停留在 0,类似电子乐"踢鼓"包络
4Square方波,f>0.5 时为 1,否则为 0
5ZigZag三角波,0→1→0 往返
6Wave正弦波归一化到 0..1
7Sin正弦波,范围 -1..1
8PerlinNoisePerlin 噪声,映射到 0..1
9PerlinNoiseSigned有符号 Perlin 噪声,范围 -1..1
10Random基于 XxHash 的伪随机 0..1(每周期跳跃)
11RandomSigned伪随机 -1..1
12Steps返回时间整数部分,产生台阶式递进

对于 Ramps/Saws/Wave/Square/ZigZag/KickSaws,先计算Fmod(time,1)/ratio并 clamp 到 0..1 作为周期内位置,再经 SchlickBias 整形;Sin 与 PerlinNoiseSigned 则使用双向版本的SchlickBiasWithNegative(先归一化到 0..1、加偏置、再映射回 -1..1,见 AnimMath.cs);Random/RandomSigned 用MathUtils.XxHash按时间与通道索引(28657 * componentIndex)生成确定性伪随机数,保证两通道的随机序列互不相同。

输入参数详解

官方文档给出的输入参数表如下,下面结合源码、默认配置文件 AnimVec2.t3 与 UI 配置文件 AnimVec2.t3ui 逐一展开:

名称(Relevancy & Type)描述
OverrideTime(Single)
Shape(Int32)
Rates(Vector2)
RateFactor(Single)
Phases(Vector2)
Amplitudes(Vector2)
AmplitudeFactor(Single)
Offsets(Vector2)
Bias(Single)
Ratio(Single)
AllowSpeedFactor(Int32)

OverrideTime(Single,默认 0)

覆盖内部标准时间。源码逻辑为OverrideTime.HasInputConnections ? OverrideTime.GetValue(context) : context.LocalFxTime——只要该输入有连接,就用外部时间源替换本地效果时间。典型用法是接入 time 类算子或录音回放等自定义时间流,让动画脱离"从开始播放计时"的默认行为。UI 配置中它的显示格式为{0:G3} if connected,即"仅在连接时显示数值"。

Shape(Int32,默认 1 = Ramps)

选择波形形状,对应上文AnimMath.Shapes枚举的 13 种。源码中会先Clamp(0, Enum.GetNames(typeof(AnimMath.Shapes)).Length)防止越界(AnimVec2.cs)。在编辑器中该输入映射为枚举下拉框(MappedType = typeof(AnimMath.Shapes))。

Rates(Vector2,默认 (1, 1))

每个通道的速率倍率,直接乘入各自的归一化时间。UI 配置(AnimVec2.t3ui)中Min: 0Max: 16,表示常规 UI 滑块范围为 0..16;但作为输入槽它仍可被连接任意数值。X/Y 分量独立,是实现"两轴不同速度"的关键参数。

RateFactor(Single,默认 1)

作用于两个通道的全局主速率因子,等价于对Rates两分量同时缩放。UI 显示格式为{0:G3} ×(乘号后缀),范围 0..16。它与Rates的区别在于:RateFactor 是"一把总闸",适合整体提速/减速;Rates 是"每轴独立微调"。

Phases(Vector2,默认 (0, 0))

每个通道的线性时间相位偏移,单位为秒。公式中体现为(time + phases.X/Y),即直接叠加在时间轴上,用于错开两通道的波形起点(例如让 Y 轴落后 X 轴四分之一拍)。

Amplitudes(Vector2,默认 (1, 1))

每个通道的波形振幅。最终值 = 波形采样 × 振幅 + 偏移。默认 (1,1) 意味着波形原样输出(对 0..1 类形状)或双向输出(对 Sin 等 -1..1 类形状)。

AmplitudeFactor(Single,默认 1)

全局振幅倍率。源码中先执行var amplitudes = Amplitudes.GetValue(context) * amplitudeFactor;(AnimVec2.cs),即它在采样前就把Amplitudes整体缩放。UI 显示格式同样为{0:G3} ×。用于在不逐个改动 X/Y 振幅的情况下快速控制整体强度,或通过调制该输入实现"呼吸感"的强弱变化。

Offsets(Vector2,默认 (0, 0))

每个通道的最终值偏移,叠加在"波形 × 振幅"之后,用于把信号抬到目标中心点(例如把 -1..1 的正弦整体上移 0.5)。

Bias(Single,默认 0.5)

Schlick 偏置系数,重新分布波形在周期内的"陡峭程度"。底层使用 Schlick 公式:

SchlickBias(x, bias) = x / ((1/bias - 2) * (1 - x) + 1)

bias = 0.5时函数恒等于x(无影响);趋向 0 时波形前段被压平、末端突变;趋向 1 时前段陡升、末端平缓(AnimMath.cs)。UI 范围被 clamp 到 0..1,图形拖拽时进一步 clamp 到 0.01..0.99。

Ratio(Single,默认 1)

控制周期内波形"占用的比例"。源码计算为(Fmod(time, 1) / ratio).Clamp(0, 1)——ratio 越小,波形在周期内越快走完、其余时间停留在末端(对 Square 相当于占空比调节)。UI 配置Min: 0Max: 1Clamp并显示为百分比格式{0:P2}(AnimVec2.t3ui)。

AllowSpeedFactor(Int32,默认 1 = FactorA)

开关是否从求值上下文读取外部速率覆盖。映射到AnimMath.SpeedFactors枚举:None=0FactorA=1FactorB=2GetSpeedOverrideFromContext会在允许时从context.FloatVariables中查找键"SpeedFactorA""SpeedFactorB",找到则作为rateFactorFromContext乘入归一化时间,找不到则回退为 1(AnimMath.cs)。这是 AnimVec2 与 SetSpeedFactors 协同工作的接口。

在图中直接操控:CTRL + 左键拖拽

官方文档特别说明:You can manipulate the rate and shape directly in the graph by dragging with CTRL+ left mouse button.这一交互由编辑器自定义 UI AnimVec2Ui.cs 实现:

  • 节点上绘制迷你波形预览,标题为"Anim2 " + 当前Shape名,并附带 RateFactor 数值标签;
  • 波形以 80 个采样点(GraphListSteps = 80)绘制,同时用两条竖线标出 X/Y 两通道当前的归一化位置(基于_normalizedTimeX/Y的 Fmod),让你直观看到两轴目前走到波形的哪一段;
  • 按住 CTRL 并左键拖动波形区域即可实时编辑:水平拖动改变RatioRatio + dragDelta.X / 100,clamp 到 0.001..1),垂直拖动改变BiasBias - dragDelta.Y / 100,clamp 到 0.01..0.99),拖拽起点以鼠标按下瞬间的参数值为基准(AnimVec2Ui.cs);
  • 按住 CTRL 悬停时曲线高亮、光标变为ResizeAll,提示"此处可拖"。

这意味着不需要展开参数面板,直接在图上就能完成最常见的 Bias/Ratio 调节;配合节点标题中的速率标签,演出中可快速扫一眼确认当前速度状态。

配合 SetSpeedFactors 实现现场速率覆盖

文档给出的第二条实用建议是:You can use [SetSpeedFactors] to override the incoming rate, which is very useful for live VJ setups.(用 SetSpeedFactors 覆盖传入速率,对现场 VJ 特别有用)。

仓库中的 SetSpeedFactors.cs 提供SpeedFactorASpeedFactorB两个浮点输入与ApplyAs模式切换(NormalizedRates/Factor)。从其内部结构(SetSpeedFactors.t3)看,它通过两个SetFloatVar子节点把值写入上下文的FloatVariables,变量名恰为"SpeedFactorA""SpeedFactorB"——这与AnimMath.GetSpeedOverrideFromContext中查找的键完全一致(AnimMath.cs)。

因此典型联动方式是:把 SetSpeedFactors 放在动画链上游(它输出 Command 用于包裹下游算子),再把 AnimVec2 的AllowSpeedFactor设为FactorAFactorB,之后你在 SetSpeedFactors 上调速,所有接入的动画算子会同步变速。结合 BeatSynchronizer / BPM 系统,可以做出"整场动画随某个控制器或节拍统一变速"的演出效果。

家族对比与延伸学习

AnimVec2 属于 Lib.numbers.anim.animators 算子组,官方文档建议一并查看的算子及仓库对应文档/实现包括:

  • AnimValue:单通道版本,参数为标量(Rate、Amplitude、Offset 等),适合驱动单个数值;
  • AnimVec3:三通道版本,输出 Vector3,适合驱动三维空间位置或 RGB 颜色;
  • TriggerAnim:布尔触发式动画,文档中给出示例链路[HasValueIIncreased]→[TriggerAnim]→[SampleGradient]→[Blob],适合"被事件触发的一次性动画";
  • OscillateVec2 与 OscillateVec3:由 2/3 个正弦波组合成向量的轻量辅助算子。

官方文档还推荐了 HowToAnimate 示例工程(仓库中位于Operators/examples/Symbols/howto/),其中包含多种动画算子的实际接线示范,是学习 AnimVec2 应用场景的最快途径。此外,仓库还自带同类算子(如 OscillateVec2、SetSpeedFactors 等)的.t3/.t3ui符号定义,可直接在 TiXL 编辑器中打开查看其内部连线。

典型接线示例

基于以上原理,一个把 AnimVec2 用于二维位置动画的典型链路可以这样组织:

[SetSpeedFactors] →(包裹)→ [AnimVec2] → [Vector2 → 位置/平移算子] → 图形对象
  • ShapeSinRates设为 (0.5, 1.0),即可得到"X 轴缓慢往返、Y 轴正常正弦"的椭圆轨迹;
  • Phases设为 (0, 0.25),让 Y 通道滞后 X 通道四分之一周期,产生圆形或旋转式轨迹;
  • AmplitudeFactorBias可分别交给现场控制器调制,实现整体尺度与波形形态的实时变化;
  • 需要"两轴异步随机跳变"时,将Shape切到Random,配合AllowSpeedFactor接入全局变速。

默认值速查

AnimVec2 在仓库中的默认配置(AnimVec2.t3)汇总如下,可作为快速上手基线:

参数默认值UI 范围/格式(AnimVec2.t3ui)
Shape1(Ramps)枚举下拉
Rates(1, 1)0..16
RateFactor10..16,{0:G3} ×
Phases(0, 0)
Amplitudes(1, 1)
AmplitudeFactor1{0:G3} ×
Offsets(0, 0)
Bias0.5clamp 0..1(拖拽 0.01..0.99)
Ratio1clamp 0..1,{0:P2}
OverrideTime0仅连接时显示
AllowSpeedFactor1(FactorA)None / FactorA / FactorB

总结

AnimVec2 是 TiXL 动画算子家族中"一节点两路 LFO"的实用成员:它把 BPM 同步、13 种波形形状、Schlick Bias/Ratio 整形、双通道独立速率/相位/振幅/偏移全部收敛进一个 Vector2 输出,配合编辑器内置的波形预览与 CTRL 拖拽交互,让二维动画的调制变得直观且适合现场操作;而其与 SetSpeedFactors 通过FloatVariables上下文协作的机制,则是构建整场统一步速的 VJ 表演系统的关键接口。理解本文的公式、参数与联动方式后,你可以直接打开 HowToAnimate 示例动手验证,再按需替换 Shape、Rates 与 Bias/Ratio,即可快速得到可演出的 2D 动态图形。

【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询