#define miRENDER_PREPROC 0x000001
#define miRENDER_OBJ_DELETE 0x000002
#define miRENDER_SHADOWMAP 0x000004
#define miRENDER_DISPLAY 0x000008
#define miRENDER_RENDER 0x000010
#define miRENDER_FB_SAVE 0x000020
#define miRENDER_FB_RESTORE 0x000040
#define miRENDER_FB_DELETE 0x000080
#define miRENDER_OUTPUTSH 0x000100
#define miRENDER_POSTPROC 0x000200
#define miRENDER_IMAGE_DELETE 0x000400
#define miRENDER_CHECK 0x000800
#define miRENDER_DUMP 0x001000
#define miRENDER_ACCEL_DELETE 0x002000
#define miRENDER_LIGHTMAP 0x004000
#define miRENDER_REINHERIT 0x008000
#define miRENDER_POSTPROC_FBC 0x010000
#define miRENDER_DISPLAY_FG 0x020000
#define miRENDER_RENDER_FG 0x040000
#define miRENDER_RENDER_PM 0x080000
#define miRENDER_LIGHT_ACCEL_DELETE 0x100000
#define miRENDER_REINHERIT_LIGHTS 0x200000
#define miRENDER_DEFAULT 0x00471f
#define miRENDER_SHADOWMAP_ONLY 0x000207
#define miRENDER_FG_ONLY 0x044607
#define miRENDER_PM_ONLY 0x084603
#define miRENDER_LIGHTMAP_ONLY 0x004607
miBoolean mi_rc_run(
miUint mode,
int imgpipe,
unsigned int prevmask,
miTag root_group,
miTag c_inst_tag,
miTag camera_tag,
miTag option_tag,
miInh_func inh_func)
This is the main entry point of the renderer. It handles preprocessing, rendering, output shading, postprocessing, and realtime image previews. It is basically a wrapper around the main rendering engine, and also handles all setup and cleanup. The following arguments must be passed:
The following bits may be added to form the mode argument (listed in typical use order, related bits are grouped together) :
| bit | function |
|---|---|
| miRENDER_PREPROC | pre-process full scene |
| miRENDER_OBJ_DELETE | delete source geometry |
| miRENDER_REINHERIT | pre-process only geometry material inheritance |
| miRENDER_REINHERIT_LIGHTS | pre-process only light inheritance |
| miRENDER_CHECK | debugging: check scene |
| miRENDER_DUMP | debugging: dump to stdout |
| miRENDER_SHADOWMAP | render shadow maps |
| miRENDER_RENDER_FG | render final gather maps |
| miRENDER_RENDER_PM | render photon maps |
| miRENDER_LIGHTMAP | compute light maps |
| miRENDER_RENDER | render images |
| miRENDER_DISPLAY | tile display callbacks, connections to imf_disp or imgpipe |
| miRENDER_DISPLAY_FG | coarse display of final gather progress prior to tiles |
| miRENDER_FB_SAVE | make a copy of the frame buffers |
| miRENDER_FB_RESTORE | restore frame buffer copy |
| miRENDER_FB_DELETE | delete frame buffer copy |
| miRENDER_OUTPUTSH | call output shaders |
| miRENDER_IMAGE_DELETE | delete result frame buffers |
| miRENDER_ACCEL_DELETE | delete internal caches |
| miRENDER_LIGHT_ACCEL_DELETE | delete light caches |
| miRENDER_POSTPROC | scene post-processing |
| miRENDER_POSTPROC_FBC | delete tessellation during post-processing |
_DELETE bits.
For convenience, these bitmaps are pre-defined for common use:
| bitmap | function |
|---|---|
| miRENDER_DEFAULT | standard rendering and output shading |
| miRENDER_SHADOWMAP_ONLY | render only shadow maps |
| miRENDER_FG_ONLY | render only final gather maps |
| miRENDER_PM_ONLY | render only photon maps |
| miRENDER_LIGHTMAP_ONLY | render only light maps |
The following code samples show several use cases for the mode bitmap:
mi_rc_run(miRENDER_DEFAULT, ...);
This is what the standalone mental ray executable uses. It pre-processes, renders, and post-processes. mental ray is then ready to repeat the process for the next frame.
mi_rc_run(miRENDER_PREPROC +
miRENDER_OBJ_DELETE, ...);
... /* use the tessellated geometry */
mi_rc_run(miRENDER_POSTPROC, ...);
This combination is useful to tessellate a scene (or, more commonly, a sub-graph of the scene) and then making use of the result of the tessellation for wireframe or hardware-shaded displays. Note that even though mental ray does not render, it is still necessary to define a camera and its instance, and adding the instance to the root group passed to mi_rc_run, because view-dependent approximations during preprocessing need to know where the tessellated geometry is in 3D space with respect to the camera.
mi_rc_run(miRENDER_PREPROC +
miRENDER_OBJ_DELETE +
miRENDER_SHADOWMAP +
miRENDER_LIGHTMAP, ...);
mi_rc_run(miRENDER_DISPLAY +
miRENDER_RENDER +
miRENDER_OUTPUTSH +
miRENDER_IMAGE_DELETE, ...);
... /* more mi_rc_run calls */
mi_rc_run(miRENDER_POSTPROC, ...);
Here, the scene is pre-processed once, and then rendered one or more times, and then post-processed. Rendering multiple times inside the pre-/post-process bracket is useful for shader parameter tuning. The middle call to mi_rc_run may be repeated every time the user has changed a shader parameter, for example to tune a material color. This works very well with shader previewing, which lets mental ray re-render only those pixels that might be affected by the change. Note, that this example cannot deal with scene graph changes - it keeps rendering the leaf instance list created by the first call to mi_rc_run and assumes that it is still valid, and no objects have been changed, added, or deleted.
mi_rc_run(miRENDER_PREPROC +
miRENDER_OBJ_DELETE +
miRENDER_SHADOWMAP +
miRENDER_LIGHTMAP +
miRENDER_RENDER +
miRENDER_FB_SAVE +
miRENDER_OUTPUTSH +
miRENDER_IMAGE_DELETE, ...);
mi_rc_run(miRENDER_FB_RESTORE +
miRENDER_OUTPUTSH, ...);
... /* more mi_rc_run calls */
mi_rc_run(miRENDER_FB_DELETE +
miRENDER_POSTPROC, ...);
This example is similar to the previous except that only the
output shaders and not the entire rendering operation are tuned.
If the user wants to tune parameters of the output shaders
attached to the camera, it would be inefficient to re-render
every time to recreate the images that the output shaders operate
on. Instead, the scene is rendered only once and then saved to
the save frame buffers before calling the output shaders for the
first time. After that, the save frame buffers are simply
restored before calling the output shaders again. Finally, when
tuning has finished, the save frame buffers are deleted and the
scene is post-processed.
Obviously, all these fragments are incomplete: no return code is checked, and
no calls to mi_par_aborted
exist between the various calls to
mi_rc_run that could stop the
render loop if the user has pressed a Cancel or Abort button. Also, before
mi_rc_run can be called for
the first time, a scene must have been constructed using mi_api_*
calls.
The following pseudocode describes the operation of mi_rc_run:
if (miRENDER_PREPROC) {
preprocess;
} else {
if (miRENDER_REINHERIT)
scene_reinherit;
if (miRENDER_REINHERIT_LIGHTS)
lights_reinherit;
}
if (miRENDER_DUMP)
scene_dump(root_group);
if (miRENDER_CHECK) {
scene_check(option_tag);
scene_check(root_group);
}
if (miRENDER_SHADOWMAP && options->use_shadow_maps) {
invalidate_local_images;
build_shadow_maps;
}
if (miIMAGE_DELETE && !options->pixel_preview)
delete_frame_buffers;
if (miRENDER_ACCEL_DELETE) {
delete_pm_cache;
delete_fg_cache;
}
if (options->no_images > 0) {
if (no frame buffers || !options->pixel_preview) {
create_frame_buffers;
invalidate_local_images;
}
if (miRENDER_DISPLAY)
if (imgpipe) init_display_pipe;
else init_display_socket;
if (miRENDER_LIGHTMAP)
build_light_maps;
if (miRENDER_RENDER_PM || miRENDER_RENDER)
build_photon_maps;
if (miRENDER_RENDER_FG || miRENDER_RENDER)
build_finalgather_maps;
if (miRENDER_RENDER)
render;
if (miRENDER_FB_SAVE)
copy frame_buffers to saved_frame_buffers;
if (miRENDER_FB_RESTORE && !miRENDER_FB_SAVE)
copy saved_frame_buffers to frame_buffers;
if (miRENDER_FB_DELETE && !miRENDER_FB_SAVE)
delete saved_frame_buffers;
if (miRENDER_OUTPUTSH)
call_output_shaders;
mi_img_invalidate_local_images;
if (!options->pixel_preview && !miRENDER_IMAGE_DELETE)
delete_frame_buffers;
}
if (miRENDER_POSTPROC) {
scene_postprocess;
if (miRENDER_POSTPROC_FBC)
delete_box_caches;
}
enum miRc_query { /* for mi_rc_run_query */
/* after preprocessing: */
miRCQ_NO_LIGHTS, /* # of light leaf insts */
miRCQ_NO_LEAF_INSTS, /* # of object leaf insts */
miRCQ_LIGHTS, /* list of light leaf insts */
miRCQ_LEAF_INSTS, /* list of object leaf insts */
miRCQ_CAMERAS, /* list of camera leaf insts */
/* after render w/o IMG_DEL: */
miRCQ_FB, /* get frame buffer base */
miRCQ_OPTIONS, /* render options tag */
miRCQ_NEEDS_PREPROC, /* needs scene preprocessing?*/
miRCQ_DISP_NET_PORT, /* port used by imf_disp */
miRCQ_DISP_TALK_PORT, /* port used by disp talk protocol */
miRCQ_CUDA_DEVICES, /* usable cuda device names */
miRCQ_CUDA_DEVICES_N, /* number of usable cuda devices*/
miRCQ_IRAY_VERSION, /* iray plugin version string */
miRCQ_CUDA_DEVICE_PROPERTIES, /* cuda device properties */
miRCQ_CUDA_MEMORY_STATS /* cuda mem stats for iray rendering */
miBoolean mi_rc_run_query(
enum miRc_query mode,
int arg,
void *result);
This function picks up information after a previous
mi_rc_run call. It is useful
when fewer mode flags are used than miRENDER_DEFAULT to split the
rendering operation, especially between pre-processing and post-processing,
and between rendering and deleting the result images.
mi_rc_run_query
accepts a mode that determines what to query, an argument that further
describes which element to return, depending on the mode, and a result
pointer that must point to a variable that the queried data is stored in.
The function returns miTRUE if the query was valid and data
was returned. Otherwise, it returns miFALSE. The following
query modes are supported :
| mode | arg | *result type | returned data |
|---|---|---|---|
miRCQ_NO_LIGHTS | − | int |
number of light leaf instances |
miRCQ_NO_LEAF_INSTS | − | int |
number of object leaf instances |
miRCQ_LIGHTS | − | miTag |
light leaf instances |
miRCQ_LEAF_INSTS | − | miTag |
object leaf instances |
miRCQ_CAMERAS | − | miTag |
camera leaf instances |
miRCQ_FB | − | miTag |
rendered frame buffers |
miRCQ_OPTIONS | − | miTag |
camera leaf instances |
miRCQ_NEEDS_PREPROC | − | int |
dynamic scene changes require pre-processing |
miRCQ_DISP_NET_PORT | − | int |
port to send disp data |
miRCQ_DISP_TALK_PORT | − | int |
port to receive disp commands |
miRCQ_CUDA_DEVICES | − | const char* const* |
array of CUDA device name strings |
miRCQ_CUDA_DEVICES_N | − | miUint |
number of CUDA devices |
miRCQ_IRAY_VERSION | − | const char* |
iray version string |
miRCQ_CUDA_DEVICE_PROPERTIES | int
| miRc_cuda_device_properties |
specific CUDA device properties |
miRCQ_CUDA_MEMORY_STATS | int
| miRc_cuda_memory_stats |
specific CUDA device memory info |
miRCQ_NO_LIGHTSmiRCQ_NO_LEAF_INSTSmiRCQ_LIGHTSmiRCQ_LEAF_INSTSmiRCQ_CAMERAS
miRCQ_FB
miTag tag;
mi_rc_run(miRENDER_DEFAULT & ~miRENDER_IMAGE_DELETE, ...);
mi_rc_run_query(miRCQ_FB, 0, &tag);
if (tag) {
miRcmap_fb* fb = (miRcmap_fb*) mi_db_access(tag);
... /* access individual frame buffer */
}
mi_rc_run(miRENDER_IMAGE_DELETE, ...);
typedef miBoolean (*miTraversal_func)(
void *data, /* opaque this pointer */
struct miInstance *parent, /* previously inherited instance */
struct miInstance *inst, /* new instance to be inherited */
miTag *path, /* path: root group .. curr inst */
int pathlen); /* number of tags in path[] */
void mi_rc_run_traversal_cb(
miTraversal_func cb, /* traversal function to call */
void *data) /* this passed to traversal func */
This function allows to set a callback function that is used during traversal
of the scene graph. It will be called once for each instance in the graph.
The function may change the current instance inst based on the
inherited information. If it returns false, the traversal of this branch of
the scene DAG is terminated. A traversal
function set with
mi_rc_run_traversal_cb
overrides the traversal function set in the options block (given that
inh_is_traversal in the options is set to true).
Note, that the traversal function can also be set by passing the function pointer as inh_func to mi_rc_run and enable the inh_is_traversal flag in the options block.
enum miRc_taskorder {
miRC_TO_HILBERT = 0,
miRC_TO_SPIRAL,
miRC_TO_LEFT_RIGHT,
miRC_TO_RIGHT_LEFT,
miRC_TO_TOP_DOWN,
miRC_TO_BOTTOM_UP
};
void mi_rc_set_taskorder( /* call before mi_rc_run */
enum miRc_taskorder o);
This function allows to change the task order visible as image tiles. It must be called before and between renderings started with mi_rc_run.
Copyright © 1986, 2015 NVIDIA ARC GmbH. All rights reserved.