Whereas the Unified Renderer is the object that lives in the scene and manages user interaction, the render session is a transient object that controls the interval rendering process. It represents one running instance of the render engine - several of which may co-exist and render in parallel, for example to update the material editor preview while an interactive session is active.
The render session takes, in essence, the scene definition as input and produces a rendered image as ouput. Both of these input and output are abstracted by the Render Session Context, to be covered in a following section.
The plugin developer implements the render sessions by deriving from two interfaces: IOfflineRenderSession and IInteractiveRenderSession. As seen previously, instances of these interfaces are created using methods on class UnifiedRenderer:
virtual std::unique_ptr<IOfflineRenderSession> CreateOfflineSession(
IRenderSessionContext& sessionContext) = 0;
virtual std::unique_ptr<IInteractiveRenderSession> CreateInteractiveSession(
IRenderSessionContext& sessionContext) = 0;
Each method may return null if it does not support that particular mode of operation - e.g. if it doesn't support interactive rendering.
The offline render session is tasked with render still images and multi-frame animations. Its emphasis is on overall rendering performance. No interactive scene changes may occur; only animation-related changes may occur from animation frame to the next. Class IOfflineRenderSession exposes the following methods, to be implemented by the plugin developer:
virtual bool TranslateScene(const TimeValue t) = 0;
virtual bool RenderOfflineFrame(const TimeValue t) = 0;
virtual bool StoreRenderElementResult(const TimeValue t, IRenderElement& render_element, IFrameBufferProcessor& frame_buffer_processor) = 0;
virtual void StopRendering() = 0;
virtual void PauseRendering() = 0;
virtual void ResumeRendering() = 0;
The offline render session is invoked strictly from the main thread. It is the plugin developer's responsibility to implement any kind of multi-threading support.
The interactive render session renders a single still image progressively while taking into account concurrent user interaction (modifications of the scene). The emphasis is on interactivity, rather than on pure rendering performance. Great care must be taken to process scene changes in a way which does not de-stabilize 3ds Max, with special attention to threading and re-entrant change notifications. Class IInteractiveRenderSession exposes the following methods, to be implemented by the plugin developer:
virtual bool InitiateInteractiveSession(const TimeValue t) = 0;
virtual bool UpdateInteractiveSession(const TimeValue t, bool& doneRendering) = 0;
virtual void TerminateInteractiveSession() = 0;
virtual bool IsInteractiveSessionUpToDate(const TimeValue t) = 0;
The interactive render session is initialized from the main thread, but the UpdateInteractiveSession()
method is pooled (at regular intervals) from a separate thread. This enables the application to remain active while the frame buffer is updated or while the scene is checked for validity. Nevertheless, care should be taken to avoid accessing the 3ds Max from this thread, as the 3ds Max SDK is generally not thread safe (see class IRenderingProcess for a mechanism that enables running tasks from the main thread).
Render Sessions were designed with encapsulation in mind. By separating the session from the plugin, it becomes possible to have multiple render sessions exist simultaneously for a single plugin. As of today, this scheme is used to update the material editor preview while an interactive render is active. By running two sessions in parallel, we avoid having to stop and restart a render.