Share

Creating and Rendering a Scene - Arnold Developer Guide

This example C++ code uses the Arnold API to create a basic scene containing a sphere, a textured quad mesh, a point light and a camera. It then renders the scene to a user-specified JPEG file on disk.

Source Code

example.cpp

#include <ai.h>

int main()
{
   AiBegin();

   // create anew universe to create objects in
   AtUniverse *universe = AiUniverse();
   // start an Arnold session, log to both a file and the console
   AtRenderSession *session = AiRenderSession(universe,  AI_SESSION_BATCH);
   AiMsgSetLogFileName("scene1.log");
   AiMsgSetConsoleFlags(universe, AI_LOG_ALL);
   AiMsgSetLogFileFlags(universe, AI_LOG_ALL);
   // create a sphere geometric primitive
   AtNode *sph = AiNode(universe, AtString("sphere"),  AtString("mysphere"));
   AiNodeSetVec(sph, AtString("center"), 0.0f, 4.0f, 0.0f);
   AiNodeSetFlt(sph, AtString("radius"), 4.0f);

   // create a polymesh, with UV coordinates
   AtNode *mesh = AiNode(universe, AtString("polymesh"), AtString("mymesh"));
   AtArray* nsides_array = AiArray(1, 1, AI_TYPE_UINT, 4);
   AiNodeSetArray(mesh, AtString("nsides"), nsides_array);
   AtArray* vlist_array = AiArray(12, 1, AI_TYPE_FLOAT, -10.f, 0.f, 10.f, 10.f, 0.f, 10.f, -10.f, 0.f, -10.f, 10.f, 0.f, -10.f);
   AiNodeSetArray(mesh, AtString("vlist"), vlist_array);
   AtArray* vidxs_array = AiArray(4, 1, AI_TYPE_UINT, 0, 1, 3, 2);
   AiNodeSetArray(mesh, AtString("vidxs"), vidxs_array);
   AtArray* uvlist_array = AiArray(8, 1, AI_TYPE_FLOAT, 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 0.f, 1.f);
   AiNodeSetArray(mesh, AtString("uvlist"), uvlist_array);
   AtArray* uvidxs_array = AiArray(4, 1, AI_TYPE_UINT, 0, 1, 2, 3);
   AiNodeSetArray(mesh, AtString("uvidxs"), uvidxs_array);

   // create a red standard surface shader
   AtNode *shader1 = AiNode(universe, AtString("standard_surface"), AtString("myshader1"));
   AiNodeSetRGB(shader1, AtString("base_color"), 1.0f, 0.02f, 0.02f);
   AiNodeSetFlt(shader1, AtString("specular"), 0.05f);

   // create a textured standard surface shader
   AtNode *shader2 = AiNode(universe, AtString("standard_surface"), AtString("myshader2"));
   AiNodeSetRGB(shader2, AtString("base_color"), 1.0f, 0.0f, 0.0f);

   // create an image shader for texture mapping
   AtNode *image = AiNode(universe, AtString("image"), AtString("myimage"));
   AiNodeSetStr(image, AtString("filename"), AtString("arnold.png"));
   AiNodeSetFlt(image, AtString("sscale"), 4.f);
   AiNodeSetFlt(image, AtString("tscale"), 4.f);
   // link the output of the image shader to the color input of the surface shader
   AiNodeLink(image, AtString("base_color"), shader2);

   // assign the shaders to the geometric objects
   AiNodeSetPtr(sph, AtString("shader"), shader1);
   AiNodeSetPtr(mesh, AtString("shader"), shader2);

   // create a perspective camera
   AtNode *camera = AiNode(universe, AtString("persp_camera"), AtString("mycamera"));
   // position the camera (alternatively you can set 'matrix')
   AiNodeSetVec(camera, AtString("position"), 0.f, 10.f, 35.f);
   AiNodeSetVec(camera, AtString("look_at"), 0.f, 3.f, 0.f);
   AiNodeSetFlt(camera, AtString("fov"), 45.f);

   // create a point light source
   AtNode *light = AiNode(universe, AtString("point_light"), AtString("mylight"));
   // position the light (alternatively use 'matrix')
   AiNodeSetVec(light, AtString("position"), 15.f, 30.f, 15.f);
   AiNodeSetFlt(light, AtString("intensity"), 4500.f); // alternatively, use 'exposure'
   AiNodeSetFlt(light, AtString("radius"), 4.f); // for soft shadows

   // get the global options node and set some options
   AtNode *options = AiUniverseGetOptions(universe);
   AiNodeSetInt(options, AtString("AA_samples"), 8);
   AiNodeSetInt(options, AtString("xres"), 480);
   AiNodeSetInt(options, AtString("yres"), 360);
   AiNodeSetInt(options, AtString("GI_diffuse_depth"), 4);
   // set the active camera (optional, since there is only one camera)
   AiNodeSetPtr(options, AtString("camera"), camera);

   // create an output driver node 
   AtNode *driver = AiNode(universe, AtString("driver_jpeg"), AtString("mydriver"));
   AiNodeSetStr(driver, AtString("filename"), AtString("scene1.jpg"));

   // create a gaussian filter node
   AtNode *filter = AiNode(universe, AtString("gaussian_filter"), AtString("myfilter"));

   // assign the driver and filter to the main (beauty) AOV,
   // which is called "RGBA" and is of type RGBA
   AtArray *outputs_array = AiArrayAllocate(1, 1, AI_TYPE_STRING);
   AiArraySetStr(outputs_array, 0, AtString("RGBA RGBA myfilter mydriver"));
   AiNodeSetArray(options, AtString("outputs"), outputs_array);

   // finally, render the image!
   AiRender(session, AI_RENDER_MODE_CAMERA);

   // ... or you can write out an .ass file instead
   // AtParamValueMap* params = AiParamValueMap();
   // AiParamValueMapSetInt(params, AtString("mask"), AI_NODE_ALL);
   // AiSceneWrite(universe, "scene1.ass", params); 
   // AiParamValueMapDestroy(params);

   // Arnold session shutdown
   AiRenderSessionDestroy(session);
   AiUniverseDestroy(universe);
   AiEnd();

   return 0;
} 

Compiling

The following commands compile and run the example on various platforms:

Linux

export ARNOLD_PATH=/path/to/arnold
export LD_LIBRARY_PATH=$ARNOLD_PATH/bin
c++ example.cpp -o example -std=c++11 -Wall -O2 -fPIC -I$ARNOLD_PATH/include -L$ARNOLD_PATH/bin -lai 
./example 

macOS

export ARNOLD_PATH=/path/to/arnold
export DYLD_LIBRARY_PATH=$ARNOLD_PATH/bin
c++ example.cpp -o example -Wall -O2 -I$ARNOLD_PATH/include -L$ARNOLD_PATH/bin -lai
./example 

Windows Visual Studio command prompt

set ARNOLD_PATH=c:/path/to/arnold
set PATH="%ARNOLD_PATH/bin;$PATH"
cl example.cpp /I %ARNOLD_PATH%/include %ARNOLD_PATH%/lib/ai.lib /link /out:example.exe
example 

Output

Once rendered, the output should look like this:

render example

Was this information helpful?