Vertices and the maximum valence limit

The valence of a vertex is the number of edges connected to that vertex. In Arnold, the maximum valence is 255 (that’s because of the data type we use to store the valence; we minimize the memory requirements since this is stored per-vertex).

If a mesh in the scene has a vertex with more than 255 edges, you’ll get a WARNING like this:

 [polymesh] example_mesh: mesh has at least a vertex with valence higher than 255, disabling subdivision

But if the adaptive subdivision results in a vertex with too many edges, you’ll get an ERROR:

 ERROR: [arnold] [subdiv] example_mesh: edge (144578,287741) in face 263433 has a vertex that exceeded the max valence limit of 255 

Sampling after the first bounce

With the default Diffuse = 2 sampling, you’ll get four diffuse rays for each camera ray. Those four diffuse rays are the first bounce after the camera ray “hits” a shape.


After the first bounce, Arnold sets all the sampling settings back to 1, so for each of those four diffuse rays, you get one second-bounce diffuse ray. This prevents an exponential explosion of rays as secondary rays like diffuse rays bounce around a scene.


The same thing is true for the other secondary rays such as glossy, refraction, and shadow rays.

So, in summary:

  • For a camera ray you can get multiple secondary rays (for example, multiple diffuse rays or multiple glossy rays, and for light sampling, multiple shadow rays)
  • But for a secondary ray, you’ll get just one ray. For example: one diffuse ray, one glossy ray (if any), one shadow ray, and so on.

Overriding shader parameters in procedurals

Procedurals (aka standins) don’t expose the parameters of objects and shaders inside the procedural.

For example, you cannot override shader parameters like standard.Kd (diffuse color) or standard.emission (emission scale) by setting those parameters on a procedural node.

But what you can do is use “user data parameters”. Inside the procedural, use user data shaders to set shader parameters, but don’t define the user data parameters on the shape.

For example, if I wanted to be able to override the emission scale, then I would set up a shader like this:


A userDataFloat shader sets the Emission. The important thing is that the custom attribute emission_scale is not defined on the shape, so the default value is used instead.

By doing that, I can put an emission_scale attribute on the procedural node, and the aiUserDataFloat shader picks up that value.


In the above example, I’ve added a mtoa_constant_emission_scale attribute to the standinShape, and that allows me to set the Emission for that specific standin.

In Arnold scene source (ASS) format, I have this in my main scene file:

 name ArnoldStandIn1Shape
 dso "standin_torus_w_emission.ass"
 declare emission_scale constant FLOAT
 emission_scale 0.649999976

And in the ASS file loaded by the procedural, I have this:

 name pTorusShape1
 shader "someshader"

 name someshader
 emission aiUserDataFloat1
 # NO user data declared here

 name aiUserDataFloat1
 floatAttrName "emission_scale"
 defaultValue 0.100000001


[MtoA] Hiding the image file statistics in the Arnold log

Here’s a good example of why you might use the User Options, and how it lets you set Arnold parameters that aren’t exposed by MtoA in Maya.

If you set the verbosity level to Warnings + Info, you’ll get some detailed image statistics in the Arnold log:


But what if you’ve got thousands of image files (eg udims)? You might not want all that in your log. There used to be a check box in the Arnold Render Settings that allowed you to turn off the detailed image file statistics, but we removed that a few years ago.

But the Arnold options.texture_per_file_stats parameter is still there, so you can use the User Options field to set that parameter to false. Just enter the parameter name “texture_per_file_stats” and the parameter value, like this:


Updating MtoA with Arnold

MtoA ships with Arnold 4.2.13.

If you want to take advantage of the improvements in Arnold (like the increase  in the maximum number of threads from 128 to 256), here’s what you need to do:

  • Download  Arnold and extract the archive
  • Replace Arnold (, ai.dll, libai.dylib), kick, and maketx in the MtoA bin folder with the versions from the Arnold download
  • Replace the Arnold Python bindings in  the MtoA scripts/arnold folder with the Python bindings from the Arnold python/arnold folder. For example, replace this folder:

    with the python\arnold folder from the Arnold download. For example:


You must update the Arnold Python bindings, otherwise MtoA won’t load. That’s because Arnold included a number of API changes, including the removal of some API (like AiLicenseSetServer). The older Python bindings still refer to the removed API, so there will be Python errors that prevent MtoA from loading.

[Arnold] Understanding the texture cache

Arnold uses the OpenImageIO texture cache. From the OIIO Programmer Documentation:

In short, if you have an application that will need to read pixels from many large image files, you can rely on ImageCache to manage all the resources for you. It is reasonable to access thousands of image files totalling hundreds of GB of pixels, efficiently and using a memory footprint on the order of 50 MB.

So, if you’re using tx files (tiled and mipmapped textures), then Arnold can read tiles as required, and use the texture cache to keep memory usage under control.

The reason we don’t read all the textures at once is that many of our customers have (literally) 100+GB of textures, so we use a texture cache that constantly loads small bits of texture data as required, and unloads old data.

By default, the size of the texture cache is 2048KB (as of Arnold The size of the texture cache is set in the Arnold Render Settings.

Max Cache Size
The maximum amount of memory to be used for texture caching. Arnold uses a tile-based cache with a LRU (Least Recently Used) type algorithm, where the least recently used tiles are discarded when the texture caches is full.

Note If we get an error reading a texture, we mark that texture as bad and we never try to read it again. This makes the renderer a lot faster when you have a missing texture, since we won’t ask the file server millions of times to read from a nonexistent file. But in a transient network error case, one bad experience and the rest of your render has the texture missing.

[MtoA] Switching between multiple versions of MtoA


If, like me, you need to switch between different versions of MtoA, here’s a recipe for setting that up.

First, you have to install multiple versions. As you probably already know, the MtoA installer always wants to uninstall first. I take care of that by zapping the Uninstall registry entry with this command:

reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\MtoA2016" /f

Then I run the MtoA installer and install in a folder with the version name, like this:

I start Maya with a batch file that creates a symbolic link named “C:\solidangle\mtoadeploy\2016” that links to the version of MtoA I want to use:

rmdir C:\solidangle\mtoadeploy\2016
mklink /D C:\solidangle\mtoadeploy\2016 C:\solidangle\mtoadeploy\2016-
rem mklink /D C:\solidangle\mtoadeploy\2016 C:\solidangle\mtoadeploy\2016-

set RLM_DEBUG=arnold
start "" "C:\Program Files\Autodesk\Maya2016\bin\maya.exe" %* -log %TEMP%\maya.log

My batch file also adds the location of my custom mtoa.mod to MAYA_MODULE_PATH. My custom mtoa.mod points to “C:\solidangle\mtoadeploy\2016”, and handles all versions of Maya:

+ MAYAVERSION:2016 mtoa any C:\solidangle\mtoadeploy\2016
PATH +:= bin
+ MAYAVERSION:2015 mtoa any C:\solidangle\mtoadeploy\2015
PATH +:= bin
+ MAYAVERSION:2014 mtoa any C:\solidangle\mtoadeploy\2014
PATH +:= bin
+ MAYAVERSION:2013 mtoa any C:\solidangle\mtoadeploy\2013
PATH +:= bin