How to get a list of AOVs and LPEs


Here’s a simple kick trick to get a list of AOVs and LPEs.

The -laovs flag lists all the AOVs in the loaded scene, but if you give kick no input, you’ll get a list of all built-in AOVs defined by Arnold.

For example, on Windows, run kick -laovs -i Nul

On Linux or macOS, run kick -laovs -i /dev/null

kick -laovs -i Nul
Available aovs:
    Type:    Name:                        LPE:
    --------------------------------------------------------------
    VECTOR2  motionvector (~)
    RGBA     RGBA                         C.*
    VECTOR   N (~)
    FLOAT    Z (~)
    RGB      direct                       C[DSV]L
    RGB      indirect                     C[DSV][DSVOB].*
    VECTOR   Pref (~)
    RGB      albedo                       C[DSV]A
    RGB      emission                     C[LO]
    RGB      diffuse_direct               C<RD>L
    RGB      background                   CB
    RGB      denoise_albedo               ((C<TD>A)|(CVA)|(C<RD>A))
    RGB      sss_albedo                   C<TD>A
    RGB      specular_albedo              C<RS[^'coat''sheen']>A
    RGB      diffuse                      C<RD>.*
    FLOAT    cputime (~)
    RGB      diffuse_indirect             C<RD>[DSVOB].*
    RGB      sss_indirect                 C<TD>[DSVOB].*
    RGB      diffuse_albedo               C<RD>A
    RGBA     shadow_matte
    FLOAT    volume_Z (~)
    RGB      specular                     C<RS[^'coat''sheen']>.*
    RGB      coat_direct                  C<RS'coat'>L
    RGB      specular_direct              C<RS[^'coat''sheen']>L
    RGB      specular_indirect            C<RS[^'coat''sheen']>[DSVOB].*
    RGB      volume_direct                CVL
    RGB      coat                         C<RS'coat'>.*
    RGB      coat_indirect                C<RS'coat'>[DSVOB].*
    RGB      coat_albedo                  C<RS'coat'>A
    RGB      sheen                        C<RS'sheen'>.*
    RGB      transmission                 C<TS>.*
    RGB      transmission_direct          C<TS>L
    RGB      transmission_indirect        C<TS>[DSVOB].*
    VECTOR2  AA_offset (~)
    RGB      transmission_albedo          C<TS>A
    VECTOR   P (~)
    RGB      sheen_direct                 C<RS'sheen'>L
    RGB      volume                       CV.*
    RGB      sheen_indirect               C<RS'sheen'>[DSVOB].*
    NODE     shader (~)
    RGB      sheen_albedo                 C<RS'sheen'>A
    RGB      sss                          C<TD>.*
    RGB      sss_direct                   C<TD>L
    RGB      volume_indirect              CV[DSVOB].*
    RGB      volume_albedo                CVA
    FLOAT    A (~)
    FLOAT    ZBack (~)
    RGB      opacity (~)
    RGB      volume_opacity (~)
    FLOAT    raycount (~)
    UINT     ID (~)
    NODE     object (~)
    FLOAT    AA_inv_density (~)
    RGBA     RGBA_denoise (~)
    --------------------------------------------------------------
    (~) No opacity blending

Kicking Bifrost ASS


You can export a Bifrost scene to an Arnold ass file and then render it with kick.

Just use the -l flag (or the ARNOLD_PLUGIN_PATH environment variable) to point to the Arnold plugins that comes with the Bifrost install. For example, on Windows:

kick -v 5 -dp bifrost_aeroColors.ass 
-l "C:\Program Files\Autodesk\Bifrost\Maya2020\2.2.0.2\bifrost\arnold-6.2.0.0"
kick render of a Bifrost graph

In the Arnold log, we see that Arnold loads the procedural nodes for Bifrost:

00:00:00 88MB | loading plugins from C:\Program Files\Autodesk\Bifrost\Maya2020\2.2.0.2\bifrost\arnold-6.2.0.0 …
00:00:00 100MB | arnold_bifrost.dll: bifrost_graph uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_object uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_multires_volume uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_multires_implicit uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_volume uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_points uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_implicit uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_polymesh uses Arnold 6.2.0.0
00:00:00 100MB | arnold_bifrost.dll: bifrost_blocks uses Arnold 6.2.0.0
00:00:00 100MB | loaded 9 plugins from 1 lib(s) in 0:00.06

In other applications, like CINEMA 4D or Houdini or Katana, you can do the same thing by setting the Plugin Search Path.

Tangent space normal maps


The built-in N AOV is in world space. So how to get a tangent-space N AOV?
Like this:

In brief, I read the N AOV, transform the normals from world to tangent space, and then map the normal values to the range 0.5, 1 (I used the range node here, but I could have used Add and Multiply to do the same thing).

Here’s the shader tree. You can save this in a .ass file and import it into Maya or whatever application you use. Then set up an AOV shader to write the custom Ntangent AOV

range
{
 name aiRange1
 input space_transform
 output_min 0.5
}

