Q100508:通过分层(实例源)实例化提高场景图 Cook 性能

关注

概括

在任何具有重复几何体的场景中,可以使用实例化来减少内存占用并提高场景图烘焙性能。通常,当许多副本中的几何图形相同并且唯一需要的修改是变换时,实例化效果很好。本文介绍了一种使用实例源进行实例化的方法,称为“分层实例化”,并举例说明了如何使用它来将几何体实例化为点云的点。

有关其他可用实例化方法的概述,请阅读Katana开发人员指南中的以下部分:实例化

请参阅Katana项目文件“ PointcloudInstancingAndMaterialAssign_Arnold.katana ”,获取示例项目,说明以下有关点云实例的部分。

分层实例化概述

以下部分是分层实例化的简要概述。要对实例进行更深入的讨论, 请参阅 Renderman 文档:RenderMan 25 Docs - Katana中的实例化,作为实例介绍,演示了如何设置所有三种实例化方法。

在分层实例化中,可以实例化场景图位置的整个分层结构。实例位置是将包含实例的场景图位置,并且实例由场景图中源位置下的几何体定义。通过将场景图位置的类型属性设置为“实例源”来声明实例源。实例位置本身是通过将其类型属性设置为“实例”来声明的。

通过将表示要实例化的层次结构的顶级位置的组位置的类型属性设置为“实例源”来声明实例源。

实例位置必须是“实例”类型。应在这些位置设置Geometry.instanceSource字符串属性,指向实例源场景图位置。

点云的分层实例化

实例化到点云类似于实例化到上一节中所述的单个实例位置。不同之处在于,实例位置不是使用多个“instance”类型的位置,而是只是一个“pointcloud”类型的位置,其中包含一个指向实例源的Geometry.instanceSource字符串属性。以下步骤解释了此设置:

1. 使用Alembic_In导入实例源,然后将场景图中几何体的父位置的类型设置为“实例源”。

2. 使用 Alembic_In 导入 Alembic 点云,然后将Geometry.instanceSource属性设置为指向实例源。

请注意,使用此方法对场景中的各个实例提供的细粒度控制较少。例如,将不同的材质分配给各个实例并不容易,因为不会为点云中的每个点生成场景图位置。但是,使用此方法,对于具有任意属性的各个实例,可以改变相同材质的着色器属性。此外,缩放点云也会缩放所有实例,并且单个实例的转换不能轻易修改。如果材料变化或需要对转换进行更多控制,请阅读下面的部分,了解更可定制的 OpScript 方法。

使用 OpScript Lua分层实例化点云

点云的分层实例化允许为点云中的每个点实例化整个位置分层结构。使用 OpScript 在场景图中为点云中的每个点生成实例位置的好处是能够为每个实例单独分配不同的材质,并对实例位置的转换提供更多控制。一个潜在的缺点是场景图稍微笨重,尤其是在有数千个实例的情况下。以下是实现点云分层实例化的步骤。

1. 使用 Alembic_In 节点导入点云和实例源。然后将实例源的类型属性设置为“实例源”。

2. 创建 OpScript 节点并将其位置参数设置为应生成实例的场景图位置,例如:“/root/world/geo/衍生资产”。

3. 在OpScript节点中,创建一个user.instanceSourceLocation参数,将其设置为实例源的场景图位置,并设置一个user.pointCloudLocation 点云场景图位置的参数。有关创建用户参数的步骤,请参阅Katana用户指南:添加用户参数

4. 然后将以下代码复制到 OpScript 节点的脚本参数中,为每个点生成实例位置。

 -- 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 为点云中的每个点创建一个“instance”类型的位置,并将每个实例位置的Geometry.instanceSource属性设置为user.instanceSourceLocation参数中指定的实例源

5. 最后,使用 Prune 或 VisibilityAssign 节点从场景图中删除点云位置,以便将其从渲染中忽略。 VisibilityAssign 节点允许点在查看器中仍然可见,而 Prune 节点将使查看器中没有实例指示。

材料分配的材料变化

修改每个实例的材质可能会带来一些额外的工作,因为所有实例都会继承实例源的属性(例如分配的材质)。本节将解释一种在保持实例性能优势的同时改变每个实例的材质和着色器的方法。

使用 OpScript 的叶级和分层实例为点云上的每个点创建实例位置的好处是可以为每个实例位置分配材质。

生成实例位置后,每个实例的每个位置的材料都可以不同。识别特定实例就像在场景图中展开实例位置并在查看器中选择所需实例一样简单。在提供的示例项目中,可以在 /root/world/geo/categories 位置下找到实例位置。

然后,可以使用 MaterialAssign 节点或通过在实例位置上设置指向材质位置的materialAssign属性,将材质分配到所需位置。

延伸阅读

有关实例概述,请参阅下面的第一个资源链接。下面的其他资源深入探讨了每种实例方法的其他高级实例主题。

附件

我们很遗憾听到

请告诉我们