Q100508: Increasing scene graph cook performance with Hierarchical (Instance Source) Instancing



In any scene with repeating geometry, instancing can be used for the benefit of a reduced memory footprint and increased scene graph cook performance. Typically, instancing works well when the geometry is the same across many copies and the only modifications required are transformations. This article describes a method of instancing using instance sources called “hierarchical instancing”, giving an example of how to use it to instance geometry to points of a point cloud.

For an overview on other available instancing approaches, please read the following section in the Katana Developer Guide: Instancing.   

Please refer the Katana project file “PointcloudInstancingAndMaterialAssign_Arnold.katana” for an example project illustrating the sections below on point cloud instancing.


Hierarchical Instancing Overview

The following section is a brief overview of Hierarchical instancing. For a more in-depth discussion to instancing, the Renderman Documentation: RenderMan 25 Docs - Instancing in Katana demonstrates how to set up all three instancing methods as introduction to instancing.

In hierarchical instancing, entire hierarchies of scene graph locations can be instanced. Instance locations are the scene graph locations that will contain the instance, and the instance is defined by the geometry under the source location in the scene graph. An instance source is declared by setting a scene graph location's type attribute to “instance source”. Instance locations themselves are declared by setting their type attribute to “instance”.

The instance source is declared by setting the type attribute of the group location representing the top level location of the hierarchy to be instanced to “instance source”.

The instance locations need to be of type “instance”. A geometry.instanceSource string attribute should be set on these locations, pointing to the instance source scene graph location. 


Hierarchical Instancing to a point cloud

Instancing to a point cloud is similar to instancing to a single instance location as described in the previous section. The difference is that instead of using several locations of type “instance”, the instance location is just one location of type “pointcloud” with a geometry.instanceSource string attribute pointing to the instance source. The following steps explain this setup:


1. Import the instance source using Alembic_In, then set the type of the parent location of the geometry in the scene graph as “instance source”. 


2. Import an alembic point cloud using Alembic_In, then set the geometry.instanceSource attribute to point to the instance source.

Please note that using this method offers less fine-grained control over individual instances in the scene. For example, assigning different materials to individual instances is not easily possible since Scene Graph locations are not generated for each point in a point cloud. However, shader properties of the same material can be varied for individual instances with arbitrary attributes using this method. Furthermore, scaling the point cloud also scales all of the instances, and transformation of individual instances can’t be easily modified. If material variation or if more control over transformations is required, please read the section below for an OpScript approach that is more customizable.


Hierarchical Instancing to a point cloud with OpScript Lua

Hierarchical instancing to a point cloud allows for entire hierarchies of locations to be instanced for each point in a point cloud. Using an OpScript to generate instance locations in the scene graph for each point in a point cloud has the benefits of being able to assign different materials individually to each instance and offering more control over the transformation of instance locations. A potential drawback is a slightly more unwieldy scene graph, especially if there are thousands of instances. The following are steps to achieve hierarchical instancing to a point cloud.


1. Import a point cloud and the instance source using Alembic_In nodes. Then set the type attribute of the instance source to “instance source”.


2. Create an OpScript node and set its location parameter to a scene graph location where instances should be generated, for example: “/root/world/geo/derivedassets”.


3. In the OpScript node, create a user.instanceSourceLocation parameter, set it to the scene graph location of the instance source and set a user.pointCloudLocation parameter to the point cloud’s scene graph location. For steps on creating user parameters, see the Katana User Guide: Adding User Parameters.


4. Then copy the following code into the OpScript node's script parameter to generate instance locations for each point.

-- 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[
     y = points[
     z = points[

-- Build op arguments for the child location
"childAttrs", Interface.GetAttr("", instanceSourceLocation))
"childAttrs.type", StringAttribute("instance"))
"childAttrs.geometry.instanceSource", StringAttribute(instanceSourceLocation))
"childAttrs.xform.interactive.translate", DoubleAttribute({x, y, z}))

-- Create the child
string.format("child%04d", i),
local childAttrs = Interface.GetOpArg("childAttrs")
for i=0, childAttrs:getNumberOfChildren()-1 do
     Interface.SetAttr(childAttrs:getChildName(i), childAttrs:getChildByIndex(i))

The above OpScript creates a location of type 'instance' for each point in a point cloud and sets the geometry.instanceSource attribute of each instance location to the instance source specified in the user.instanceSourceLocation parameter. 


5. Lastly, use a Prune or VisibilityAssign node to remove the point cloud location from the scene graph so that it will be omitted from the render. A VisibilityAssign node allows the points to still be visible in the Viewer, while a Prune node will leave the Viewer empty of an indication of instances. 


Material Variation with Material Assign

Modifying the material per-instance can pose some extra work as all instances inherit the properties of the instance source such as the assigned material. This section will explain a method to vary the material and shader per instance while maintaining the performance benefits of instancing.

Using leaf-level and hierarchical instancing with an OpScript to create instance locations for each point on point clouds has the benefit that materials can be assigned per instance location.

After generating the instance locations, the materials can be varied per location of each instance. Identifying specific instances is as simple as expanding the instance locations in the Scene Graph and selecting the desired instance in the Viewer. In the provided example project, the instance locations can be found underneath the /root/world/geo/derivedassets location.

A material can then be assigned to the desired locations using a MaterialAssign node or by setting a materialAssign attribute on the instance location, pointing to the material location.



For an instancing overview, see the first resource link below. The other resources below go in-depth on other advanced instancing topics on each instancing method.



We're sorry to hear that

Please tell us why