概括
在任何包含重复几何体的场景中,实例化都能有效减少内存占用并提升场景图的计算性能。通常,当多个副本的几何体完全相同,且仅需进行变换时,实例化效果最佳。本文介绍了一种使用实例源的实例化方法,称为“分层实例化”,并举例说明如何使用该方法将几何体实例化为点云中的点。
有关其他可用实例化方法的概述,请阅读Katana开发人员指南中的以下部分:实例化。
请参考Katana项目文件PointcloudInstancingAndMaterialAssign_Arnold.katana ,其中包含一个示例项目,演示了以下关于点云实例化的部分。
更多信息
层级实例化概述
以下部分简要概述了分层实例化。如需更深入地了解实例化,请参阅 RenderMan 文档: RenderMan 26 Docs - Katana中的实例化,其中演示了如何设置所有三种实例化方法,作为实例化的入门介绍。
在层级实例化中,可以实例化整个场景图位置层级结构。实例位置是包含实例的场景图位置,实例由场景图中源位置下的几何体定义。实例源通过将场景图位置的 type 属性设置为“instance source”来声明。实例位置本身通过将其 type 属性设置为“instance”来声明。
通过将表示要实例化的层次结构顶层位置的组位置的类型属性设置为“实例源”来声明实例源。
实例位置必须为“实例”类型。应在这些位置上设置geometry.instanceSource字符串属性,指向实例源场景图位置。
分层实例化到点云
将点云实例化与上一节所述的将点云实例化到单个实例位置类似。区别在于,实例位置并非使用多个“实例”类型的位置,而是使用一个“点云”类型的位置,该位置具有一个指向实例源的geometry.instanceSource字符串属性。以下步骤说明了此设置:
1. 使用 Alembic_In 导入实例源,然后将场景图中几何体的父位置类型设置为instance source 。
2. 使用 Alembic_In 导入 Alembic 点云,然后将geometry.instanceSource属性设置为指向实例源。
请注意,使用此方法对场景中的各个实例的控制粒度较差。例如,由于场景图位置并非针对点云中的每个点生成,因此很难为各个实例分配不同的材质。但是,使用此方法可以为具有任意属性的各个实例更改同一材质的着色器属性。此外,缩放点云也会缩放所有实例,因此无法轻松修改各个实例的变换。如果需要更改材质或更精细地控制变换,请阅读下文,了解更可定制的 OpScript 方法。
使用 OpScript Lua 将分层实例化到点云
对点云进行层级实例化,可以针对点云中的每个点实例化整个位置层级结构。使用 OpScript 在场景图中为点云中的每个点生成实例位置,其优势在于能够为每个实例单独分配不同的材质,并更好地控制实例位置的变换。潜在的缺点是场景图会略显臃肿,尤其是在实例数量达到数千个时。以下是实现对点云进行层级实例化的步骤:
1. 使用 Alembic_In 节点导入点云和实例源。然后将实例源的类型属性设置为“实例源”。
2. 创建一个 OpScript 节点,并将其位置参数设置为应该生成实例的场景图位置,例如:“/root/world/geo/derivedassets”。
3. 在 OpScript 节点中,创建一个user.instanceSourceLocation参数,将其设置为实例源的场景图位置,并设置一个user.pointCloudLocation 用户参数用于点云场景图的位置。有关创建用户参数的步骤,请参阅Katana用户指南:添加用户参数。
4. 然后将以下代码复制到 OpScript 节点的script参数中,以生成每个点的实例位置。
-- Read op arguments
local instanceSourceLocation = Interface.GetOpArg("user.instanceSourceLocation"):getValue()local pointCloudLocation = Interface.GetOpArg("user.pointCloudLocation"):getValue()
if Interface.AtRoot() then
-- Read the point cloud
local points = Interface.GetAttr("geometry.point.P", pointCloudLocation):getNearestSample(Interface.GetCurrentTime())
-- Loop over points
local x, y, z
local gb = GroupBuilder()
for i=0, #points/3 - 1 do
x = points[3*i+1]
y = points[3*i+2]
z = points[3*i+3]
-- Build op arguments for the child location
gb:update(Interface.GetOpArg())
gb:set("childAttrs", Interface.GetAttr("", instanceSourceLocation))
gb:set("childAttrs.type", StringAttribute("instance"))
gb:set("childAttrs.geometry.instanceSource", StringAttribute(instanceSourceLocation))
gb:set("childAttrs.xform.interactive.translate", DoubleAttribute({x, y, z}))
-- Create the child
Interface.CreateChild(
string.format("child%04d", i),
Interface.GetOpType(),
gb:build())
end
else
local childAttrs = Interface.GetOpArg("childAttrs")
for i=0, childAttrs:getNumberOfChildren()-1 do
Interface.SetAttr(childAttrs:getChildName(i), childAttrs:getChildByIndex(i))
end
end
上述 OpScript 为点云中的每个点创建一个类型为“实例”的位置,并将每个实例位置的geometry.instanceSource属性设置为user.instanceSourceLocation参数中指定的实例源。
5. 最后,使用 Prune 或 VisibilityAssign 节点从场景图中移除点云位置,使其在渲染中被忽略。VisibilityAssign 节点允许这些点在查看器中仍然可见,而 Prune 节点则会在查看器中完全移除实例指示。
材料差异与材料分配
逐个实例修改材质会增加一些额外的工作量,因为所有实例都会继承实例源的属性,例如分配的材质。本节将介绍一种在保持实例化性能优势的同时,为每个实例更改材质和着色器的方法。
使用 OpScript 进行叶级和分层实例化,为点云上的每个点创建实例位置,其优点是可以为每个实例位置分配材质。
生成实例位置后,可以针对每个实例的不同位置更改材质。要识别特定实例,只需在场景图中展开实例位置,然后在查看器中选择所需的实例即可。在提供的示例项目中,实例位置位于/root/world/geo/derivedassets location目录下。
然后可以使用 MaterialAssign 节点或在实例位置上设置materialAssign属性,指向材料位置,将材料分配到所需的位置。
延伸阅读
有关实例化的概述,请参阅下方第一个资源链接。下方的其他资源将深入探讨每种实例化方法的其他高级实例化主题。
- Katana开发者指南:实例化
- Q100517:通过叶级(实例 ID)实例化提高场景图烹饪性能
- Q100514:利用实例数组实例化提高场景图烹饪性能
- RenderMan 文档:RenderMan 26 文档: Katana中的实例化
附件
我们很遗憾听到
请告诉我们