Render a single frame in Maya with Arnold not working

Hey guys, anyone could help me explaning why these approaches are not working for render a single frame in arnold?
My goal is simple:

  1. render the given camera with the given resolution using arnold
  2. save it in .exr in a given path

Please if you can, take a loot at my attempts codes:

# WORKING:
cmds.setAttr("defaultRenderGlobals.currentRenderer", "arnold", type="string")

output_path = "C:\\Users\\joao\\Desktop\\apresentacao\\renders\\render4.exr"
cmds.setAttr("defaultRenderGlobals.imageFilePrefix", output_path, type="string")
cmds.setAttr("defaultRenderGlobals.imageFormat", 51)

cmds.setAttr("defaultResolution.width", 1920)
cmds.setAttr("defaultResolution.height", 1080)

cmds.setAttr("defaultArnoldDriver.aiTranslator", "exr", type="string")

# NOT WORKING (ATTEMPT 1): it doesnt generate a proper image file, because its not openable in any software
cam = "persp"
cmds.render(cam)

# NOT WORKING (ATTEMPT 2): it doesnt respect the correct camera name ("front in this case")
mel.eval('renderWindowRenderCamera render renderView "front";')
mel.eval('renderWindowEditor -edit -writeImage "C:\\qwe.exr" renderView;')

# NOT WORKING (ATTEMPT 3): it renders with arnold, but I couldnt find how to change the camera
mel.eval('renderSequence;')

thank you so much!
Joao

Before starting rendering, you must ensure that the current renderer is Arnold and ensure that Arnold is loaded correctly and configured correctly.
Below, I have provided the code for the function that serves the loading and configuration of Arnold.
In addition, it is advisable to check and disable IPR in the current Render View window.
And also check and cancel batchRender.

Arnold copies many of the parameter values for his attributes from the parameter values of the defaultRenderGlobals node.
This behavior is set by default, using the defaultArnoldRenderOptions.renderGlobals attribute.
Therefore, for many resulting parameters, it does not matter where they were set: in the defaultRenderGlobals node or in the defaultArnoldRenderOptions / defaultArnoldDriver nodes.
It is important to distinguish that Arnold has two different nodes with similar functions:
defaultArnoldDriver and defaultArnoldDisplayDriver !!!
Next: Camera resolution. You can change the parameters globally in the defaultResolution node.
And then, by default, rendering will occur with the parameters specified in the defaultResolution node.
Alternatively, you can specify render-only resolution values using the -height and -width flags in the arnoldRender command
Passing an absolute path to defaultRenderGlobals.imageFilePrefix is a VERY, VERY BAD IDEA!!!
Instead, change the path to the current project’s images folder (set to workspace).
You can manipulate workspace parameters using the workspace command of the same name.
If necessary, after rendering is complete, revert the previous value for the current project’s images folder path.

You may want to have some parameter values appended to the base filename.
For example: camera name, resolution, frame number, etc.
You can set/change Frame/Animation extension parameters using the attributes of the defaultRenderGlobals node:
To do this, you must first set the parameters for the animation and outFormatControl attributes:
cmds.setAttr('defaultRenderGlobals.animation', 1)
cmds.setAttr('defaultRenderGlobals.outFormatControl', 0)
After this, you can set how to build the extension.
For example, for name_####.ext:
cmds.setAttr('defaultRenderGlobals.putFrameBeforeExt', 1)
cmds.setAttr('defaultRenderGlobals.periodInExt', 2)
cmds.setAttr('defaultRenderGlobals.extensionPadding', 4)
You can see more details in the file:
C:\Program Files\Autodesk\Maya2024\scripts\others\setMayaSoftwareFrameExt.mel

You can still set/change parameters for Animation Range using the attributes of the defaultRenderGlobals node:
cmds.setAttr('defaultRenderGlobals.animationRange', 0)
cmds.setAttr('defaultRenderGlobals.startFrame', start_frame)
cmds.setAttr('defaultRenderGlobals.endFrame', end_frame)
cmds.setAttr('defaultRenderGlobals.byFrameStep', step_frame)

Well, the actual rendering needs to be done using the arnoldRender command.
For example:
cmds.arnoldRender(batch = True, camera = camera_name, height = 1920, width = 1080)

Other arnoldRender flags:
-ofn / -origFileName - String
-p / -port - UnsignedInt
-seq / -frameSequence - String
-srv / -saveToRenderView - String

Small demo:

import os
import maya.cmds as cmds


