Enhancements
- Non-Photorealistic Rendering: a non-photorealistic rendering (NPR) solution is provided as the combination of the
contour
filter andtoon
shader. Thecontour
filter draws contour lines using the information provided by thetoon
shader and it works even for reflected or refracted objects. Thetoon
shader can be used to obtain a cell animation look. A variety of interesting effects can be achieved by, for example, changing the line width using theedge_width_scale
parameter, connecting a procedural texture tomask_color
, or using stylized highlights. (#5591, #6848) - Adaptive sampling: Arnold now has the capability of adapting the sampling rate of each pixel when the
enable_adaptive_sampling
render option is enabled, allowing it to dedicate a greater number of camera samples (and thus also a greater amount of render time) to the pixels that show a greater variation in their sample values. When used, all pixels will receive a sampling rate of at leastAA_samples
, but no more thanAA_samples_max
. The adaptive sampler's sensitivity to noise may be controlled through theAA_adaptive_threshold
render option, where lower threshold values will apply higher sampling rates to a greater number of pixels. The-asmax
command-line option has been added tokick
as well. (#3165, #6090, #6686, #6883) - Denoiser (
noice
): a stand-alone, post-process denoiser executable callednoice
is now bundled with Arnold. This is a high-quality denoiser that takes into account multiple frames and multiple light AOVs. It requires variance information for all AOVs and optionally uses normal, depth and albedo. (#6322) - Denoiser (OptiX): the fast, GPU-powered Nvidia OptiX AI denoiser is now available in Arnold as a filter called
denoise_optix_filter
(#6513). Note that it is not available on OSX. This filter has one parameterblend
which is a float and controls the linear interpolation between the denoised and original pixel values. The filter can be applied to an output just like other filters, with the following limitations:- The filter must be unique for each output it is applied to. Meaning that you must create a new OptiX denoise filter for each output you wish it to be applied to.
- The filter will only work with single-channel EXR images.
- Outputs with the OptiX denoise filter applied will be received by the driver later than the outputs without. As the OptiX denoiser works on full frame images,
driver_prepare_bucket
anddriver_process_bucket
will be called again after the full frame has completed providing bucket data for only the denoised output. - If you want to render the same AOV with and without the OptiX denoise filter, we have added a feature to allow you to do so and avoid AOV name conflicts. You can add the suffix
_denoise
onto the end of an AOV name and the filter will source the name from the original AOV. For example if we wanted to apply the OptiX denoise filter to the RGBA AOV, but already had an RGBA AOV added to the outputs, we could add an AOV namedRGBA_denoise
and the OptiX denoise filter will source the RGBA AOV as the input.
- Alembic procedural: a procedural node called
alembic
which is capable of reading Alembic .abc files has been added. It resides in an external dynamic library that is by default located in the "plugins" directory of the Arnold core package. (#6547) - Automatic loading of plugins from Arnold installation: Arnold looks for a directory "../plugins" relative to where the core shared library is installed and automatically loads procedurals, shaders, etc from that location. This is also the default location of the newly introduced Alembic procedural. (#6808)
- Operators: Operators are a new node type which perform per-object (node) parameter assignments and overrides, including late-bindings and deferred overrides on procedurally generated nodes. Operators can also create nodes and carry out general scene inspection and modifications. Operators can be chained together in a graph which is evaluated from a given target operator, set using
AiOpSetTarget(node)
orkick -op node_name
. Multiple disconnected operator graphs can exist in the scene, where only the graph connected to the target operator will be evaluated for rendering. Operators can be ignored by settingoptions.ignore_operators
to true or usingkick -iops
. Some operators provide a selection parameter which determines, using a wildcard expression, what nodes are processed by the operator. A series of operator nodes are now available:materialx
,set_parameter
,disable
,collection
,switch_operator
, andset_transform
. (#6209, #6210, #6530, #6606, #6662, #6699, #6676, #6700, #6701, #6878) - More efficient texture mapping: the performance of certain types of texture lookups, including opacity masks, skydome_lights, and certain kinds of specular and diffuse rays has been optimized. (#6387, #6391, #6480, #6603)
- Faster scene initialization: scene initialization and update can be much faster as they are now performed in parallel by default. Multiple threading issues were fixed that also make the scene initialization code more stable. Finally, procedural contents are initialized asynchronously, in parallel with the rest of the nodes, to make full use of all available threads. In the case of interference with non-threadsafe scene construction techniques involving custom procedurals, parallel initialization can be manually disabled by setting
options.parallel_node_init
to false. (#5724, #5406, #6744) - Difference filter: an auxiliary
diff_filter
for denoising that measures AOV variance has been added. (#6462) - EXR metadata for AOVs: additional metadata tags (filter, filter width, LPE, original AOV source) have been added to describe output AOVs. (#6461)
- Matte shader opacity: the
matte
shader has gained an opacity parameter, so it can honor transparency the same way the built-inmatte
object parameter does. (#6415) - Per-lightgroup shadow mattes: The
shadow_matte
shader has a newaov_group
parameter that when enabled makes the shader sensitive only to lights with a matchingaov
setting. (#6609) - Trace sets in ambient occlusion shader: the
ambient_occlusion
shader now supports thetrace_set
parameter to specify which objects are included or excluded. (#6602) extra_samples
in hair shader: thestandard_hair
shader now supports theextra_samples
parameter to use additional GI samples on a per-shader basis. (#6443)- Improved uniformity in hair shader: like the classic
hair
shader, thestandard_hair
shader will now display a uniform result over a strand's cross-section, which can reduce sampling noise. (#6444) image
tile tags optional offset: the<tile>
tag in theimage
shader'sfilename
now accepts an optional tile offset, instead of being hard-coded to one, e.g.<tile:0>
is now possible. (#6429)- New wrap mode in
image
shader: similar to the preexistingblack
wrap mode, there is now amissing
wrap mode where lookups to theimage
shader that are outside the texture will use themissing_texture_color
. (#6430) - ID AOVs in
standard_surface
andstandard_hair
: thestandard_surface
andstandard_hair
shaders now support ID AOVs. These are useful for creating mattes. (#6693) - Face mode option in
color_jitter
: with the newface_mode
option, color can be randomized per quadrangle as well as triangle. (#6495) - Reference positions from
rgb
/rgba
array: procedural texture shaders (noise
,flakes
triplanar
, andcar_paint
) can now read reference positions (Pref
) from anrgb
orrgba
array as well as avector
array. (#6729) - Arbitrary name for reference positions: users now can specify the name of the reference position user-data array in procedural texture shaders such as
noise
. Previously, the name was hard-coded as "Pref", which is still the default. (#6709). - New AOV-write shader: an
aov_write_rgba
shader has been added which complements the existingrgb
,float
andint
variations of this shader. (#6639) - Layer shaders: the newly added
layer_float
andlayer_shader
shaders can be used to mix float values and closures respectively.layer_rgba
allows to composite textures. The maximum number of layers in these shaders is limited to 8. (#6549) normal
parameter inpassthrough
shader: thepassthrough
shader now has anormal
parameter that allows for the assignment of a normal or bump map that affects the entire network of shaders it is connected to. (#6435)- Self-intersection detection in OSL trace: OSL shaders can now more easily inspect the self-intersection status of probe rays via the "hitself" trace message like so:
getmessage("trace", "hitself", hit);
This function assigns a 1 or 0 to thehit
variable depending on whether the ray intersects the same object or not. (#6326) - Oren-Nayar transmission in OSL: the
translucent
closure in OSL, which is based on a back-facing Oren-Nayar shading effect, can now be fed a second parameter indicating the surface roughness in a similar fashion to theoren_nayar
closure. (#6424) ginstance
can overridestep size
:ginstance
nodes can now override thestep_size
parameter of volume containers such as points, polymeshes, cubes and spheres. This allows for example an instance of a volume shape to be shaded as a surface (by setting the instance step size to zero, opaque off, and using a surface shader). (#6627)- Less confusing stack traces: Arnold would often misleadingly print out
AiShaderGlobalsEdgeLength
orAiCreateAtStringData_private
in the call stack. These functions should no longer be displayed. (#6439) - Structured statistics: render statistics can now be output to JSON files at the end of each render pass, either appended to or overwriting an existing .json file. This is much easier for tools to inspect rather than attempt to parse out the raw-text statistics in the logs that were meant for human consumption. (#6108)
- Better time statistics: additional timing statistics, organized by both nodes and categories, will now be output. This makes it possible to know which objects are most expensive to render and what parts of the renderer took the most amount of time. Detailed information about rendering performance can be output to a file in JSON format, such as "my_profile.json", by calling
AiProfileSetFileName("my_profile.json")
orkick -profile "my_profile.json"
, and then visualized in Google's Chrome web browser "chrome://tracing/". (#5106) - Frame and fps global options: current frame and frames per second attributes have been added to options as
options.frame
andoptions.fps
. This information will also be exported to rendered images as EXR metadata. (#6474) lmutil
: a licensing tool calledlmutil
, which can be used to diagnose and solve certain FlexNet/AdLM/Clic licensing issues, is now distributed in the Arnold core package. (#6528)- Progressive refinement (EXPERIMENTAL): a new rendering mode that completes a render call in multiple passes has been added to Arnold. During each of the intermediate passes, drivers that do not output to a file will be invoked after each tile has completed, which allows for display drivers to show a result whose noise progressively converges towards the result at the final AA sample settings. This mode can be enabled through the
enable_progressive_render
render option (default:false
). Note that, in its current unoptimized state, this mode is not recommended for batch rendering at high AA samples, as the final passes can take very long to filter. This will be addressed in a future update. (#6146) - Node dependency graph (EXPERIMENTAL): a new node dependency graph allows tracking references between nodes, so that when a node is deleted or replaced, it can be automatically changed anywhere the node may have been referenced in the scene. It can be enabled using
options.enable_dependency_graph
. This is still a work in progress, so there are some unsupported cases, which will be addressed in a future release. (#6437)
API additions
- Shader compatibility: even though this is technically an API-breaking release, Arnold 5.0 shaders are still compatible with 5.1 and can continue to be used without being recompiled. (#6475)
- Render session type:
AiBegin()
has gained an argument specifying whether the session is for offline, batch rendering (AI_SESSION_BATCH
) or for interactive/IPR rendering (AI_SESSION_INTERACTIVE
). Arnold will perform certain optimizations during batch rendering because it expects nodes will not be modified after rendering, but which may leave the scene missing information. Interactive rendering will leave all information intact so that nodes may be edited as needed after rendering and re-rendered again. (#6234) - New render control API: Invoking a render now happens asynchronously through
AiRenderBegin()
. This takes an optional render update callback which will be called before and after each render pass and in which the scene may be modified for interactive rendering. During interactive rendering, only the main output will have pixels sent to, until the final pass where all outputs are activated. Rendering paused viaAiRenderInterrupt()
can be restarted withAiRenderRestart()
or restarted in the callback. And finally, when rendering is done or needs to wrap up,AiRenderEnd()
must be called. The current render status is obtained withAiRenderGetStatus()
. Please see the API documentation for more information on the new render control API. Note: the oldAiRender()
andAiRendering()
API functions are now deprecated. (#6234, #6226, #6542) - Structured statistics API: two functions have been added to set up output of render statistics to .json files,
AiStatsSetFileName(const char*)
andAiStatsSetMode(AtStatsMode)
to control JSON stats output. Two additional functions to get the filename and mode are also available. The two available modes are to output JSON and overwrite any existing data in the stats file, or to append additional render pass statistics and keep any previous stats in the file. (#6108) - Better time statistics API: user functions can also be profiled by calling
AiProfileBlock ("my label", my_AtNode);
at the start of a code block that needs to be timed. This can be called with just a string literal, just anAtNode
, or both. This profiler has low overhead, so is generally safe to use without incurring any noticeable slowdown. (#5106) - Device selection API: New APIs for selecting devices Arnold may use during the rendering process. Currently functionality for these APIs is only for selecting GPUs to use for denoising. See
ai_device
for full details (#6329, #6539, #6580, #6586, #6623, #6685, #6767)AiDeviceSelect
- Explicitly select which devices Arnold may use during the rendering process.AiDeviceAutoSelect
- Auto selected devices that can be used via the optionsdefault_gpu_names
anddefault_gpu_min_memory_MB
AiDeviceGetSelectedType
- Queries the currently selected render device type. Currently onlyAI_DEVICE_TYPE_CPU
AiDeviceGetSelectedIds
- Queries the currently selected device IDsAiDeviceGetCount
- Queries the number of devices by type (AI_DEVICE_TYPE_CPU
/AI_DEVICE_TYPE_GPU
)AiDeviceGetIds
- Queries valid device IDs by type (AI_DEVICE_TYPE_CPU
/AI_DEVICE_TYPE_GPU
)AiDeviceGetName
- Queries device nameAiDeviceGetMemoryMB
- Queries device memory information. (Total/Free/Used)
- AiNodeReplace: the new
AiNodeReplace
API function allows in-place substitution of a node, updating references from other nodes based on the new (experimental) dependency graph. So, for example, a shader can be replaced by another, automatically updating all nodes using the first shader. There are still some limitations. For example, instanced nodes are not yet supported. (#6466) - OSL support for writing to AOVs: OSL shaders may now write out to AOVs via
debug()
closures. (#5466) The syntax looks like this:shader surface_shader_osl(output closure color result = 0) { // The weight of the debug closure will be added to the DBG1 AOV
result = cellnoise(u * 10, v * 10) * diffuse(N) + color(0, 1, 1) * debug("DBG1"); }
Incompatible changes
- Removed
P
parameter intriplanar
: theP
parameter was broken and has therefore been removed. This parameter was provided to read reference positions exported as a color array by connectinguser_data_rgb
andrgb_to_vector
. This can now be done directly without these nodes. (#6264, #6709 #6729)
Bug fixes
- #6264 reference positions do not work in triplanar
- #6302 Clear up indirect node usage
- #6396 small bug fixes in car_paint
- #6402 zero-radius problem in random-walk SSS
- #6576 nurbs and polymesh common parameters not copied
- #6730 Fix bug in procedural name scope that was causing a race condition with parallel_node_init
- #6731 Fix race condition in overrides
- #6732 Fix bug in transformation of lights contained in procedurals when using parallel_node_init
- #6734 Normal map issue using strength parameter with back facing normals
- #6736 Artifact with intersecting object in polymesh-based volumes
- #6741 Fix race conditions in node name manipulation code
- #6752 tag with index but without default value crashes
- #6756 implement missing `bsdf_merge` for hair BCSDFs
- #6766 Python AtArray get and set functions crashing on error due to missing arguments
- #6777 AiNodeLookUpByName and AiNode crash with non-procedural parent
- #6799 Point and Vector functions in ai_matrix.py not returning correct type
- #6810 NaN in Zinke BCSDF
- #6837 high res opacity masks sometimes have incorrect regions
- #6872 kick -ar (aspect ratio) is broken
- #6652 AiMakeTx() fails with single channel input and DWAA compression
- #6738 Fix random crash with unnamed nodes#6791kick -ipr default value not working