Process

Description

Fired whenever the rendering engine is requested to perform a process (for example, render a frame). For sequences, all the frames in a sequence will be called before switching to another render job (although the render can be terminated before the sequence is done). This guarantees that the renderer can recycle previous frame's data.

The Process callback uses the RendererContext to retrieve the renderer options property, get Framebuffer information, and send tile data back to the Render Manager.

Applies To

Custom Renderers

Syntax

// C++
CStatus <renderer_name>_Process( CRef& in_context )
{ 
   ... 
}

<renderer_name> is the name specified in the call to RegisterRenderer with any spaces removed.

Parameters

Parameter

Language

Type

Description

in_context

C++

CRef &

A reference to the RendererContext object. Context::GetSource returns the Renderer .

Context Attributes

Attribute

Type

Description

Process

siRenderProcessType

The process type requested by the render manager.

RenderType

CString

The current type of rendering being performed. For example "Pass", "Region" or "Shaderball".

Scene

CRefArray of Model objects

A list of models that together make up the scene to render. When rendering the current scene, this is simply the scene root model. When rendering shaderballs this can be a composite of the hero object (for example, the apple) and the background object (for example, the checkerboard pattern).

ObjectList

CRefArray of X3DObjects

(Optional) A subset of objects to render from the scene root(s) given in the "Scene" attribute. These objects override any currently selected object, including the "SelectionOnly" only attribute. The "TrackSelection" attribute also changes its behaviour to enclose the objects given in this list, rather than the current selection.

Lights

CRefArray of Light objects

The list of scene lights. This is more of a convenience list and saves the renderer having to traverse the scene models to grab all the lights and check their visibility, etc..

Camera

Primitive

The viewing camera primitive for this render. Use ProjectItem::GetParent3DObject to get the owner X3DObject in order to access the kinematic state and other properties of the camera.

Material

Material or Shader

The material or shader to use if an object's material has nothing connected to it. This is used for shaderball previews only.

Note: This attribute is not available for region and pass rendering.

ImageWidth

unsigned int

The width of the image output in pixels.

ImageHeight

unsigned int

The height of the image output in pixels.

CropLeft

unsigned int

The left offset of the crop rectangle.

CropBottom

unsigned int

The bottom offset of the crop rectangle.

CropWidth

unsigned int

The width of the crop rectangle.

CropHeight

unsigned int

The height of the crop rectangle.

SelectionOnly

bool

Only render objects that are selected.

TrackSelection

bool

Automatically adjust the crop window to fit the object selection (in screen space). In this case the specified crop values should be ignored.

MotionBlur

bool

Motion blur enabled.

ShutterSpeed

double

Shutter open time in frames.

ShutterOffset

double

Shutter offset in frames.

ShutterType

siRenderShutterType

The three shutter types (center, end on frame and start on frame).

MotionBlurDeformation

bool

Motion blur affects deformations as well as transformations.

FileOutput

bool

Images should be written to disk, otherwise only send fragments.

SkipExistingFiles

bool

Skip existing files, if they're deemed rendered already. Locking must be done in order for two machines not to overwrite each others' files.

FieldRender

bool

Field rendering enabled.

FieldInterleave

siRenderFieldType

Field interleave type ( none, Even/NTSC, Odd/PAL).

ArchiveFileName

CString

The current frame's archive filename to use. For multi-frame archives, this will be the same filename for all the frames in the sequence.

Note: This attribute is only set if the process type is siRenderProcessExportArchive.

ArchiveMultiFrame

bool

Embed all frames into a single archive file.

Note: This attribute is only set if the process type is siRenderProcessExportArchive.

Return Value

CStatus

The Process callback should return a status code depending upon whether the render succeeded, was aborted or there was an internal failure:

Status

Description

CStatus::OK

Render completed successfully, in other words, all requested data was successfully written out or passed back to Softimage.

CStatus::Abort

This can only be returned if the Process callback is responding to a call to the Abort callback. It should not be returned under any other circumstances.

CStatus::Fail

