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

 name aiRange1
 input space_transform
 output_min 0.5

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

 name read_N_AOV
 aov_name "N"

 name defaultArnoldRenderOptions/aov_write_rgb_Ntangent
 aov_input aiRange1
 aov_name "Ntangent"

Denoising AOVs with the Optix imager

The Optix imager can denoise the beauty and any other AOV.

The so-called layer selection tells the imager what AOVs to denoise. For example, if you want to denoise both the beauty and the coat AOVs, enter RGBA or coat in the Layer Selection text box.

Using AOV names with or is an easy way to select multiple AOVs.

You can also use wildcard characters (such as *, ., and []) to select AOVs (this is what is called glob in the docs). For example:

*Selects all AOVs
RGBA_*Selects all light group AOVs for the beauty (for example, RGBA_default, RGBA_key, and so on)
RGBA_light0[135]Selects RGBA_light01, RGBA_light03, and RGBA_light05
RGBA_light0.The period (.) matches any single character, so this selects RGBA_light00 through to RGBA_light09.
RGBA_light0[1-9] does the same thing.

You can even use regular expressions for more complicated selections. But in general, using or and wildcards should be more than enough.

[MAXtoA] Denoising AOVs with noice

First, set up your AOVs like this:

Then run noice like this:

set IMAGES="C:\Users\Stephen Blair\Documents\3ds Max 2020\renderoutput\denoiseme"

set ARNOLD_BIN=S:\solidangle\arnold\Arnold-\bin

%ARNOLD_BIN%\noice ^
-ef 2 -sr 2 -pr 2 -v 0.5 ^
-i %IMAGES%/AOVs0003.exr ^
-i %IMAGES%/variance0003.exr ^
-l diffuse ^
-l specular ^
-o %IMAGES%/denoised_AOVs0003.exr 

The AOVs and variance AOVs are in separate EXRs
That’s necessary to be able to have different filters for the same AOV in MAXtoA

Tip: In the Windows command prompt, you can use ^ (Shift + 6) character to indicate line continuation, and break long commands into multiple lines. You can also use ^ in in a batch file.

Remapping paths at render time!

New with Arnold 6.0.4 is path mapping.

All you have to do is create a json file that looks something like this:

         "windows": { "S:/": "\\server\projects\" },
         "mac": { "S:/": "/Volumes/projects/"},
         "linux": {"S:/": "/mnt/projects/"}

and then set ARNOLD_PATHMAP to point to the json path mapping file

Read more about path mapping here…


[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 [991b08e9] windows icc-17.0.2 oiio-2.2.1 osl-1.11.0 vdb-4.0.0 clm- rlm-12.4.2 optix-6.7.0 2020/04/17 09:11:12
### host app: MAXtoA (2021) 3ds Max 23.0.915.2021 

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

 name /gBufID_Switch
 index /gBufID
 input1 1 0 0 1
 input2 0 1 0 1
 input3 0 0 1 1

 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'

Auto-instancing in Arnold 6.0.2

Controllable auto-instancing on ASS procedurals: You can now disable the default automatic instantiation of procedurals pointing at the same ASS file with the auto_instancing parameter on each procedural or by the procedural_auto_instancing option. This workaround is sometimes useful when overriding procedural parameters with operators.

Arnold 6.0.2 release notes https://docs.arnoldrenderer.com/x/1gGvBg

So, what’s all that mean?

It means that if you load the same ass file many times, Arnold will load the ass file just one time, and then automatically create instances of that. For example, if I load an ass file three times, I will get two instances.

In previous versions, this was known as the procedural cache, and it was a global option. Now it’s called auto_instancing and you can set it on each procedural node (aka aiStandin in Maya).

In general, you want auto instancing, because instancing is more efficient than loading the same ass file over and over. But if you’re using operators to apply different looks to the same procedural, you need to turn off auto instancing. Otherwise all the procedurals will have the same look (because they all be instances of the same one procedural).

For example, with auto instancing on, I get this, even though I’ve assigned different looks to each procedural (standin):

Everything has the same look with auto instancing on

I can also tell from the Arnold log that I’m getting instances. Note that 2 are reused

| ---------------------------------------------------------
| ass file cache           
|   unique (loaded from disk)              1 (33.33%) 
|   reused (found in cache)                2 (66.67%) 
|   total referenced .ass files            3 (100.00%) 
| ---------------------------------------------------------

If I turn off auto instancing (in the procedural parameters)

then I get three different looks

In the Arnold log, that looks like this (0 reused means 0 instances)

| ---------------------------------------------------------
| ass file cache
| unique (loaded from disk) 1 (100.00%)
| reused (found in cache) 0 (0.00%)
| total referenced .ass files 1 (100.00%)
| ---------------------------------------------------------

Updating texture paths with the string_replace operator

Arnold 6.0.2 includes a new string_replace that lets you do find and replace on string parameters.

For example, I got an ass procedural file from a user, but I didn’t get the textures. Normally I would just enable ignore textures, but this time I used string_replace to replace all textures with my trusty-old-Softimage noicon pic.

string_replace operator in MtoA (Maya)
  • Selection selects all Arnold image nodes. So this string replace operation applies to all string parameters of the image node (which includes name, uvset, color_space as well as filename).
  • Match is a regular expression that matches anything that looks like C:/project/sourceimages/example.tx or X:/temp/test/example.tx
    • [A-Z] matches any drive letter from A to Z
    • .* matches any string of characters
    • Note that match is a regular expression, so you cannot use glob wildcards like this: C:\sourceimages\*.tx (because * is not any string of characters, it is zero or more occurrences of the previous character)
    • \.tx matches a period followed by “tx”. The period has to be escaped with a backslash because ‘.’ matches any single character
    • Note that this match expression won’t handle something like example.txtra.tx
  • Replace is the string that replaces anything matched by the Match expression.