全局、序列、帧数据
After Effects 允许插件在三个范围存储数据: 全局,序列和帧。 仔细考虑将信息存储在何处; 选择不当会影响性能,或者让用户感到困惑。
将全局数据用于所有效果实例的公共信息: 静态变量和数据、位图、指向其他 DLL 或外部应用程序的指针。 如果你的效果支持多帧渲染,任何静态或全局变量都必须不存在竞争条件(参见效果线程安全意味着什么? 的更多信息)。
将任何特定于此插件实例的内容( UI 设置、文本字符串和任何未存储在参数中的自定义数据)存储在序列数据或新的多帧渲染计算缓存中。
帧数据用于特定于渲染给定帧的信息。 这已经被废弃了,因为大多数机器一次可以将整个帧加载到内存中。 当然,生成 IMAX 的用户仍然会欣赏您所做的任何优化。
持续性
After Effects 在项目文件中保存序列数据,但不保存全局或帧数据。序列数据中指向外部数据的指针在重新打开项目时很可能无效,必须重新连接。我们称这个过程为序列数据的“平展化”和“非平展化”。
注意:计算缓存不会将其内容存储到项目文件中。必须在渲染期间重新创建存储在缓存中的数据。
验证序列数据
仔细的序列数据验证对于跨时间进行模拟的效果非常重要,因为第 N 帧依赖于第 N-1 帧,并且您在序列数据中使用了计算数据的缓存。 如果一个参数改变了,某些计算的数据可能不再有效,但盲目地在每次更改后重新计算一切也是浪费。
当要求渲染第 N 帧时,假设您已经计算了缓存数据到第 N-1 帧,从 PF_ParamUtilSuite3
调用 PF_GetCurrentState() / PF_AreStatesIdentical()
来查看计算数据的缓存在当前参数设置下是否仍然有效。
所有参数的状态(除了那些设置了 PF_ParamFlag_EXCLUDE_FROM_HAVE_INPUTS_CHANGED
的参数),包括层参数(包括 param[0]
)在过去的时间跨度内进行检查。
它能有效地完成,因为更改跟踪是用时间戳完成的。
如果输入没有改变,您可以安全地使用缓存,并且内部缓存系统将假定您对传递的范围(passed range)有时间依赖性。 因此,如果上游(upstream)发生变化,主机的缓存将自动失效。
为了测试它的工作,在每一帧,在一个打上关键帧的参数上应用你的效果。 RAM 预览填充缓存,然后改变其中一个关键帧。 相关联的帧和所有依赖的帧(例如,在模拟的情况下,后面的帧)应该失去它们的缓存标记并需要重新渲染。 类似地,对层参数来源的上游的变化应该会导致缓存的时间选择性(time-selective)失效。
展平化和非展平化的序列数据
如果序列数据引用外部内存(在指针或句柄中),则必须将数据平展化 或 非平展化以实现磁盘安全存储。这类似于创建自己的微型文件格式。
在接收到 PF_Cmd_SEQUENCE_FLATTEN
后,将指针引用的数据放到一个连续块中,稍后可以从这个块中恢复旧的结构。
如果序列数据包含一个指向 long
的指针,分配 4 个字节来存储平展化的数据。您必须处理平台特定的字节排序。
请记住,您的用户(购买了两个插件副本的用户)可能希望在 macOS 和 Windows 上使用相同的项目。
当数据重新加载后,无论是平展化的数据还是非平展化的数据,Effects 都会发送 PF_Cmd_SEQUENCE_RESETUP
。
在两个结构的共同偏移量处使用标志来指示数据的状态。
typedef struct {
A_char* messageZ;
PF_FpLong big_numF;
void* temp_storage;
} non_flat_data;
typedef struct {
char message[256];
PF_FpLong big_numF;
A_Boolean big_endianB;
} flat_data;
复制代码
缩放序列数据
在 PF_Cmd_SEQUENCE_SETUP
期间,为特定于你的效果实例的数据分配句柄。
您可以在任何选择器中修改序列数据的内容,但不能修改序列数据的大小。
你只能在以下选择器中调整序列数据句柄的大小:
PF_Cmd_AUDIO_SETUP
PF_Cmd_AUDIO_SETDOWN
PF_Cmd_FRAME_SETUP
PF_Cmd_FRAME_SETDOWN
PF_Cmd_AUDIO_RENDER
PF_Cmd_RENDER
PF_Cmd_SEQUENCE_SETUP
PF_Cmd_SEQUENCE_SETDOWN
PF_Cmd_SEQUENCE_FLATTEN
PF_Cmd_SEQUENCE_RESETUP
PF_Cmd_DO_DIALOG
在多帧渲染的渲染时刻访问 sequence_data
当对一个效果启用多帧渲染时, sequence_data
对象在渲染期间将是只读的 const ,并且可以通过 PF_EffectSequenceDataSuite1
套件在每个渲染线程上访问。
PF_EffectSequenceDataSuite1
PF_GetConstSequenceData
当启用多帧渲染效果时,检索渲染线程的只读 const sequence_data
对象。
PF_Err(*PF_GetConstSequenceData)(
PF_ProgPtr effect_ref,
PF_ConstHandle *sequence_data);
复制代码
static PF_Err Render(
PF_InData *in_dataP,
PF_OutData *out_dataP,
PF_ParamDef *params[],
PF_LayerDef *output )
{
PF_ConstHandle seq_handle;
AEFX_SuiteScoper<PF_EffectSequenceDataSuite1> seqdata_suite = ///< 获取套件
AEFX_SuiteScoper<PF_EffectSequenceDataSuite1>(
in_dataP,
kPFEffectSequenceDataSuite,
kPFEffectSequenceDataSuiteVersion1,
out_dataP);
PF_ConstHandle const_seq; ///< 只读对象
seqdata_suite->PF_GetConstSequenceData(in_data->effect_ref, &const_seq);
// 将 const_seq 转换为存储到 sequence_data 时使用的类型
// rest of render function code...
}
复制代码