Non-fatal error condition was encountered, such as missing textures, abort request from an event (from the RendererContext::TriggerEvent call), etc. In this case one-shot render operations such as pass renders or exports are canceled. Continuous render operations (such as render region or shaderballs) simply stop updating until refreshed.

(any other failure code)

Renderer encountered a catastrophic failure. At this point the whole render job is canceled. If the job was created by the region, the region will close automatically. If the failure happened to a shaderball, that shaderball stops updating.

Examples

//
// Example rendering engine
//

// There is only ever *one* instance of this plug-in running so global variables
// are "ok".

#include <xsi_application.h>
#include <xsi_camera.h>
#include <xsi_context.h>
#include <xsi_decl.h>
#include <xsi_longarray.h>
#include <xsi_math.h>
#include <xsi_pluginregistrar.h>
#include <xsi_renderer.h>
#include <xsi_renderercontext.h>
#include <xsi_customproperty.h>
#include <xsi_ppglayout.h>
#include <xsi_pass.h>
#include <xsi_project.h>
#include <xsi_scene.h>
#include <xsi_passcontainer.h>
#include <xsi_primitive.h>
#include <xsi_x3dobject.h>

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

using namespace XSI; 

XSIPLUGINCALLBACK CStatus XSILoadPlugin( PluginRegistrar& in_reg )
{
   in_reg.PutAuthor(L"Softimage");
   in_reg.PutName(L"Color Renderer");
   in_reg.PutEmail(L"support@softimage.com");
   in_reg.PutURL(L"http://www.softimage.com");
   in_reg.PutVersion(1,0);
   in_reg.RegisterProperty( L"Color Renderer Options" );
   in_reg.RegisterRenderer( L"Color Renderer" );

   return CStatus::OK;
}

//==============================================================================
//
// Rendering Engine Section

/*! Abort handling.
*/
static bool   g_bAborted;
HANDLE           g_hAbort;
CRITICAL_SECTION g_barrierAbort;

void setAbort( bool in_bAbort )
{
   ::EnterCriticalSection( &g_barrierAbort );
   g_bAborted = in_bAbort;
   if( in_bAbort )
       ::SetEvent( g_hAbort );
   else
       ::ResetEvent( g_hAbort );
   ::LeaveCriticalSection( &g_barrierAbort );
}

bool isAborted( )
{
   bool   bAbort;
   ::EnterCriticalSection( &g_barrierAbort );
   bAbort= g_bAborted;
   ::LeaveCriticalSection( &g_barrierAbort );

   return( bAbort );
}


/*! Initialization function for the renderer, called when the
   plug-in is loaded.

   This is where the rendering engine tells the environment what 
   process types it can perform (render, export archives etc.), 
   which property to use for its options and which output formats 
   it supports (and how those formats are defined).

   The renderer can perform any other one-time initialization here also.
*/
XSIPLUGINCALLBACK CStatus ColorRenderer_Init( CRef &in_ctxt )
{
   Context ctxt( in_ctxt );
   Renderer renderer = ctxt.GetSource();

   // Tell the render manager what render processes we support.
   CLongArray process;
   process.Add( siRenderProcessRender );
   renderer.PutProcessTypes( process );

   // Specify the custom property to use for the renderer options
   renderer.AddProperty( siRenderPropertyOptions, L"Color Renderer.Color Renderer Options" );

   // Add the Softimage PIC format as an output format.
   renderer.AddOutputImageFormat( L"Softimage PIC", L"pic" );
   renderer.AddOutputImageFormatSubType( siRenderChannelColorType, L"RGBA", siImageBitDepthInteger8 );

   // And some arbitrary image format.
   renderer.AddOutputImageFormat( L"Foo Format", L"foo" );
   renderer.AddOutputImageFormatSubType( siRenderChannelColorType, L"RGBA", siImageBitDepthInteger8 );
   renderer.AddOutputImageFormatSubType( siRenderChannelColorType, L"RGBA", siImageBitDepthInteger16 );
   renderer.AddOutputImageFormatSubType( siRenderChannelColorType, L"RGB", siImageBitDepthInteger8 );
   renderer.AddOutputImageFormatSubType( siRenderChannelGrayscaleType, L"Gray", siImageBitDepthInteger16 );

   // Create the handles for a thread-safe abort
   g_bAborted = false;
   ::InitializeCriticalSection( &g_barrierAbort );
   g_hAbort = ::CreateEvent( NULL, FALSE, FALSE, NULL );

   return( CStatus::OK );
}


