220 likes | 367 Views
vtkPainter and Friends. Kenneth Moreland Sandia National Laboratories. Sandia is a multiprogram laboratory operated by Sandia Corporation, a Lockheed Martin Company, for the United States Department of Energy’s National Nuclear Security Administration under contract DE-AC04-94AL85000.
E N D
vtkPainter and Friends Kenneth Moreland Sandia National Laboratories Sandia is a multiprogram laboratory operated by Sandia Corporation, a Lockheed Martin Company,for the United States Department of Energy’s National Nuclear Security Administration under contract DE-AC04-94AL85000.
Motivation • Rendering performance of VTK (vtkOpenGLPolyDataMapper) is legendary for its mediocrity. • Principally limited to OpenGL 1.0 functions. • Relies heavily on display lists. • To be fair, mapper improved significantly in past couple of years (as did nVidia’s display lists). • We know we can do better with vertex arrays. • Enter vtkOpenGLVertexArrayMapper. • Saw 4x improvement and declared success.
Motivation • Soon found problems with vertex array mapper. • Taking advantage of OpenGL extensions meant subclassing. • A factory had to choose the “right one” up front. • Worked well only on limited poly data. • Mapper contains lots of “hacks” for rendering all types of data. • Hacks worked poorly and obfuscated the code.
What’s Wrong? • A vtkPolyDataMapper is required to render anything you throw at it. • There are many combinations. • 4 cell types x 3 normal configs x 3 scalar configs x 2 tcoord configs = 72 • Does not include tuple sizes and data types. • Handling all of them reasonably inevitably leads to obfuscated code. • All rendering approaches have their drawbacks. • Calling glVertex, glColor, etc. is API bound. • Display lists have high overhead. • Vertex arrays do not work well on cell data and can be API bound.
Goal: A More Flexible Mapper • The mapper should change its rendering strategy (i.e. display list vs. vertex array) based on input. • It should be easy to add new rendering methods/incorporate new OpenGL extensions. • It should be Cg/HLSL ready. • It should (hopefully) handle everything we have not thought of yet gracefully.
Context ContextInterface() Strategy AlgorithmInterface() ConcreteStrategyA AlgorithmInterface() ConcreteStrategyB AlgorithmInterface() ConcreteStrategyC AlgorithmInterface() Approach: Strategy Pattern
vtkPainterPolyDataMapper vtkPolyDataPainter vtkStandardPolyDataPainter vtkDisplayListPainter vtkDefaultPainter Application
What is a vtkPainter? • A vtkPainter is responsible solely for issuing rendering commands that draw primitives. • Establishing pipeline state is left for the thin mapper, property, and other classes. • Mapper calls DrawVerts(), DrawLines(), DrawPolys(), and DrawStrips(). • A vtkPainter does not have to support all types of poly data. • It is free to render some types poorly or not at all. • Making a painter is easy compared to making a poly data mapper.
Some Painter Implementations • vtkStandardPainter • A jack of all trades. A master at none. • vtkPointsPainter, vtkLinesPainter, vtkPolygonsPainter, vtkTSTripsPainter • Painters optimized for rendering a particular type of polygon (but no other type of polygon).
Painter Decorators • All painters have a delegate painter that can do all or some of the rendering work. • A painter can operate by simply modifying the behavior of (or decorating) its delegate. • The behavior of the delegate painter is modified by some pre- or post-processing. • From the outside, a decorating painter behaves just like any other painter.
Example Painter Decorators • Existing painter decorators. • vtkDisplayListPainter • vtkClipPlanesPainter • vtkLightingPainter • vtkScalarsToColorsPainter • vtkCoincidentTopologyResolutionPainter • vtkRepresentationPainter • Other possible decorators • Sorting • View dependent level-of-detail • Hardware friendly layout (triangulation, stripping, partitioning, cache miss minimization, cell to point, etc.) • ??? • Note the flexibility (although there may be memory copy overheads).
Establishing a Painter Pipeline • Most often, you need a combination of several painters (lighting, coloring, drawing, etc.) to get a viable image. • Establishing this pipeline can be confusing and annoying. • Solution: use vtkDefaultPainter. • The default painter is a meta-painter that internally sets up a default pipeline that establishes all of the most common non-drawing operations (the delegate performs the drawing). • Replicates the non-drawing operations of the original vtkOpenGLPolyDataMapper.
Choosing a Painter for Drawing • Sometimes you will have a painter in mind, most often you will not. • How does an application choose a painter? • Solution: use vtkChooserPainter. • The default painter was programmed with implicit knowledge about some set of painters. • Based on the poly data, the rendering system, and information given by the application, the default painter will pick a reasonable (if not optimal) painting algorithm. • vtkChooserPainter is the default delegate painter for vtkDefaultPainter.
State Maintained by vtkPainter Superclass • A vtkPolyData (cell and point data is ignored). • Usage flags. • StaticData, ConserveMemory, HighQuality, BuildNormals. • These flags may be ignored by some painters.
Attribute Arrays • A painter defines primitives by sending data from attribute arrays to the graphics card. • The order the attributes are sent determines (in part) the nature of the primitives. • The data in the attributes (plus the rendering system state) determine the position and colors. • Each attribute array has an index. • Attributes can be defined on points or cells. • Attribute meaning usually corresponds to vtkDataSetAttributes::AttributeTypes enums (with NUM_ATTRIBUTES mapped to point positions), but this can be overridden for shaders.
Painter Device Adapters • An abstract wrapper around OpenGL drawing functions. • Used instead of calling functions such as glBegin, glEnd, glVertex*, and glDrawElements. • Works with the abstract attributes. • Default OpenGL adapter maps to positions, colors, normals, and texture coordinates in the same way as the aliases in vtkPainter. • Can be substituted for another rendering API.
Integrating Cg • Create a subclass of vtkPainterDeviceAdapter. • Map attribute indices to vertex-program variable parameters. • Call the appropriate Cg lib functions. • It’s probably best to maintain the attribute aliases. • Set in the painter any attribute arrays that do not fall into the standard aliases (point position, color, normal, and texture coordinate). • That’s it. Were you, like, expecting something more difficult?
vtkDisplayListPainter vtkScalarsToColorsPainter vtkRepresentationPainter vtkClipPlanesPainter vtkLightingPainter vtkChooserPainter vtkDisplayListPainter vtkCoincidentTopologyResolutionPainter Class Overview vtkPolyDataMapper vtkPainter DelegatePainter Painter vtkPolyDataPainter vtkPainterDeviceAdapter vtkPainterPolyDataMapper vtkOpenGLPainterDeviceAdapter vtkStandardPainter vtkPrimitivePainter vtkPointsPainter vtkLinesPainter vtkPolygonsPainter vtkTStripsPainter
Conclusions • Disadvantages • Higher API overhead. • Particularly problematic with the virtual functions in vtkPainterDeviceAdapter. • Aggravates an already existing problem (and, yeah, vtkStandardPainter is really slow). • Runaway combinations in attributes. • No choice but to iterate over attributes. • Looser coupling. • Excessive memory reordering/copying may be required.
Conclusions • Advantages • Looser coupling. • Better code separation, less obfuscation. • Easier to employ rendering techniques/extensions. • Dynamic choosing of rendering technique. • Technique is specific to the data/state. • The extra overhead can be mitigated by using the best painter for the job. • A decorator can apply a feature to any other painter (even another decorator). • Cg ready.