space_transform
{
 name space_transform
 input read_N_AOV
 type "normal"
 to "tangent"
 tangent 1 0 0
 normal 0 1 0
 normalize on
}

aov_read_rgb
{
 name read_N_AOV
 aov_name "N"
}

aov_write_rgb
{
 name defaultArnoldRenderOptions/aov_write_rgb_Ntangent
 aov_input aiRange1
 aov_name "Ntangent"
}

[MAXtoA] Setting up an Object ID AOV


Here’s how to use the 3ds Max object ids for a simple Object ID AOV.

And here’s the material (aka shader tree) that writes the AOV. Use a text editor to save this as Arnold Scene Source (.ass) file, and then import it into 3ds Max (like I did in the video).

An ASS file is a plain-text file.

### exported: Thu May 21 07:53:19 2020
### from:     Arnold 6.0.3.0 [991b08e9] windows icc-17.0.2 oiio-2.2.1 osl-1.11.0 vdb-4.0.0 clm-1.1.1.118 rlm-12.4.2 optix-6.7.0 2020/04/17 09:11:12
### host app: MAXtoA 4.0.4.36 (2021) 3ds Max 23.0.915.2021 

aov_write_rgb
{
 name /Write_Object_ID_AOV
 aov_input /gBufID_Switch
 aov_name "object_id"
 declare nodeName constant STRING
 nodeName "Material #43"
}

switch_rgba
{
 name /gBufID_Switch
 index /gBufID
 input1 1 0 0 1
 input2 0 1 0 1
 input3 0 0 1 1
}

user_data_int
{
 name /gBufID
 attribute "gBufID"
}

Updating procedural file paths with string_replace


This is actually pretty cool…you can use an operator to update file paths before an ASS file or ABC file is loaded, then use another operator to touch the geometry loaded by that procedural.

For example, suppose at render time you want to replace trex_proxy.abc with trex.abc. You can easily do that with a string replace operator:

  • *.(@node==’alembic’) selects all Alembic procedural nodes
  • Match matches any file name that ends with “_proxy.abc”
  • Replace replaces “_proxy.abc” with “.abc”

And that all happens before the abc file is loaded.

We can see this in the Arnold log (Debug verbosity). First the string replace operator is applied; then after the abc file is loaded, a set parameter operator is applied to the nodes loaded from the abc file.

| initializing 16 nodes …
| [operators] init op: 'aiStringReplace1'
| [operators] cook op: 'aiStringReplace1' | node: '/aiStandIn/aiStandInShape'
| [proc] /aiStandIn/aiStandInShape: loaded 1 nodes (1 objects, 0 shaders)
| [operators] init op: 'TRex:tRexShape_aiSetParameter1'
| [operators] cook op: 'TRex:tRexShape_aiSetParameter1' | node: '/TRex:tRex/TRex:tRexShape'

How to use wireframe shader for alpha


You can use the wireframe shader to drive the opacity of a standard_surface.

The wireframe shader itself doesn’t support opacity, and neither do the flat, utility, and ambient_occlusion shaders. They are all color shaders (RGB). In Arnold, only shaders that return closures can support opacity.

In the more general case, where the opacity isn’t coming from the same shader, you can use the emission for the color:

The case of Maya and the missing ProductInformation.pit file


One of the strange thing about supporting Arnold at Autodesk is that you have to be a guru-level licensing expert on Autodesk licensing (not RLM, but Autodesk licensing).

In this case, Maya 2019 would silently fail at startup. Sometimes you’d see the splash screen, but then that would just disappear.

  • There was nothing in the Adlm.log
  • No MayaAdlm log was created
  • The MayaCLM log had only this:
    ERROR: checkoutLicense: Failed to authorize license
  • The clm log did have this:
    JsProductLicenseFact.loadSelectedProductInfoKey - Unable to get selected product key due to unknown problem.

TIP All these log files are in the Temp folder.

  • On Windows, look in %LOCALAPPDATA%\Autodesk\Logs
  • On OSX, look in $TMPDIR
  • On Linux, look in /var/tmp

Process Monitor confirmed that the ProductInformation.pit file was missing:

ProductInformation.pit is an all-important file used by the licensing infrastructure. Every Autodesk product must be registered in that pit file.

If ProductInformation.pit is missing, or corrupted, then everything stops working.

[macOS] Rendering xgen procedurals in another app


Or: how to fix the node xgen_procedural” is not installed problem.

For example, suppose you want to render XGen hair in CINEMA 4D on macOS.

  • From MtoA, export your XGen hair to an ass file.
  • Set DYLD_LIBRARY_PATH before you start your application (for example, open a Terminal, set DYLD_LIBRARY_PATH there, and start CINEMA 4D the command line)
    export DYLD_LIBRARY_PATH=/Applications/Autodesk/maya2018/plug-ins/xgen/lib:/Applications/Autodesk/maya2018/Maya.app/Contents/MacOS
  • Load the ass file into CINEMA 4D with an Arnold Procedural.
  • Set the Plugin Search Path to the MtoA procedurals folder