Create a ticket

Q100170: Handling Textures in Katana


Textures are handled in a variety of different ways by shader libraries and studio pipelines and Katana offers a flexible framework to assign textures, following some common conventions. 

Below is a summary of some of these options to work with both Arnold and RenderMan. Please also see the attached example scene that demonstrates both approaches explained here.



Using material attributes to declare textures

The simplest way to give each object its own texture is to create a material per object and explicitly declare the textures as string parameters in the shader. Each object is then assigned the relevant material.

This approach is the most labour-intensive, especially when working with a scene that contains a large number of objects, and lacks flexibility when changes to a material have to be made.

Often many objects can share the same material, but need to be assigned different textures. In this case it is possible to set up the scene so that each object picks up its own textures:


Using object attributes to declare textures

Rather than setting the texture on the material, the objects to be rendered can point to the relevant texture file via an arbitrary attribute.

RenderMan primvars

When using RenderMan, the texture file can be passed to the renderer as a RenderMan primvar.

In Katana any string attribute called is automatically written out to RenderMan as a primvar called xxx. If your shader has a string parameter of the same name, RenderMan will use the value of the primvar passed to it from the geometry to set this shader parameter at rendertime.

If your texture's name is contained in an arbitrary attribute on the geometry, you can use an OpScript to set these attributes in the format that will be recognised by RenderMan.

To set up an example scene using RenderMan primvars, do the following:

  1. Add a CameraCreate and two Pony nodes by clicking Help > I want a pony. Make sure you name the ponies.
  2. Use AttributeSet nodes to create an attribute ‘geometry.arbitrary.texFile’. Set it to ‘flag_uk.tx’ on one of the ponies and ‘flag_usa.tx’ on the other.
  3. Merge all nodes using a Merge node.
  4. Create a Material and add an RMSGPSurface Shader to it.
  5. Assign the Material to root/world/geo//* using a MaterialAssign node.
  6. Add a GafferThree node with a PxrStdAreaLight.
  7. Now create the OpScript node that will handle the textures.
    - Apply it at a Custom CEL location: /root/world/geo//*. This means the OpScript will be applied recursively on all objects beneath geo.
    - Add a user parameter named texturePath and set the value to where the textures for the demos included with Katana are stored, for example
    /opt/Foundry/Katana2.5v3/demos/tx_files/ on Linux or
    C:/Program Files/Katana2.5v3/demos/tx_files/ on Windows
    - Add the following lua code:
    local texPath = Interface.GetOpArg('user.texturePath')
    local fileName = Interface.GetAttr('geometry.arbitrary.texFile')
    local filePath = (texPath:getValue() .. fileName:getValue())

    Interface.SetAttr('textures.SurfaceMap', StringAttribute(filePath))

  8. Render this and you will see that each of the ponies is assigned the texture specified by geometry.arbitrary.texFile.

To see the parameter's internal name in Katana, like in this case SurfaceMap, you can middle-mouse drag it into the Script Editor's text field. The resulting command will tell you which name to use for the attribute.

To get more information on how to add a tag containing the name or file path of the texture to geometry.arbitrary, please refer to the Katana Online Help on Using Pipeline Data to Set Textures.

{attr:xxx} syntax for shader parameters

Another option, which will work with both Arnold and Renderman, is to use the {attr:xxx} syntax for shader parameters. This works by setting any parameter of the material to, for example, {attr:tex.SurfaceMap} when you create the material.

At rendertime, the renderer will look for an attribute called tex.SurfaceMap on the geometry to be rendered. The shader parameter will then be set to the value that is read from the geometry attribute. ​

For this approach, set the scene up just like described in the example above, but add {attr:tex.SurfaceMap} as the value of the Surface Map parameter (not textures. to show that we are not using primvars), and change the last line of the OpScript code to

Interface.SetAttr('tex.SurfaceMap', StringAttribute(filePath))

For more information please see the "Texture Handling - Overview" example project and the Texture Handling Options section of the Katana Online Help.

Was this article helpful?

We're sorry to hear that

Please tell us why
2 out of 5 found this helpful