# Def for load and configure Arnold Renderer:
def load_and_configure_arnold_render():
    # Check that IPR and Batch is not running. Otherwise - cancel:
    try:
        cmds.arnoldRenderView(opt = ('Run IPR', 'False'))
    except:
        pass
    try:
        cmds.batchRender()
    except:
        pass
    if 'mtoa' in cmds.moduleInfo(listModules = True):
        if not cmds.pluginInfo('mtoa', query = True, loaded = True):
            print(('{0}{1}{2}{0}'
                  ).format('\n','\t', ' Loaded Arnold MtoA Plugin ...'))
            try:
                cmds.loadPlugin('mtoa', quiet = True)
                print(('{0}{1}{2}{0}'
                      ).format('\n', '\t',
                               ' Loaded Arnold MtoA Plugin - successful.'))
                from mtoa.core import createOptions
                if not cmds.objExists('defaultArnoldRenderOptions'):
                    print(('{0}{1}{2}{0}'
                          ).format('\n', '\t',
                                   ' Create Arnold Render Options ...'))
                    createOptions()
                    print(('{0}{1}{2}{0}'
                          ).format('\n', '\t',
                                   ' Create Arnold Render Options -' +
                                   ' successful.'))
                print(('{0}{1}{2}{0}'
                      ).format('\n', '\t',
                               ' Configure Arnold Render Options ...'))
                cmds.setAttr(
                    'defaultArnoldRenderOptions.render_device_fallback', 1)
                cmds.setAttr(
                    'defaultArnoldRenderOptions.renderDevice', 0)
                cmds.setAttr(
                    'defaultArnoldRenderOptions.abortOnError', 0)
                print(('{0}{1}{2}{0}'
                      ).format('\n', '\t',
                               ' Arnold Render Options configure -' +
                               ' successful.'))
            except Exception:
                print(('{0}{1}{2}{0}'
                      ).format('\n', '\t',
                               ' !!! Error loading Arnold MtoA Plugin !!!'))
                traceback_print_exc()
                return 0
            else:
                return 1
        else:
            try:
                print(('{}{}'
                      ).format('\t',
                               ' Create and configure Arnold Render Options ' +
                               '...'))
                from mtoa.core import createOptions
                createOptions()
                cmds.setAttr(
                    'defaultArnoldRenderOptions.render_device_fallback', 1)
                cmds.setAttr(
                    'defaultArnoldRenderOptions.renderDevice', 0)
                cmds.setAttr(
                    'defaultArnoldRenderOptions.abortOnError', 0)
                cmds.arnoldFlushCache(flushall = True)
                print(('{1}{2}{0}'
                      ).format('\n', '\t',
                               ' Arnold Render Options create and configure' +
                               ' - successful'))
            except Exception:
                print(('{0}{1}{2}{0}'
                      ).format('\n', '\t',
                               ' !!! Error Create and configure Arnold' +
                               ' Render Options !!!'))
                traceback_print_exc()
                return 0
            else:
                return 1
    else:
        print(('{0}{0}{1}{2}{0}{0}'
              ).format('\n', '\t',
                       ' !!! Arnold MtoA Plugin Not registred in this' +
                       ' MAYA_PLUG_IN_PATH !!!'))
        return 0


# Def for configure minimal Renderer options:
def prerender_settings(output_dir, image_base_name, camera_name, start_frame, end_frame, step_frame = 1, image_format = 'exr'):

    # Create output dir if not exists.
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    # Create output file name with camera name and resolution parametrs.
    output_file_base_name = ('{}__cam_{}_{}x{}_frame').format(image_base_name, camera_name, im_h, im_w)

    if load_and_configure_arnold_render():
        # Set "defaultArnoldRenderOptions" "renderGlobals" attribut from "defaultRenderGlobals" node attributes.
        cmds.setAttr('defaultArnoldRenderOptions.renderGlobals', 'defaultRenderGlobals', type = 'string')

        # Set "defaultArnoldDriver" attribut for output render file format ("exr").
        cmds.setAttr('defaultArnoldDriver.aiTranslator', image_format, type = 'string')
        cmds.setAttr('defaultArnoldDriver.outputMode', 2)
        cmds.setAttr('defaultArnoldDriver.exrCompression', 0)
        cmds.setAttr('defaultArnoldDriver.colorManagement', 2)

        # Set defaultRenderGlobals attributes for prefix (replace default render path)
        cmds.setAttr('defaultRenderGlobals.imageFilePrefix', output_file_base_name, type = 'string')
        cmds.setAttr('defaultRenderGlobals.useFrameExt', 1)
        cmds.setAttr('defaultRenderGlobals.useMayaFileName', 1)

        # Set defaultRenderGlobals attributes for naming with frame ext.
        cmds.setAttr('defaultRenderGlobals.animation', 1)
        cmds.setAttr('defaultRenderGlobals.outFormatControl', 0)
        cmds.setAttr('defaultRenderGlobals.putFrameBeforeExt', 1)
        cmds.setAttr('defaultRenderGlobals.periodInExt', 2)
        cmds.setAttr('defaultRenderGlobals.extensionPadding', 4)

        # Set defaultRenderGlobals attributes for animation range
        cmds.setAttr('defaultRenderGlobals.animationRange', 0)
        cmds.setAttr('defaultRenderGlobals.startFrame', start_frame)
        cmds.setAttr('defaultRenderGlobals.endFrame', end_frame)
        cmds.setAttr('defaultRenderGlobals.byFrameStep', step_frame)
        return 1
    else:
        cmds.error('\n', '\t',
                   ' !!! Error Create and configure Arnold' +
                   ' Render Options !!!')
        return 0


