Pass Channels (XSISDK)

Pass Channels allow shaders to redirect a color channel to a separate output buffer. These output buffers show up in the Render Options PPGs.

Table of contents

Writing shaders for pass channels

Shaders can easily take advantage of the pass channels mechanism. All they need to provide is a string indicating the name (and optionally a type) of the pass channel(s) they provide. This string is used by the rendering engine to figure out which pass channels to enable for the scene.

At render time the rendering engine adds the requisite framebuffers that will contain the pass channel data and a userdata (XSIPassChannelsUD) that gets linked to the render options. The userdata is required since mental ray does not provide a way of naming the framebuffers. The userdata contains a mapping table between the name of each active pass channel and the framebuffer index to use for it.


The pass channel string is added to the option block of the mental ray renderer in the metashader section. The option name is called "pass channel". It can contain one or more comma separated pass channel names. Each pass channel can optionally contain a specific image type in brackets. For example "Normal Buffer(normal)" would add a pass channel called "Normal Buffer" with an image of type normal, which maps to the mental ray image type of miIMG_TYPE_N.

Below is an example of how to add this option

MetaShader "pass_channel"
  Name = "Pass Channel Example Shader";
  Type = texture;
  Renderer "mental ray"
    Name = "pass_channel";
      "pass channel" = "ChannelOne(rgb),ChannelTwo(motion)";

Names and image types

Below is a table of image names and the matching mental ray image type. The channel names are case-insensitive. mental ray treats each image type as a seperate channel format and bit depth. XSI allows (in most cases) the channel type and bit depth to be selected individually.

Name Type
"Alpha" or "A" miIMG_TYPE_A, miIMG_TYPE_A_16 and miIMG_TYPE_A_FP
"Intensity" or "S" miIMG_TYPE_S, miIMG_TYPE_S_16 and miIMG_TYPE_S_FP
"Depth" or "Z" miIMG_TYPE_Z
"Motion" or "M" miIMG_TYPE_M
"Normal" or "N" miIMG_TYPE_N
"Tag" or "T" miIMG_TYPE_TAG

mental ray shader code

The mental ray code for the pass channel setup seen above would correspond to the code below. The code provided is very basic. Ideally the shader should store away the information from get_pass_channel in a shader local data which would be created in the _init function of the shader.

It is probably a good idea to only store pass channel samples, unless otherwise required, when called as a specific ray, usually the eye ray (miRAY_EYE). Otherwise the channel samples might start showing up in reflections and other areas where possibly another pass channel is handling that data.

#include <shader.h>
#include <xsi_miuserdata_defs.h>
#include <string.h>

#ifdef WIN32
#define strcasecmp stricmp

int get_pass_channel
  miState    *state,
  char    *channel_name
  miTag    data = state->options->userdata;
  XSIPassChannelsUD *pc = NULL;
  int i;

  /* Find the pass channels userdata */
  while( data )
    miUint label;

    mi_query( miQ_DATA_LABEL, NULL, data, (void *)&label );
    if( label == XSIPassChannels_Magic )
      mi_query( miQ_DATA_PARAM, NULL, data, (void *)&pc );
    mi_query( miQ_DATA_NEXT, NULL, data, (void *)&data );
  if( pc == NULL )
    return( -1 );
  for( i = 0; i < pc->nb_passchannels; i++ )
    if( strcasecmp( pc->passchannel[ i ].name, channel_name ) == 0 )
      return( pc->passchannel[ i ].fb );
  return( -1 );

/* The shader is set as a pass-through shader and hence the parameter block
   consists of a single color only. The shader records the incoming color
   and the motion at current intersection point */
miBoolean pass_channel( miColor *result, miState *state, miColor *p )
  int      fb_color, fb_motion;

  *result = *mi_eval_color( p );

  fb_color = get_pass_channel( state, "ChannelTwo" );
  if( fb_color != -1 && state->type == miRAY_EYE )
    mi_fb_put( state, fb_color, result );
  fb_motion = get_pass_channel( state, "ChannelTwo" );
  if( fb_motion != -1 && state->type == miRAY_EYE )
    miVector    motion = { 0.0f, 0.0f, 0.0f };

    /* Get the motion vector in internal (world) space */
    if( state->motion.x != 0.0f && 
      state->motion.y != 0.0f && 
      state->motion.z != 0.0f )
      mi_vector_from_object( state, &state->motion, &motion );

    mi_fb_put( state, fb_motion, &motion );

  return( miTRUE );

This page was last modified 04:27, 2 Oct 2010.
This page has been accessed 8243 times.

© Copyright 2009 Autodesk Inc. All Rights Reserved. Privacy Policy | Legal Notices and Trademarks | Report Piracy