Components

Realtime shaders need two components:

User interface: The user interface is defined by a SPDL file. A single dynamic library can contain multiple shader implementation. However, the SPDL file can only describe one shader. See User Interface

Implementation code: The implementation code is compiled in a dynamic library. See Implementation code.

User Interface

This section contains the following topics

Generate the SPDL file

Register the Shader

Generate the SPDL file

To define the user interface of a realtime shader, create a SPDL file. You can create it by hand or you can use the shader wizard that comes with the SOFTIMAGE|XSI SDK (right-click on the SPDLs folder in the XSI Plugins Tree and choose New > Shader from the context menu).

Example of a SPDL file generated by the wizard:

# SPDL Generated by XSI Shader Wizard
SPDL
Version = "2.0.0.0";
Reference = "{E4367113-30EC-4D16-9107-725EDE386618}";
PropertySet "Halo_pset"
{
   Parameter "out" output
   {
       GUID = "{B63F5024-A49D-4B7A-834F-3DB8033B42EE}";
       Type = color;
   }
   Parameter "inner_ring" input
   {
       GUID = "{56022339-041A-4DBD-8F86-4C092F0A9966}";
       Type = scalar;
       Value = 1.0;
   }
   Parameter "outer_ring" input
   {
       GUID = "{C94AF607-105B-4CD4-A065-3596B661195E}";
       Type = scalar;
       Value = 1.1;
   }
   Parameter "color" input
   {
       GUID = "{9480CAB5-6DB6-44EC-8EF9-BFC23A12363B}";
       Type = color;
       Value = 1.0 0.0 0.0 0.5;
   }
}

MetaShader "Halo_meta"
{
   Name = "Halo Shader";
   Type = texture;
}

Defaults
{
   color
   {
       UIType = "rgba";
   }
}

Layout "Default"
{
   Row
   {
       inner_ring;
       outer_ring;
   }
   Row
   {
       color;
   }
}

Plugin = Shader
{
   FileName = "Halo";
}

Register the Shader

To register the shader in XSI, open a SOFTIMAGE|XSI command prompt and type

xsibatch –i <file>.spdl

In this case, xsi should return something like:

-- Copied SPDL file C:\Documents and Settings\Alex\My Documents\Softimage\dev\Halo\Halo.spdl
        to c:\users\Alex\Softimage\XSI_4.0\Application\spdl
-- Registered file c:\users\Alex\Softimage\XSI_4.0\Application\spdl\Halo.spdl
-- Created preset file c:\users\Alex\Softimage\XSI_4.0\Data\DSPresets\Shaders/RealTime\Halo.Preset
** Warning: No associated library found.
Press [Enter] to continue...

Ignore the warning for now. Once the shader is compiled, the warning should disappear.

Implementation code

This section contains the following topics:

Versioning

Callbacks

Versioning

Each dynamic library needs to implement the GetVersion function. This will tell SOFTIMAGE|XSI which version of the Realtime Shader API this shader was compiled with. The implementation should always be:

RTSHADER_API ULONG RTS_GetVersion()
{
   return XSI_RTSHADER_VERSION;
                 }

Callbacks

Each shader need to implement the following functions

<shader>_Init

<shader>_Term

<shader>_Execute

<shader>_GetRequirements

The <shader>_Execute function is mandatory.

The <shader> prefix is the name of the shader as identified in the SPDL file. For example, if the shader is named OGL13Shade, then you need to implement OGL13Shade_Init, OGL13Shade_Execute, OGL13Shade_Term and OGL13Shade_GetRequirements.

 

These functions return TRUE if successful; otherwise FALSE. All functions receive the system parameters, the property page parameters, and the shader instance user data. Shader instance user data is useful if you want to pass instance data to the <shader>_Term, <shader>_Execute and <shader>_GetRequirements entry points.

Example

// Implementation
RTSHADER_API bool OGL13Shade_Execute
                     (
   XSI_RTS_SystemParams *in_pSysParams,     //! The system parameters
   void              *in_pParams,          //! The property page parameters
   XSI_RTS_TriangulatedGeometry *in_pGeom, //! The geometry information
   void              **io_pShaderInstanceData //! The shader instance data
)
{
   OGL13ShadePPG *ppg = (OGL13ShadePPG *) in_pParams;

   ::glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT , (float *)&ppg->Ambient);
   ::glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE , (float *)&ppg->Diffuse);
   ::glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR , (float *)&ppg->Specular);
   ::glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION , (float *)&ppg->Emission);
   ::glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, ppg->Shininess);

   if(ppg->Lighting)
       ::glEnable( GL_LIGHTING );
   else
   {
       ::glDisable( GL_LIGHTING );
       ::glColor4fv((float *)&ppg->Diffuse);
   }

   // needed because we don't want to have visual regressions with old scenes
   ::glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR );


   return TRUE;
}

<shader>_Init

The <shader>_Init function is called when the shader is created:

RTSHADER_API bool <shader>_Init
                     (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   void              **io_pShaderInstanceData //! The shader instance data
)

This function receives the system parameters, the property page parameters, and the shader instance user data.

For example:

typedef struct tagOGLTextureInstanceData
{
   int    m_Handle;
   LONG   m_MipMap;
   LONG   m_Compression;
   LONG   m_Format;
} OGLTextureInstanceData;

RTSHADER_API bool OGL13Texture_Init
                 (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   void              **io_pShaderInstanceData //! The shader instance data
)
{
   OGLTextureInstanceData *pInstanceData = new OGLTextureInstanceData();
   pInstanceData->m_Handle = -1;

   *io_pShaderInstanceData = pInstanceData;
   return TRUE;
}

<shader>_Term

The <shader>_Term function is called when the shader is destroyed:

RTSHADER_API bool <shader>_Term
                     (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   void              **io_pShaderInstanceData //! The shader instance data
)

This function receives the system parameters, the property page parameters and the shader instance user data.

For example:

typedef struct tagOGLTextureInstanceData
{
   int    m_Handle;
   LONG   m_MipMap;
   LONG   m_Compression;
   LONG   m_Format;
} OGLTextureInstanceData;

RTSHADER_API bool OGL13Texture_Term
                 (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   void              **io_pShaderInstanceData //! The shader instance data
)
{
   OGLTextureInstanceData *pInstanceData = (OGLTextureInstanceData *) *io_pShaderInstanceData;
   if(pInstanceData != NULL)
   {

       // Delete the current handle if needed
       if(pInstanceData->m_Handle != -1)
       {
          ::glDeleteTextures(1, (unsigned int *)&pInstanceData->m_Handle);
       }

       // Delete our instance data
       delete pInstanceData;

   }
   return TRUE;
}

<shader>_Execute

The <shader>_Execute function is called when the shader is used to display the object:

RTSHADER_API bool <shader>_Term
                     (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   XSI_RTS_TriangulatedGeometry *in_pGeom, //! The geometry information
   void              **io_pShaderInstanceData //! The shader instance data
)

This function receives the system parameters, the property page parameters, the geometry of the object it is connected to and the shader instance user data.

For example:

typedef struct tagOGLTextureInstanceData
{
   int    m_Handle;
   LONG   m_MipMap;
   LONG   m_Compression;
   LONG   m_Format;
} OGLTextureInstanceData;

RTSHADER_API bool OGL13Texture_Execute
                     (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   XSI_RTS_TriangulatedGeometry *in_pGeom, //! The geometry information
   void              **io_pShaderInstanceData //! The shader instance data
)
{
   OGL13TexturePPG *pPpg = (OGL13TexturePPG *) in_pParams;
   OGLTextureInstanceData *pInstanceData = (OGLTextureInstanceData *) *io_pShaderInstanceData;
   assert(pInstanceData != NULL);


   //
   // code removed for readability
   //


   return TRUE;

}

<shader>_GetRequirements

The <shader>_GetRequirements function is called before the shader is used to display the object to query for specific shader requirements:

RTSHADER_API bool <shader>_Term
                     (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   XSI_RTS_TriangulatedGeometry *in_pGeom, //! The geometry information
   void              **io_pShaderInstanceData, //! The shader instance data
ULONG                in_lRequirement,  //! The requirement identifier
   ULONG             *out_pRequirementValue //! The returned requirement value
)

This function receives the system parameters, the property page parameters, the geometry of the object it is connected to, the shader instance user data, the requirement ID and the returned requirement value.

The Realtime Shader API version 2.0 currently supports these requirements:

RTS_REQUIRE_ZSORT
sort the object using the graphic pipeline; this is usually used for transparency sorting

RTS_REQUIRE_OBJECTHANDLE
the shader code needs to access the object handle

RTS_REQUIRE_MATERIALHANDLE
the shader code needs to access the material handle

RTS_REQUIRE_LIGHTHANDLE
the shader code needs to access the light handles

If the shader does not need these requirements, then you should always answer FALSE to improve performance.

The result of the query is returned in the out_pRequirementValue.

For example:

RTSHADER_API bool OGL13Draw_GetRequirements
                         (
   XSI_RTS_SystemParams *in_pSysParams, //! The system parameters
   void              *in_pParams,      //! The property page parameters
   XSI_RTS_TriangulatedGeometry *in_pGeom, //! The geometry information
   void              **io_pShaderInstanceData, //! The shader instance data
ULONG                in_lFlag,         //! The flag to check
   ULONG             *out_pValue       //! The returned value
)
{
   OGL13DrawPPG *ppg = (OGL13DrawPPG *) in_pParams;

   *out_pValue = 0;
   switch(in_lFlag)
   {
       case RTS_REQUIRE_ZSORT:
          if((ppg->Blending) && (ppg->BlendFuncDst > 0))
              *out_pValue = 1;
          break;
   };

   return true;
}


SOFTIMAGE|XSI v6.01     

Return to Softimage XSI Index