# Set Custom input parametrs:
image_format = 'exr'
camera_name = 'persp'
im_h = 1080
im_w = 1920
start_frame = 0
end_frame = 5
step_frame = 1
output_dir = os.path.normpath('e:/Temp')
image_base_name = 'My_creative'

# Get current "images" folder:
workspace_file_rule_images = cmds.workspace(fileRuleEntry = 'images')
# Get extend current "images" folder:
# cmds.workspace(expandName = workspace_file_rule_images)
# Set output dir for current "images" folder:
cmds.workspace(fileRule=[workspace_file_rule_images, output_dir])

# We will do all preparatory work:
alloved = prerender_settings(output_dir, image_base_name, camera_name, start_frame, end_frame, step_frame, image_format)

# Rendering current frame. Only camera flag. Resolution from value in defaultResolution node
if alloved: cmds.arnoldRender(camera = camera_name)

# OR
# Rendering current frame. Set Custom Resolution flags
if alloved: cmds.arnoldRender(camera = camera_name, height = im_h, width = im_w)

# OR
# Rendering sequence with custom resolution, from range values in defaultRenderGlobals node
if alloved: cmds.arnoldRender(batch = True, camera = camera_name, height = im_h, width = im_w)

# Assign the previos value for "images" folder (relative):
cmds.workspace(fileRule = ['images', workspace_file_rule_images])

I hope this post will make the rendering process more transparent and controllable for you.
Good luck and harmony!

Print help info for nodes attributes:

print(sorted(cmds.attributeInfo("defaultArnoldRenderOptions", all = True)))
print(sorted(cmds.attributeInfo("defaultArnoldDriver", all = True)))
print(sorted(cmds.attributeInfo("defaultArnoldFilter", all = True)))
print(sorted(cmds.attributeInfo("defaultRenderGlobals", all = True)))
print(sorted(cmds.attributeInfo("defaultResolution", all = True)))

command (Python) workspace

PS:
If you do not want the image to be written to the tmp subfolder when rendering one current frame, then use arnoldRender with the batch = True flag, while setting start_frame = end_frame = current frame.

PS_02:
Regarding cmds.render(cam):
I think the command works and saves the images rendered using MayaSoftware renderer into a tmp subfolder

PS_03:

mel.eval('renderWindowRenderCamera render renderView "front";')

By default, orthogonal cameras are not Renderable.
To fix this:
cmds.setAttr('frontShape.renderable', 1)

mel.eval('renderWindowEditor -edit -writeImage "C:\\qwe.exr" renderView;')
You can not do it this way. MEL syntax requires either a backslash or a forward triple slash:
mel.eval('renderWindowEditor -edit -writeImage "C:\\\qwe.exr" renderView;')
or
mel.eval('renderWindowEditor -edit -writeImage "C:/qwe.exr" renderView;')
Or, just use the python command:
cmds.renderWindowEditor('renderView', edit = True, writeImage = r'C:\qwe.exr')
But! In different versions of Maya, the result is unpredictable and incorrect with almost all formats!
Using the -colorManage and -cmEnabled flags does not correct the situation…
At the same time, saving manually, through the menu, or using Arnold commands works correctly with all formats.

1 Like

ohh, what a explanation!
thank you so much @VVVSLAVA , I will test it!

best,
joao

hey @VVVSLAVA ! it worked great, thank you so much! :slight_smile:

1 Like