Q100311:如何在自定义渲染器插件中实现实时渲染

概括

本文解释了如何在渲染器插件中实现实时渲染,并涵盖以下主题:

  • 属性约定
  • 渲染器信息插件功能
  • 渲染插件功能
  • Python 工具
    - LiveRenderAPI
    -
    实时渲染动作
    - 回调函数
  • 陷阱
    - 单次采样更新
    非持久性更新

有关实时渲染的一般说明,请参阅Katana用户指南中关于渲染类型的描述,以及执行渲染中的“启动和停止实时渲染”子部分和关于控制实时渲染的部分。

有关渲染器插件其他部分的详细说明,以及与实时渲染没有直接关系的渲染 API 其他功能的文档,可以在Katana开发者指南的渲染器插件部分找到。

更多信息

属性约定

Katana的实时渲染系统由场景图中的属性驱动。为了提高效率,只有更新渲染器所需的属性才会被发送到渲染插件。属性的约定如下:

liveRender.<updateGroup>.<attributeName>

image__3_.png

<updateGroup> - 这是一个 GroupAttribute,用于将属性组合在一起进行单个更新。

<attributeName> - 这是要监控的顶级属性的名称。在上图中, liveRender.geoXform.xform属性指示实时渲染系统将任何更改发送到顶级xform属性。请注意,这是一个 StringAttribute 类型,其值通常与<updateGroup>匹配。这是出于历史原因,但通常内部不使用。如果在同一个更新组中指定了多个属性,则当其中任何一个属性发生更改时,所有属性都会被发送到渲染器。

渲染器信息插件功能

void fillLiveRenderTerminalOps( OpDefinitionQueue & terminalOps ,
                              const FnAttribute::GroupAttribute& stateArgs )

虽然可以在节点图中设置上述属性约定,但通常更方便的做法是使用 RendererInfo 插件中的fillLiveRenderTerminalOps()函数,在实时渲染开始时自动设置属性。该函数接收一个名为terminalOps 的参数,该参数是一个std::deque ,其中包含一个或多个std::pair对象,每个对象包含操作类型( std::string类型)和操作参数( GroupAttribute类型)。

例如,以下代码监视/root/world/lgt下灯光位置的xform属性的变化

 FnAttribute::GroupBuilder opArgs;
opArgs. set ( "type" , FnAttribute::StringAttribute( "light" ));
opArgs. set ( "location" , FnAttribute::StringAttribute( "/root/world/lgt" ));
opArgs. set ( "attributeNames" , FnAttribute::StringAttribute( "xform" ));
terminalOps.push_back( std ::make_pair( "LiveRenderFilter" , opArgs.build()));

Katana自带的Geolib3 操作在这里很有用:

实时渲染过滤器

用于指示哪些属性需要监控以进行实时渲染。单个 LiveRenderFilter 可以监控多个属性,如果其中任何一个属性发生更改,所有属性都会作为一个 GroupAttribute 发送。这是设置上述实时渲染属性约定的标准方法。

操作精氨酸

- attributeNames (StringAttribute) - 属性名称应被监视以进行更改,并在每次更改时作为单个更新发送到渲染插件。

- location (StringAttribute)- 一个 CEL 表达式,定义此操作应用的第一个位置。它将应用于所有子位置。

- exclusions (StringAttribute) - (可选)排除位置类型的列表,此操作不应在这些位置类型上运行。

- typeAlias (StringAttribute)- (可选)将发送给渲染插件的“type”属性的名称。如果未设置,则将使用位置类型。

- type (StringAttribute) - (可选)如果设置,则操作将仅在这种类型的位置运行。

- collectUpstream (IntAttribute) - (可选)如果非零,则每个父位置的每个受监视属性的值也将包含在实时渲染更新中。

生命属性

此操作会存储查看器操作器在操作过程中生成的值(而不是等待操作完成且参数最终确定)。此操作是实时渲染模块专门查找的特殊情况。

操作精氨酸

此操作的参数由实时渲染系统自动设置,不应手动设置。

LocalizeXform

将某个位置的所有祖先的 xform 扁平化为一个名为 xform.matrix 的单一世界空间矩阵。

操作精氨酸

- excludeCel (StringAttribute) - 描述操作不应应用到的场景图位置的 CEL 表达式。

- addMaterialHash (IntAttribute) - (可选)旧版本实时渲染的遗留行为。如果非零,则“material”属性的哈希值将存储为“materialHash”。

- outputAttrName (StringAttribute)-(可选)用于存储新的本地 xform 属性的名称。默认为“xform”,会覆盖现有属性。

LocalizeLiveAttributeXform

在查看器中进行操作时,位置的实际 xform 属性不会改变(直到笔尖抬起)。取而代之的是,使用 LiveAttribute 操作将临时 xform 存储在liveAttributes.xform下。此操作类似于 localizeXform,但它遵循 liveAttribute 约定,因此如果liveAttributes.xform存在,则会使用它而不是 xform。这允许在操作期间更新位置的 xform。当然,此操作必须在 LiveAttribute 操作之后应用。

操作精氨酸

- addMaterialHash (IntAttribute) - (可选)旧版本实时渲染的遗留行为。如果非零,则“material”属性的哈希值将存储为“materialHash”。

本地化灯光列表实时渲染过滤器

此操作是标准 LiveRenderFilter 操作的特例,专门用于灯光列表。它的行为与 LiveRenderFilter 操作类似,区别在于它会在每个位置创建关于 lightList 属性的附加信息。这些信息包括灯光路径、当前位置是否启用灯光链接以及父位置是否启用灯光链接。这些信息将作为“lightLink”更新发送到渲染插件。

操作精氨酸

- attributeNames (StringAttribute) - 属性名称应被监视以进行更改,并在每次更改时作为单个更新发送到渲染插件。

- location (StringAttribute)- 一个 CEL 表达式,定义此操作应用的第一个位置。它将应用于所有子位置。

- exclusions (StringAttribute) - (可选)排除位置类型的列表,此操作不应在这些位置类型上运行。

- typeAlias (StringAttribute)- (可选)将发送给渲染插件的“type”属性的名称。如果未设置,则将使用位置类型。

- type (StringAttribute) - (可选)如果设置,则操作将仅在这种类型的位置运行。

- collectUpstream (IntAttribute) - (可选)如果非零,则每个父位置的每个受监视属性的值也将包含在实时渲染更新中。

坐标系统实时渲染过滤器

这是标准 LiveRenderFilter 操作的另一个特例,专门用于坐标系。它的行为与 LiveRenderFilter 操作完全相同,区别在于它会先检查当前位置是否在/root/world/目录下的globals.coordinatesystems属性中列出,只有当该属性为真时才会继续执行。

操作精氨酸

- attributeNames (StringAttribute) - 属性名称应被监视以进行更改,并在每次更改时作为单个更新发送到渲染插件。

- location (StringAttribute)- 一个 CEL 表达式,定义此操作应用的第一个位置。它将应用于所有子位置。

- exclusions (StringAttribute) - (可选)排除位置类型的列表,此操作不应在这些位置类型上运行。

- typeAlias (StringAttribute)- (可选)将发送给渲染插件的“type”属性的名称。如果未设置,则将使用位置类型。

- type (StringAttribute) - (可选)如果设置,则操作将仅在这种类型的位置运行。

- collectUpstream (IntAttribute) - (可选)如果非零,则每个父位置的每个受监视属性的值也将包含在实时渲染更新中。

渲染器插件功能

int startLiveEditing()
 int stopLiveEditing()

这两个函数由Katana调用,用于通知您实时渲染何时处于活动状态以及位置更新何时会发生。

 int processControlCommand( const std::string & command )

此函数是Katana用户界面与渲染插件之间的一种通信方式。用户界面可以通过 Python 的LiveRenderAPI.SendCommand()函数以字符串形式发送命令,您可以在渲染插件中处理该命令,用于任何您想要的目的。

 int queueDataUpdates(FnAttribute::GroupAttribute updateAttribute)

当被监控的属性发生变化时,其新值将通过此函数传递给渲染插件。传递的属性将包含三个子属性:

  • type - 更新类型(即上面属性约定部分列出的<updateGroup>
  • 位置- 此更新所针对的场景图位置。
  • 属性- 已更改属性的值。请注意,如果位置已被删除,则此项将包含一个名为“deleted”的属性。

请注意,此函数是在一个专门用于接收实时渲染更新的专用线程中调用的。

 bool hasPendingDataUpdates()

该函数告诉 renderboot 进程是否有已在queueDataUpdates()中排队的实时渲染更新需要应用。

 int applyPendingDataUpdates() 

此函数在主渲染线程中调用,负责接收并应用所有已排队的实时更新。仅当hasPendingDataUpdates() ` 返回 `true` 时才会调用此函数。

Python 实用程序

Katana的用户界面提供了多种实用工具,有助于改善实时渲染体验,如下所示:

LiveRenderAPI

此 API 允许您使用LiveRenderAPI.SendCommand()LiveRenderAPI.SendData()函数向正在运行的实时渲染发送自定义命令(字符串)或实时更新。它还提供了各种函数来查询和修改实时渲染子系统正在使用的终端操作列表。这些终端操作用于确定位置何时发生变化,而不是改变当前场景图(由您的节点生成)。这实际上是一种更改在调用RendererInfo::fillLiveRenderTerminalOps()期间传递的操作的方法。

实时渲染动作

您可以通过使用plugin_apis/python/BaseLiveRenderAction.py中的类,为“渲染 > 实时渲染”菜单添加自定义菜单项。只需继承 BaseLiveRenderAction 类(该类本身继承自QtGui.QAction )并重写其成员函数即可。这样,您的类就可以使用Katana的任何 Python API,包括 LiveRenderAPI,从而向渲染插件发送自定义命令或更新。LiveRenderAction 的实例应放置在$KATANA_RESOURCES/UIPlugins目录中,以确保它们仅在 UI 会话期间尝试加载。

回调函数

在向渲染插件发送实时更新或实时渲染命令之前, Katana会分别触发名为 onLiveRenderUpdate 或 onLiveRenderCommand 的回调函数。这些回调函数会接收即将传递给渲染插件的命令或更新属性。这主要用于监控,允许您检查传递给渲染插件的数据,但也可以通过引发异常来阻止消息的发送。不过,这样做会在Katana的消息日志中触发一条错误消息。

陷阱

单次采样更新

渲染开始时,geolib 会生成多重采样属性以实现运动模糊等效果。然而,在Katana UI 中,属性通常仅使用单次采样获取,并且实时渲染更新也来自Katana UI。这意味着在实时更新期间发送的属性通常只有一个时间采样。

非持久性更新

渲染开始时, Katana会将生成场景的操作树写入磁盘,渲染进程(使用其自身的 Geolib3 运行时)会读取该操作树。渲染插件可以通过 SceneGraphIterator 访问场景图及其属性。然而,该场景是不可变的。当Katana传递实时渲染更新时,它无法更新 Geolib3 运行时。这意味着,即使渲染插件已收到实时更新,SceneGraphIterator 也始终返回原始场景。因此,实时更新属性必须包含渲染插件所需的所有信息,因为您无法安全地使用 SceneGraphIterator 获取额外信息。

    我们很遗憾听到

    请告诉我们