/*! This is called when the plug-in is unloaded.
   The rendering engine should shut down completely and clean 
   out any global data. Any rendering jobs using this engine
   have already been terminated at this point.
*/
XSIPLUGINCALLBACK CStatus ColorRenderer_Term( CRef &in_ctxt )
{
   ::DeleteObject( g_hAbort );
   ::DeleteCriticalSection( &g_barrierAbort );

   g_hAbort = NULL;
   ::ZeroMemory( &g_barrierAbort, sizeof( g_barrierAbort ) );

   return( CStatus::OK );
}

class MyFragment : public RendererImageFragment
{
public:
   MyFragment( 
       unsigned int in_offX, unsigned int in_offY, unsigned int in_width, unsigned int in_height, 
       double in_color[ 4 ] )
   {
       offX = in_offX;
       offY = in_offY;
       width = in_width;
       height = in_height;

       unsigned int r, g, b, a;

       r = (unsigned int)( in_color[ 0 ] * 255.0 );
       g = (unsigned int)( in_color[ 1 ] * 255.0 );
       b = (unsigned int)( in_color[ 2 ] * 255.0 );
       a = (unsigned int)( in_color[ 3 ] * 255.0 );

       color = ( a << 24 ) | ( b << 16 ) | ( g << 8 ) | ( r );
   }

   unsigned int GetOffsetX( ) const { return( offX ); }
   unsigned int GetOffsetY( ) const { return( offY ); }
   unsigned int GetWidth( ) const { return( width ); }
   unsigned int GetHeight( ) const { return( height ); }
   bool GetScanlineRGBA( unsigned int in_uiRow, siImageBitDepth in_eBitDepth, unsigned char *out_pScanline ) const
   {
       unsigned int *pScanline = (unsigned int *)out_pScanline;
       for( unsigned int i = 0; i < width; i++ )
          pScanline[ i ] = color;

       return( true );
   }

private:
   unsigned int offX, offY, width, height;
   unsigned int color;
};

/*! This is the main function that gets called by the render manager
   whenever the rendering engine is requested to perform a process
   (render a frame, export an archive, etc.).

   It is called with a specialized Context object, called RendererContext.
   The RendererContext allows to retrieving the renderer options property,
   getting framebuffer information and sending tile data back to the render 
   manager.
*/
XSIPLUGINCALLBACK CStatus ColorRenderer_Process( CRef &in_ctxt )
{
   setAbort( false );

   RendererContext ctxt( in_ctxt );
   Renderer renderer = ctxt.GetSource();

   // The LockSceneData method *must* be called before accessing any potential
   // scene data. This is to ensure that multiple threads do not concurrently access
   // and/or modify the scene data. It is also important that the renderer does *not*
   // modify any scene data at all. It can modify its own private data but nothing
   // that is a part of the scene or the current application state, unless explicitly
   // allowed.
   if( renderer.LockSceneData() != CStatus::OK )
       return( CStatus::Abort );

   Primitive  camera_prim = ctxt.GetAttribute( L"Camera" );
   X3DObject  camera_obj = camera_prim.GetOwners( )[ 0 ];
   Camera        camera  = camera_obj;
   CString       camera_name = camera_obj.GetName();
   const wchar_t *wcsCameraName = camera_name.GetWideString();

   // Get the size of the image to render (in pixels). The origin is defiend as the
   // bottom-left corner of the image.
   unsigned int width, height;
   width = (ULONG)ctxt.GetAttribute( L"ImageWidth" );
   height = (ULONG)ctxt.GetAttribute( L"ImageHeight" );

   // Check if there is a crop area defined. If the offset is 0,0 and the crop 
   // width/height is the same as the image width/height, then no cropping should take
   // place. The crop window is always fully inside of the rendered image.
   unsigned int cropOffsetX, cropOffsetY;
   unsigned int cropWidth, cropHeight;

   cropOffsetX = (ULONG)ctxt.GetAttribute( L"CropLeft" );
   cropOffsetY = (ULONG)ctxt.GetAttribute( L"CropBottom" );
   cropWidth = (ULONG)ctxt.GetAttribute( L"CropWidth" );
   cropHeight = (ULONG)ctxt.GetAttribute( L"CropHeight" );

   // Get our render property evaluated at the correct time. If rendering fields, any 
   // parameter that is animated, needs to be evaluated at the half-frame in between the
   // current frame and the next frame after. Same goes potentially for motion blur, unless
   // the renderer is incapable of interpolating the data, in which case it should use
   // the current frame as a base.
   CTime  evalTime = ctxt.GetTime();

   Property myProp = ctxt.GetRendererProperty( evalTime );

   double     color[ 4 ];

   color[ 0 ] = myProp.GetParameterValue( L"Color_R", evalTime );
   color[ 1 ] = myProp.GetParameterValue( L"Color_G", evalTime );
   color[ 2 ] = myProp.GetParameterValue( L"Color_B", evalTime );
   color[ 3 ] = myProp.GetParameterValue( L"Color_A", evalTime );

   // Unlock the scene data *before* we start rendering and sending tile data back.
   renderer.UnlockSceneData();

   // Check after the scene data has been evaluted whether the abort flag is set.
   if( isAborted() )
       return( CStatus::Abort );

   // Notify the renderer manager that a new frame is about to begin. This is necessary so
   // that any recipient tile sink can re-adjust its own size to accommodate.
   ctxt.NewFrame( width, height );

   unsigned int  tileSize = 32;

   for( unsigned y = 0; y <= ( cropHeight / tileSize ); y++ )
   {
       for( unsigned x = 0; x <= ( cropWidth / tileSize ); x++ )
       {
          unsigned int ox, oy, sx, sy;

          ox = x * tileSize;
          oy = y * tileSize;
          sx = tileSize;
          sy = tileSize;

          if( ( ox + tileSize ) > cropWidth )
              sx = width - ox;
          else
              sx = tileSize;

          if( ( oy + tileSize ) > cropHeight )
              sy = height - oy;
          else
              sy = tileSize;

          MyFragment fragment( 
              ox + cropOffsetX, oy + cropOffsetY, sx, sy, color );

          // Send back a new tile.
          ctxt.NewFragment( fragment );

          DWORD  dwResult = ::WaitForSingleObject( g_hAbort, 40 );
          if( dwResult != WAIT_TIMEOUT )
              return( CStatus::Abort );
       }
   }

   return( CStatus::OK );
}

/*! Called by the render manager when the renderer should do a full 
   cleanup of any data that got created by the Process function. 
   This is usually called when the current scene is being destroyed,
   or if the specific render process (region, pass render, export)
   requests that data be cleaned up after the process has completed.
*/
XSIPLUGINCALLBACK CStatus ColorRenderer_Cleanup( CRef &in_ctxt )
{
   Context ctxt( in_ctxt );
   Renderer renderer = ctxt.GetSource();

   return( CStatus::OK );
}


/*! Called when the render needs to be aborted. The function should
   trigger an abort and return as quickly as possible. It should
   *not* refer to any scene data and not perform any processing
   besides triggering the abort. It is up to the Process function
   to ensure a clean abort is done upon the receipt of an abort
   signal.
*/
XSIPLUGINCALLBACK CStatus ColorRenderer_Abort( CRef &in_ctxt )
{
   Context ctxt( in_ctxt );
   Renderer renderer = ctxt.GetSource();

   setAbort( true );

   return( CStatus::OK );
}


