概括
在任何具有重复几何体的场景中,可以使用实例化来减少内存占用并提高场景图烘焙性能。通常,当许多副本中的几何图形相同并且唯一需要的修改是变换时,实例化效果很好。本文介绍了一种使用“实例数组”位置进行实例化的方法,并举例说明了如何使用它来将几何体实例化为点云的点。
有关其他可用实例化方法的概述,请阅读Katana开发人员指南中的以下部分:实例化。
您可以参考以下Katana项目文件“ instanceArray_arnold_material.katana ”作为示例项目,说明以下有关点云实例的部分。
实例数组
以下部分是数组实例化的简要概述。要对实例进行更深入的讨论, 请参阅 Renderman 文档:RenderMan 25 Docs - Katana中的实例化,作为实例化的介绍,演示了如何设置所有三种实例化方法。
在实例数组中,实例位置通过“实例数组”类型的单个位置上的属性映射到一个或多个实例源。实例数组与分层实例类似,其附加优点是可以轻松设置多个实例源。一个缺点是材料不能根据实例而变化。
实例数组位置需要包含geometry.instanceSource和至少一个变换属性。如果instanceSource仅包含单个路径,则geometry.instanceIndex是可选的,在这种情况下,实例源用于实例数组中的所有实例。
几何实例源 | 包含一个或多个实例源的场景图位置路径的字符串或字符串数组属性 |
几何实例索引 | 具有与实例所需相同数量的元素的数组属性。该数组中存储的值指示Geometry.instanceSource数组中所需实例源的索引。换句话说, instanceIndex构成了从实例索引到实例源索引的映射。 |
几何.instanceMatrix 几何.instanceTranslate 几何.instanceRotateX 几何.instanceRotateY | 这些属性中的每一个都是每个实例转换的平面数组。每个属性的含义与常规变换属性相同,并且可以对这些属性进行多重采样以支持动画。 注意: RenderMan仅支持使用geometry.instanceMatrix属性。 |
有关实例化属性约定的更多信息,请访问Katana开发人员指南:实例化。
数组实例化为点云
实例数组的优点是仅使用一个位置来保存实例,即使在具有数千个实例位置的场景中,也可以使场景图保持较小。实例数组读取包含实例源位置的geometry.instanceSource属性来生成实例数组。可以使用包含实例源索引数组的geometry.indexArray属性来引用多个实例源,每个实例一个索引。以下是生成实例数组以将几何实例化为点云中的点的步骤。
1.创建或导入点云对象,并使用 AttributeSet 节点将其位置的类型属性设置为点云。点云可以是具有geometry.point.P属性的任何几何体,例如来自PrimitiveCreate节点的几何体。
然后您将看到场景图中点云的位置类型已更改:
2. 然后创建或导入您想要用作实例源的几何体。然后使用另一个 AttributeSet 节点将其父位置的type属性设置为实例源。
例如,如果几何图形位于/root/world/geo/src/teapot,则/root/world/geo/src应为实例源位置。您稍后可以在此位置下添加更多对象以使用多个实例源。
然后,您将在场景图中看到实例源的位置类型发生变化:
3. 将两个网络合并在一起,得到如下所示的结果:
4. 在 Merge 的下游,创建一个 OpScript 节点并将其applyWhere参数更改为at certain location 。现在,您将在 OpScript 节点参数的顶部看到一个新的位置参数。位置参数的值将确定实例数组在场景图中的何处生成。在此示例中,我们使用/root/world/geo/instances
5. 在 OpScript 节点中,创建user.pointCloudLocation字符串参数并将其设置为点云的场景图位置路径。然后创建一个user.instanceSourceLocations字符串数组参数,其小部件类型为Scene Graph Locations ,并将实例源场景图位置路径作为值添加到数组中。
有关创建用户参数和更改其小部件类型的步骤,请参阅Katana用户指南:添加用户参数。
6. 以下 OpScript Lua 代码是从Renderman Docs: Instancing中找到的 Pixar 示例中修剪而来的,它基于点云和实例源位置创建实例数组。
将此代码复制到 OpScript 节点的脚本参数中,以生成实例数组,其中实例放置在点云的每个点处。
-- Read the op arguments
local instanceSourceLocations = Interface.GetOpArg( "user.instanceSourceLocations" )
local pointCloudLocation = Interface.GetOpArg( "user.pointCloudLocation" ):getValue()
-- Read the point cloud's points
local pointAttr = Interface.GetAttr( "geometry.point.P" , pointCloudLocation)
local points = pointAttr :getNearestSample(Interface.GetCurrentTime())
-- Create a single location which will generate an array of instances
-- Set type for this location to 'instance array'
Interface.SetAttr( 'type' , StringAttribute( 'instance array' ))
-- This instance array location must point to the instance source locations
-- through the attribute 'geometry.instanceSource'
Interface.SetAttr( 'geometry.instanceSource' , instanceSourceLocations)
-- The indexArray attribute determines which instance source each instance location represents
local indexArray = {}
-- for each instance create an instance index
for i= 0 ,#points/ 3-1 do
-- For this example, the instances are arbitrarily assigned to an
-- instance source
-- a more stable apporach would be to use an arbitrary attribute
-- on the point cloud to assign an instance source
indexArray[#indexArray +1 ] = i%instanceSourceLocations:getNumberOfTuples()
end
-- Set index for instance array element
Interface.SetAttr( 'geometry.instanceIndex' , IntAttribute(indexArray, 1 ))
-- geometry.instanceMatrix
-- Get the transforms from the points
local numTimeSamples = pointAttr:getNumberOfTimeSamples()
local matrixArrayMap = {}
-- to get motion blur on the instances, create an instanceMatrix at each
-- time sample available from the point cloud points attribute
for idx=0,numTimeSamples -1 do
local sampleTime = pointAttr:getSampleTime(idx)
local points = pointAttr:getNearestSample(sampleTime)
-- each instance in array has its own matrix
local matrixArray = {}
local workMatrix = Imath.M44d():toTable()
-- for each instance build a matrix with a mocked up transformation
for i=0,#points/ 3-1 do
-- grab the points that represent this instance
x = points[ 3 *i +1 ]
y = points[ 3 *i +2 ]
z = points[ 3 *i +3 ]
-- set the translate of the matrix to the points in the point cloud
workMatrix[ 13 ] = x
workMatrix[ 14 ] = y
workMatrix[ 15 ] = z
for j = 1 , 16 do
matrixArray[#matrixArray +1 ]=workMatrix[j]
end
end
matrixArrayMap[sampleTime] = matrixArray
end
Interface.SetAttr('geometry.instanceMatrix', DoubleAttribute (matrixArrayMap, #matrixArrayMap))
上面的OpScript将实例数组geometry.instanceSource属性设置为在user.instanceSourceLocations用户参数中设置的实例源位置。此外,实例数组geometry.instanceIndex属性设置为在实例源之间交替。最后,实例数组geometry.instanceMatrix属性由点云中每个点的平移信息填充。
7. 现在实例已经创建,不再需要点云,我们可以使用 Prune 节点将其从场景中删除。
现在您可以渲染以查看实例数组:
您可以在此处下载完成的场景: instanceArray.katana
用于改变每个实例分配的材质的实例数组解决方法
与其他实例化技术不同,实例数组没有直接改变每个实例的材质的机制。然而,通过使用具有不同材料的实例源位置,可以使用不同的材料。使用实例数组的好处是所有实例都包含在一个场景图位置中。然而,这也意味着定位特定实例几乎是不可能的,因为各个实例不会出现在查看器或场景图中,并且仅在场景的渲染中可见
请参阅上面的实例数组到点云部分来生成实例数组。创建实例数组后,可以通过改变每个实例源的材质来改变每批实例的材质。使用 MaterialAssign 节点更改实例源的材质,并且材质分配会传递到利用该特定实例源的每个实例位置。只需创建 MaterialAssign 节点并将材质分配到选择作为实例源的场景图位置。
延伸阅读
有关实例概述,请参阅下面的第一个资源链接。下面的其他资源深入探讨了每种实例方法的其他高级实例主题。
- Katana开发者指南:实例化
- Q100508:通过分层(实例源)实例化提高场景图 Cook 性能
- Q100517:通过叶级(实例 ID)实例化提高场景图烘焙性能
- Renderman 文档:RenderMan 25 文档 - Katana中的实例化
附件
我们很遗憾听到
请告诉我们