Pure-virtual and default implementation in the RixShadingPlugin API
RixShadingPlugin API and the associated subclasses (
RixBxdf, etc...) also contain non-pure virtual methods, it is strongly recommended to use the C++ keyword
override when overriding methods of the API.
Interactive editing and Options / Render State queries.
RenderMan 23 introduces the possibility of editing displays and LPEs during an interactive rendering session, without needing to restart the entire rendering session (e.g. translate the entire scene again).
As a consequence, several quantities that
RixShadingPlugin could previously query in the
RixShadingPlugin::CreateInstanceData() may change during the rendering session, leading to shading plugins using out-of-date values.
For example, the following may now change between renders:
- resolution, number of displays, and other display-related options
- contents of the
- quantities available through the
In order to avoid counter-intuitive behavior (e.g. restarting a render suddenly yields a very different render), it's is highly recommended for shading plugin to stop accessing these inside the
CreateInstanceData(). Instead, the
Synchronize() and (newly introduced)
SynchronizeInstanceData() methods should be used, allowing the user to update the data stored for the plugin and plugin instances before a new render.
RixCustomLPEinterfaces are not available in Init() and CreateInstanceData() anymore.
RixRenderStateand calls to
GetOptions()are still available, but may return out-of-date values. It is strongly recommended to move the associated code to the synchronization methods.
The restriction to
RixLPEInfo implies that functions like
RixBXLookupLobeByName shouldn't be called in
CreateInstanceData() either. This function should usually be called in
RixPlugin::CreateInstanceData() and RixPlugin::SynchronizeInstanceData()
Plugin Instance Initialization
The return type of
RixShadingPlugin::CreateInstanceData() has been changed from
Previously, when a value of
-1 was returned, the renderer would ignore the
InstanceData::data member, and
nullptr would be provided as 'instancedata' to the various shading plugin methods (e.g.
In 23, the renderer directly inspects the value of
InstanceData::data to detect if the plugin instance allocated private instance data. The (newly introduced)
SynchronizeInstanceData() will then be given a chance to update the contents of this private instance data, before the pointer is provided to the usual shading plugin methods.
Plugin Instance Synchronization
RixShadingPlugin::SynchronizeInstanceData() is a new API that allows user to update the private instance data associated with a plugin instance.
Because this method will be executed before a new render starts (i.e. after edits have been processed), it allows for options and render state queries to return up-to-date values.
For performance reasons, this method will only be called if the shading plugin instance has explicitly subscribed to it. This is done by setting the (new)
InstanceData::synchronizeHints member to a non-zero value during
CreateInstanceData(). This member is a bit field that the plugin instance can use to specify on which kind of edit category should the
SynchronizeInstanceData() be called. Currently, only two values are exposed, but additional categories may be added shortly (e.g. k_DisplayEdit, k_OptionEdit, k_LPEEdit, etc...).
Let's consider a plugin instance with a non-trivial
RixShadingPlugin::CreateInstanceData() method, using option queries and storing the returned values in its own private instance data class.
MyBxdf::CreateInstanceData() will only be called once during an interactive rendering session, the option values stored in `data` may become out-of-date, yielding incorrect and/or counter-intuitive results.
In RenderMan 23, this plugin should do the following:
MyBxdfFactory::GetInstanceHints() relies on some member of the private instance data,
CreateInstanceData() still needs to initialize these, because
RixBxdfFactory::GetInstanceHints() is currently only called once per rendering session, before the first call to
A similar issue happens with
RixPattern::Bake3dOutput(): these methods are run before
SynchronizeInstanceData(), so it is important to ensure that
CreateInstanceData() is properly initializing the required members of the private instance data.
Alternatively, if no computations need to happen in
RixShadingPlugin::CreateInstanceData(), it is possible to delegate the management of the private instance data entirely to
SynchronizeInstanceData() by doing the following:
RixProjectionFactory::CreateProjection() and RixProjection::RenderBegin()
For similar reasons, the
RixProjection API has changed. Previously, the
RixIntegratorEnvironment structure was provided to
In order for a
RixProjection object to respond to edits affecting the
RixIntegratorEnvironment structure, a new API has been introduced:
RixProjection::RenderBegin(). Note that we do not pass
Any code previously in the
RixProjection constructor that was using
RixIntegratorEnvironment should now live in
Previously, the projection plugins were allowed to modify the value of
RixIntegratorEnvironment::deepMetric during the creation of the
RixProjection object. This is not the case anymore, and in
RixProjection::RenderBegin(), this structure is now read-only.
Projection plugins should now use the a
RixProjection::GetProperty() mechanism to communicate a particular metric to the renderer (similarly to what was already happening for
A typical implementation of the
RixProjection::GetProperty() method would look like this:
The integrator plugins are now using a Factory, similarly to RixProjection.
In general, it should be sufficient adding something like this to the existing integrator plugins:
And replace the existing
RIX_INTEGRATORDELETE by the following: