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