Solaris is the umbrella name for Houdini’s scene building, layout, lighting, and rendering tools based on the Universal Scene Description (USD) framework. LOP (lighting operator) nodes generate USD describing characters, props, lighting, and rendering.

Tips

Instancer

  • Instancer
    • The hip file below ( karma_instancer_motionblur.hiplc ) contains a simple instancer setup
    • SOP level
      • Prototype meshes
        • Create some meshes to use as prototypes
        • Give each mesh a unique primitve name attrib, for instance “sphere”
        • Create a path attrib to place them where you want them in the scene graph
          • we can do this with vex and base it on the name attrib:
          • s@path = ‘/geo/meshes/‘+s@name;
      • Target Points
        • Create some points
        • Give them names (point attrib) that matches the name we gave to meshes
          • The point attrib name will be used to instance the “correct” geo
    • LOP level
      • SOP Create
        • Create an SOP Create node
        • Dive in, and create an Object Merge and point to the SOP geo
        • Solaris will use the path attrib to place the prims in the scene tree
      • Collection
        • Create a Collection node
        • Give it a Collection Name: “my_collection”
        • Remove the all text inside the Primitives textbox
        • Write /geo/meshes/* in the Primitives textbox
          • what this means is that it will add all primitives below this primitive to the collection
        • Note: from the scene graph tree you can also drag and drop the “geo/meshes” that we brought in with the sop create. Just make sure to add “/*” at the end
      • Instancer
        • Target points > Location Source : External SOP
          • Set the SOP Path to point to the SOP level points we created
        • Prototype Primitives
          • On the Prototypes > Prototype Primitives we need to set the collection we created.
          • Enter “%my_collection” (percentage sign followed by he collection name we set earlier)
          • Note: you can also use the drop down on the right hand side and at the bottom of the list you should find the collection
          • We also set the Primitive Path (of the instancer) to organize the scene graph tree
        • Prototype Index In the Options > Prototype Index we set Name Attribute and set the Name Attribute to “name”

Rendering

  • Motion Blur
    • Instancer
      • Curved instance motion blur
        • Create a Trail SOP
          • To be able to generate acceleration blur on the instances we use a trail sop to generate v and accel attrib
          • Result Type : Compute Velocity
          • Velocity Approximation: Central Difference
          • Compute Acceleration: On
      • karma_instancer_motionblur.hiplc
        Setup acceleration motion blur on instancer in Karma
  • Cryptomatte
    • Houdini > Resolve
      • To be able to render a cryptomatte exr for use in Fusion we need to render in Legacy Mode
      • To do this either:
        • USD Render ROP > Husk > Rendering > Enable Legacy EXR Mode: On
        • USD Render ROP > Output > Render Command : husk –exrmode 0
      • Also if you use fusion in Resolve you can not use the Media in, you need to use a Loader to bring in the exr

Lighting

  • Automatic headlight Creation
    • The default behaviour when there are no lights present in the scene is to create a default headlight. To disable the default light uncheck the following checkbox
      Karma render settings (node) > Rendering > Geometry and Shading > Shading > Automatic Headlight Creation : Disable

Python

Scene Graph Tree

Lets select some prims in the Scene Graph Tree using Python. Note that the selection is stored on the LOP Network. In this example below the lop network is inside the “geo1” sop network. If it we are using the lop “Stage” context the path would be “/stage”

# get the selection of a lopnetwork inside a geo sop network

hou.node('/obj/geo1/lopnet1').selection()

# get the selection of the "root" stage context

hou.node('/stage').selection()

# set selection

paths = ['/scene/geo/sub/sphere', '/scene/geo/sub/box']
hou.node('/stage').setSelection(paths)

Get prim

We are in the Stage context in houdini.

  • In the LOP network we have 3 nodes.
    • First we have a null named “null_0”
    • Then we have a Material Library named “materiallibrary” connected
      • An inside this material library we have a material called “green”
    • Lastly we have a null named “null_1” connected at the end
  • Lets try to get the material prim
    • If we try to get it through the first null we are out of luck since the prim does not yet exists in “usd” file.
    • But we can get it if we access it through the material library or the last null node
# Try accessing through null_0

lop_node = hou.node('/stage').node('null_0')
# <hou.LopNode of type null at /stage/null_0>

stage = lop_node.stage()
# Usd.Stage.Open(rootLayer=... ...LOP:rootlayer-session.usda'))

stage.GetPrimAtPath('/materials/green')
# invalid null prim


# Try accessing through null_1

lop_node = hou.node('/stage').node('null_1')
# <hou.LopNode of type null at /stage/null_1>

stage = lop_node.stage()
# Usd.Stage.Open(rootLayer=... ...LOP:rootlayer-session.usda'))

stage.GetPrimAtPath('/materials/green')
# Usd.Prim(</materials/green>)

Camera

# camera in the lop context named camera1

# translation: (1, 2, 3)

# rotation: (-270, 0, 0)


lop_cam = hou.node('/obj/lopnet1/camera1')
stage = lop_cam.stage()
primpath = lop_cam.evalParm("primpath")
cam = stage.GetPrimAtPath(primpath)

property_names = cam.GetPropertyNames() 
# print(property_names)

# ['clippingPlanes', 'clippingRange', 'exposure', 'focalLength', ...


focus_dist_attr = cam.GetAttribute('focusDistance')
focus_dist = focus_dist_attr.Get()
#print(focus_dist)

# 9.644547462463379

#print(type(focus_dist))

# <class 'float'>


transform_attr = cam.GetAttribute('xformOp:transform')
transform = transform_attr.Get()
#print(transform)

# ( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (1, 2, 3, 1) )

#print(type(transform))

# <class 'pxr.Gf.Matrix4d'>

#print('\n'.join(dir(transform)))


pos = transform.GetRow3(3)
#print(pos)

# (1, 2, 3)

#print(type(pos))

# <class 'pxr.Gf.Vec3d'>

pos_tuple = (pos[0], pos[1], pos[2])


z_axis = transform.GetRow3(2)
#print(z_axis)

# (0, -1, 0)

z_axis_tuple = (z_axis[0], z_axis[1], z_axis[2])

print(pos_tuple)
print(z_axis_tuple)

Docs

Vex

Materials

I am using an Assign material node with the primpattern parm set to All Mesh Primitives (%type:Mesh) and using vex to specify the material (see snippet below).
I am checking if a shop_materialpath attr exists, if it does use that to construct the material name, if it does not exist set the “material name” to “no_shopmatpath”. Then I am checking to see if the constructed path to the material exists if it does, assign the material (by returning it) if it does not return the path to a material that will be used when materials are missing in the lop material library. This is probably not the best way to do this, but it is a way.

string shop = usd_attrib(0, @primpath, 'shop_materialpath');
if(shop==''){
    shop = 'no_shopmatpath';
}

string mat_name = '/materials/' + shop;
int mat_exists = usd_isprim(0, mat_name);

if (mat_exists){
    return mat_name;
}

else {
    return '/materials/missing_in_lop';
}
usd_assign_mat_with_vex_01.hiplc
Assign material with vex (with fallback for missing material) using sop attrib

misc

// material binding
string mat = usd_boundmaterialpath(0, @primpath);

// set attrib
usd_setattrib(0, @primpath, 'yolo', 42);

Nodes

Rendering

Camera

Latlong cubemap in Karma
I needed to render out a cube map using Karma so this led me to dig deeper into lens shaders. Paul Ambrosiussen and Matt Estela has some good information on the subject.
There seems to be a bug when Karma is rendering with Hython so the lensshader using cvex errors out (will maybe be fixed in Houdini 19.5). A workaround is to use the vrlens shader that you can create in a shopnet context.

karma_lens_shader_01.hiplc
Latlong / Polar CVEX Lens shader

Settings

Applies renderer-specific geometry settings to geometry in the scene graph.

unshaded_color_01.hiplc
Using a mtlxuniform_edf and a render geometry settings node to render an unshaded color material

Materials

Read more about material assignment in lops cgwiki. Below is a hip file where I try out varius ways of editing material attributes in lops.

lop_assign_material_01.hiplc
setting materials in lops using attributes from sops