/*! This function serves two purposes: To return the current "quality"
   level of the render options and to set a preset for the given
   "quality" level. The calculated quality level should be simply
   the value that corresponds to the closest match to a level
   preset.
   \note This mechanism might be aborted shortly and replaced by
       something else that gets handled by Softimage directly.
*/
XSIPLUGINCALLBACK CStatus ColorRenderer_Quality( CRef &in_ctxt )
{
   Context ctxt( in_ctxt );
   Renderer renderer = ctxt.GetSource();

   CValue quality = ctxt.GetAttribute( L"Quality" );
   Property prop = ctxt.GetAttribute( L"Property" );

   static const double levels[ 5 ][ 4 ] = {
       { 1.0, 0.0, 0.0, 1.0 },
       { 0.0, 1.0, 0.0, 1.0 },
       { 1.0, 0.0, 1.0, 1.0 },
       { 1.0, 0.5, 0.5, 1.0 },
       { 0.7, 0.4, 0.3, 0.5 },
   };

   if( quality.IsEmpty() )
   {
       double color[ 4 ];
       int    closest = -1;
       double maxclose = DBL_MAX;

       color[ 0 ] = prop.GetParameterValue( L"Color_R", CTime() );
       color[ 1 ] = prop.GetParameterValue( L"Color_G", CTime() );
       color[ 2 ] = prop.GetParameterValue( L"Color_B", CTime() );
       color[ 3 ] = prop.GetParameterValue( L"Color_A", CTime() );

       // We're being asked for the quality value (0-4).
       // Find the closest color match.
       for( int i = 0; i < 5; i++ )
       {
          double close;
          double dist = 0.0;

          for( int j = 0; j < 4; j++ )
          {
              dist += ( color[ j ] - levels[ i ][ j ] ) * ( color[ j ] - levels[ i ][ j ] );
          }
          close = sqrt( dist );
          if( close < maxclose )
          {
              maxclose = close;
              closest = i;
          }
       }

       ctxt.PutAttribute( L"Quality", closest );
   }
   else
   {
       // Set a quality value based on the five levels (0-4).
       prop.PutParameterValue( L"Color_R", levels[ (ULONG)quality ][ 0 ] );
       prop.PutParameterValue( L"Color_G", levels[ (ULONG)quality ][ 1 ] );
       prop.PutParameterValue( L"Color_B", levels[ (ULONG)quality ][ 2 ] );
       prop.PutParameterValue( L"Color_A", levels[ (ULONG)quality ][ 3 ] );
   }

   return( CStatus::OK );
}


//==============================================================================
//
// Renderer Options Property

XSIPLUGINCALLBACK CStatus ColorRendererOptions_Define( CRef& in_ctxt )
{
   Context ctxt( in_ctxt );
   CustomProperty oCustomProperty;
   Parameter oParam;
   oCustomProperty = ctxt.GetSource();
   oCustomProperty.AddParameter(L"Color_R",CValue::siDouble,siPersistable,L"",L"",0l,0l,1l,0l,1l,oParam);
   oCustomProperty.AddParameter(L"Color_G",CValue::siDouble,siPersistable,L"",L"",0l,0l,1l,0l,1l,oParam);
   oCustomProperty.AddParameter(L"Color_B",CValue::siDouble,siPersistable,L"",L"",0l,0l,1l,0l,1l,oParam);
   oCustomProperty.AddParameter(L"Color_A",CValue::siDouble,siPersistable,L"",L"",0l,0l,1l,0l,1l,oParam);
   return CStatus::OK;
}

XSIPLUGINCALLBACK CStatus ColorRendererOptions_DefineLayout( CRef& in_ctxt )
{
   Context ctxt( in_ctxt );
   PPGLayout oLayout;
   PPGItem oItem;
   oLayout = ctxt.GetSource();
   oLayout.Clear();
   oLayout.AddColor(L"Color_R",L"Color",true);
   return CStatus::OK;
}

See Also

Init (Renderer)

Abort

Quality

Query

Cleanup

Renderer Callbacks



Autodesk Softimage v7.5