Houdini 22.0 Solaris and Karma

Textures from attributes

Use texture paths from attributes in material networks.

On this page

Houdini’s Solaris provides several methods for applying textures. There are, for example, the Material Library LOP, the Material Linker LOP, or the Vary Material Assignment LOP. But did you know that you can also use attributes/primvars to assign a certain texture? To be precise: an attribute with a texture path will be added to the primitives of one or more objects. Then you create a MaterialX material where you read the attribute and feed an image node.

A typical use case for such an attribute is the creation of material variants. Let’s say you have several identical items and they should have materials with different diffuse, specular, and roughness maps. Instead of creating multiple separate materials, you can set up one material. The material network will then read the attribute and pass the different texture paths to the shader.

The objects on this image were created on the points of a Grid SOP and duplicated with a Copy to Points SOP. The Point attributes chapter of this guides explains the creation process.

You can also define geometry subsets and apply an attribute that specifies how certain polygons will be textured. The image below shows a cube with three different textures, but just one material. The texture paths are read from an attribute.

Example setup

The example works with a single object, but can be extended to an arbitrary number of items. For a better understanding, we’ll only focus on the relevant nodes here. UVs, names, and other properties aren’t discussed.

On the Solaris stage level, create a SOP Create LOP and double-click it to dive inside. There, create a basic primitive, for example a Box SOP.

Note that you can use any other available node to bring your geometry to Solaris, for example the SOP Import LOP. The basic workflow is the same, but the location of your SOP network will differ.

Attribute creation

There are numerous ways in Houdini to create attributes, and one solution is to use an Attribute Create SOP. The advantage with this node is that it’s very convenient to specify things like attribute name, class and type. The Attribute Create SOP is also a multi-parm node and you can create all necessary path definitions on the same node - unless you want to use groups.

Add the Attribute Create SOP and connect its input with the output of the box. Then, make the following settings.

  • Name is the name of the attribute, for example texturepath.

  • Class will be Primitive here to make the attribute work in Solaris.

  • Type is always String, because you're defining a file path.

  • String contains the full path of the texture file. You can use the $HIP variable and it’ll be replaced by Houdini automatically. A path could look as in this example: $HIP/textures/diffuse.jpg

Solaris

Leave the SOP network and return to the stage level. You should now see the box in the viewport and you're ready to create a material.

Inside a Material Library LOP, run the Karma Material Builder tool to create a subnet with a basic shader. We’ll only explain the workflow for the base_color input of the MtlX Standard Surface VOP. The steps for the MtlX Open PBR Surface VOP and other channels are the same.

  • Inside the karmamaterial subnet, add a MtlX Image VOP. Connect its out pin with the surface node’s base_color input. Don’t forget to choose the correct Signature.

  • Lay down a MtlX Geometry Property Uniform Value VOP and connect its out pin with the image node’s file input.

  • On the property node, go to the Geomprop parameter and enter the name of the attribute with the texture, for example texturepath. Now, Solaris will change the image node’s file content according to the string value from the attribute.

Material assignment

Assigning an attribute-driven material to an object works as usual and you don’t have to consider anything special. A fast and convenient method is to use the Material Library itself. On the Fill section, click Auto-fill Materials and turn on Assign to Geometry.

Geometry Path points to the primitives you want to use with the material. The path for the box in this example is /World/box/mesh0.

Now you can already start an interactive preview render in the viewport to see the results of your work. From the viewport’s first dropdown menu (set to Persp by default), choose one the Karma delegates, for example Karma XPU.

Point attributes

The previous example applied a primitive attribute to a single object, but there are situations where you create copies of an object, for example with scatter points. One solution is to create the attribute on the scatter points. However, there’s no straightforward way to randomize strings like file paths and in the end you also need a primitive attribute. Here’s a screenshot of the SOP network you’ll be creating. Again, we’ll only focus on the nodes that are required for the task.

In the following scene you’ll be randomizing an index that resembles texture numbers like diffuse_1, diffuse_2, and so on. A short VEX script will turn the random index values and into a texturepath attribute.

Again, everything happens inside a SOP Create LOP where you copy a Box SOP to the points of a Grid SOP.

Texture index

Add the Grid SOP and change its Size, Rows, and Columns parameters to 3.

Also, lay down an Attribute Create SOP and connect its input with the output of the grid. You only have to change two parameters:

  • For Name, enter index

  • From the Type dropdown menu, choose Integer

To shuffle the index values, add an Attribute Randomize SOP and connect its input with the output of the create node. Make the following settings:

  • For Attribute Name, enter index

  • On the Distribution tab, set Dimensions to 1

  • The Min Value and Max Value parameters define the indices of the textures, for example 1 and 5

  • On the Options tab, you can find a Global Seed parameter that lets you change the random distribution of the index numbers.

VEX script

The VEX script will live on an Attribute Wrangle SOP. Connect its first input with the output of the Attribute Randomize SOP. Then, use ⌃ Ctrl + C to copy the script below and paste it with ⌃ Ctrl + V to the wrangle’s VEXpression field.

The script uses two custom parameters where you can enter the texture path (without the index), and a file extension (without the dot). To add the parameters to the UI, press the Create spare parameters for each unique call of ch() button.

s@texturepath = chs("path")+itoa(i@index)+"."+chs("extension");

A typical example for Path is $HIP/textures/diffuse_, and for Extension you can enter jpg or exr.

The script creates a texturepath attribute from the parameters and the random index. Note that the itoa statement converts the integer into a string to make it usable with the other string components of the path.

Copies

To create copies of the box, add a Copy to Points SOP. Connect its first input with the output of the Box SOP, and link the second input with the output of the wrangle.

If you want, you can turn on the copy node’s Pack and Instance option. This option helps to save resources and the texturepath attribute will be kept.

To convert texturepath a primitive attribute, add an Attribute Promote SOP and make it the last node of your SOP network.

  • On the Original Name parameter, enter texturepath.

  • From the New Class dropdown menu, chose Primitive.

Now you can return to the stage and apply your material as described in the Solairs and Material assignment chapters.

Solaris and Karma

Solaris and USD

Karma

  • Karma

    Houdini’s Physically Based USD Renderer.

  • Karma XPU

    Houdini’s fast and modern XPU render engine.

  • Color management

    Learn more about OCIO, color spaces, gamma and tone mapping.

  • Render statistics

    How to view various statistics about the render process of an on-going render or rendered image.

Karma User Guide

Look Development

  • MaterialX

    Houdini has VOP node equivalents of the MaterialX shader nodes. You can build a shader network using these nodes, or import an existing MaterialX-based shader, and use them with Karma (Houdini’s USD renderer).

  • UDIM paths

    You can encode different tiles of a texture space into different texture files, each with its own resolution. You can then specify a texture filename such as kaiju.exr, and Houdini will replace the token with the specific tile address at load time.

  • Shader translation

    Describes the Solaris shading framework, including shader node translation to USD primitives.

  • Shotbuilder tools

    Multi-Shot Pipeline in a Box.

Procedurals

Supporting documents