VTK Painters
The VTK Painters and associated components were developed as part of a collaborative effort between Kitware and Sandia National Laboratories.
For documentation on VTK Shaders please refer to VTK Shaders.
Overview
This document describes the implementation of the Painters in VTK. For the original design/motivation please refer to VTK Painters Design Wiki. Painter are used within a mapper. The design decomposes the tasks that a mapper needs to perform into several operations, each handled by a separate painter. The mapper creates a chain of painters, with each painter having at most one delegate painter. Each painter performs its operations and then delegate the rendering request to the delegate, if any.
Note that the current implementation is provided for poly data mapper alone, although the design should work with other data types. With some modifications to the implementation it should be possible to use the painters for other data types as well.
Implementation
vtkPainter
vtkPainter is the superclass for all painters. The important public API is as follows
// Description: // Get/Set the information object associated with this painter. vtkGetObjectMacro(Information, vtkInformation); virtual void SetInformation(vtkInformation*); // Description: // Set/Get the painter to which this painter should propagare its draw calls. vtkGetObjectMacro(DelegatePainter, vtkPainter); virtual void SetDelegatePainter(vtkPainter*); // Description: // Generates rendering primitives of appropriate type(s). Multiple types // of primitives can be requested by or-ring the primitive flags. // Default implementation calls UpdateDelegatePainter() to update the // deletagate painter and then calls RenderInternal(). virtual void Render(vtkRenderer* renderer, vtkActor* actor, unsigned long typeflags); // Description: // Release any graphics resources that are being consumed by this painter. // The parameter window could be used to determine which graphic // resources to release. // The call is propagated to the delegate painter, if any. virtual void ReleaseGraphicsResources(vtkWindow *);
Each painter keeps an Information object pointer. This information object is used to pass important information about the rendering pass down the painter chain. Typically the mapper fills up the information object based on user selection eg. whether user wants to use display lists, whether scalar coloring is enabled, which lookup table to use etc. and then sets it on the head painter in the painter chain. As will be explained later, this information object then gets propagates to all delegates the painter chain. Each painter only looks for those keys in the information object that it is concerned with and adapts its behaviour accordingly. Each painter may define a set of information keys that it understands.
Each painter can have a delegate painter. One can think of each painter doing its part and the delegating the rest to the delegate painter. eg. we have a display list painter that manages the creation and rendering of display lists, however it does not perform the actual primitive rendering i.e. drawing of polygons. That is delegated to the delegate painter. The delegate painter is set when the painter chain is set up. This is typically done by the mapper. However the user can create his own chain and set it on the mapper (or modify the one set up by the mapper) to customize the pipeline.
A render request is propagated to the painter using the Render method. typeflags identifies the types of primitives that primitives that we are interested in rendering eg. in case of polydata we may choose vertices, lines, polys or tstrips.
vtkPolyDataPainter
vtkPolyDataPainter is the subclass of vtkPainter that provides mechanism for propagating polydata along the painter chain. All the logic in here needs to be collapsed into the superclass (refer to Bug 2809 for details). That will make is possible for all painters to propagate a vtkDataObject which opens up the possibility for using the painters in mappers for anything other than polydata.
The only main addition provided by vtkPolyDataPainter, is that when propagating the Information object to the delegate painter, it propagates the polydata object as well. The default implementation simply passes the input polydata to the delegate. However, subclasses (such as scalars to colors painter) create a new copy of the input polydata, change some of its properties (in case of scalars to colors painters, it adds a new colors array which is colors assigned to points or cells after mapping through the lookuptable) and pass that to the delegate.
Rendering Sequence
For this section we will look at vtkPolyDataPainter and see the sequence of operations performed when Render() is called.
void Render(vtkRenderer* renderer, vtkActor* actor, unsigned int typeflags)
- ProcessInformation: First, the painter mush gather information about user preference for the rendering pass from the information object passed to the painter. A painter should read the Information object for the keys it knows and updates its ivar only by overriding the void ProcessInformation(vtkInformation*) method. The painters use ivars to avoid accessing the map during each render. After ProcessInformation() is called, vtkPainter updates a timestamp called InformationProcessTime. Next time, ProcessInformation() is called only if the information object's MTime is less than this->InformationProcessTime. This avoids processing of the information on every render pass unless the information has changed.
- PrepareForRendering: Some painter may need to do some preprocessing before the actual rendering eg. build efficient data structures for rendering the data. This can be done here. PrepareForRendering is called during each render requests, so subclasses may want to check the data object's MTime to avoid building these data structures unless the data has changed.
- RenderInternal: This is a virtual method that gets called to perform the actual rendering. Default implementation does the following if a delegate painter is present:
- UpdateDelegatePainter: This updates the delegate painter. Updating a delegate painter implies passing the information object to the delegate. This is done by calling the virtual method PassInformation(vtkPainter* toPainter). vtkPolyDataPainter overrides PassInformation to pass the polydata object to the delegate as well. As discussed earlier, default implementation simply passes the input polydata to the delegate, however subclasses may change that.
Sandia is a multi-program laboratory operated by Sandia Corporation, a Lockheed Martin Company, for the United States Department of Energy under Contract DE-AC04-94AL85000.