Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

State Handling

One of the main tasks of a scene graph system is efficiently managing the OpenGL state.

Every primitive is rendered using the currently active OpenGL state, which includes things like material parameters, textures, transformation matrices etc. Changing OpenGL state can be very expensive and should be minimized as much as possible. Primitives using the same OpenGL state set should be grouped together, so that changing the state is not needed.

But on top of that it is necessary to sort the different state sets so that the changed when changing from one to the other are minimized, too. For example all objects using the same texture should be rendered close together, as loading a texture into the graphics board can take a long time.

Thus the different state sets used by the visible objects should be sorted into a sequence that minimizes the state changes necessary. Unfortuneately that problem is NP-complete (it's equivalent to the Traveling Salesman Problem). To simplify it the rather large OpenGL state is divided into a small number of parts. Elements of the state that are usually changed together are grouped into a osg::StateChunk.

Every type of osg::StateChunk has an associated osg::StateChunkClass. The osg::StateChunkClass is used to identify the osg::StateChunk and associate it with a name and a low integer numeric Id. Some types of chunks can be used simulatenously in multiple instances in OpenGL, e.g. light sources or textures (in a multi-texture environment). The maximum number of concurrently active slots of the osg::StateChunk type is also stored in the osg::StateChunkClass.

The complete OpenGL state wrapper is the osg::State. It primarily contains a vector of osg::StateChunks. For every type of chunk there are as many slots as possibly concurrently active copies of the chunk. A chunk can be activated, which sets the OpenGL state it covers to its settings, if the settings differ from an internally defined default state. It is possible to switch from one instance of a state chunk to another instance of the same type. This tries to optimize and minimize the changes, to speed up switching. The cost of switching can be estimated, currently that estimation will always be 0, though. Finally a chunk can be deactivated, which resets the OpenGL state it covers to the default value. All the chunks in a osg::State can be managed at the same time by using the equivalent methods of the osg::State.

Ext: To add new chunks you need to derive it from osg::StateChunk. It needs to keep a static instance of osg::StateChunkClass and implement the public osg::StateChunk::getClass() method to allow access to it. The osg::StateChunkClass needs to define the name of the new chunk class and the number of possible concurrently active chunks for the new class. To implement the actual behaviour the osg::StateChunk::activate(), osg::StateChunk::changeFrom() and osg::StateChunk::deactivate() methods are needed. The osg::StateChunk::switchCost() method is in there already, but the semantics are not defined yet, and it is not used. Implement it, but leave it empty and always return 0.

You will probably need to handle OpenGL extensions, see OpenGL Extensions for details on how to do that. The convention for naming the static variables for holding the extension and extension function handles is _extExtensionName (e.g. _extBlendSubtract for the GL_EXT_blend_subtract, extension) and _funcFunctionName (e.g. _funcBlendColor for glBlendColor).

Hint! If you want to use state chunks in the scene graph, you can attach them to a osg::ChunkMaterial or one of its descendents.

Dev: The main motivation for osg::StateChunk::changeFrom() is to allow optimizations in terms of state changes. When switching between chunks that have similar settings, only the differences need to be passed to OpenGL. When and where it makes sense to pass it to OpenGL anyway instead of checking is still an open topic.

Every chunk has a number of parameter which are pretty directly mapped to OpenGL parameters. Thus in many cases OpenGL constants are used to define different parameter values and enumerations. This allows usage of some OpenGL extensions directly by supplying the correct constants.

OpenGL uses explicit enabling in most situations. To get around having to keep extra variables for enabling the value GL_NONE is used in many places to indicate a disabled feature. The documentation of the chunk notes where this is possible.

The different types of state chunks are:

BlendChunk

The osg::BlendChunk handles OpenGL blending, i.e. the definition how incoming fragments are combined with the pixel already in the frame buffer, including alpha culling.

The wrapped OpenGL functions are glBlendFunc and glAlphaFunc, see their documentation for details. It also handles the common blending-related OpenGL extensions EXT_blend_color, ARB_imaging, EXT_blend_subtract, EXT_blend_minmax and EXT_blend_logic_op, when they are supported by the hardware.

ClipPlaneChunk

The osg::ClipPlaneChunk controls user-defined clipping. It uses a beacon osg::Node reference to control the cordinate system where the clipping plane is defined, this allows attaching the ClipPlane to another object to move it around. The clipping plane itself is defined in the standard (a,b,c,d) form used by OpenGL. 6 user defined clipping planes are possible.

CubeTextureChunk

The osg::CubeTextureChunk is similar to TextureChunk and uses the same osg::StateChunkClass (i.e. can be used instead of a osg::TextureChunk, but not both at the same time), but has 5 more texture images. Note that all textures have to be square and have to have the same resolution. The textures are accessed using 3D texture coordinates, which are usually created using a osg::TexGenChunk.

Cube textures are an extension that is only available in newer hardware. They can not be emulated, thus they are ignored when they are not supported by the active window.

LightChunk

The osg::LightChunk contains the parameter set for a single light source. It's parameters are taken straight from the glLight() manpage. The maximum number of concurrently active lights is currently set to 8.

Note that these chunks are created by the system internally from the osg::Light sources and shouldn't be directly used by an application.

LineChunk

The osg::LineChunk contains the parameters that are specificly set for lines. This includes line width, stippling and antialiasing.

PointChunk

The osg::PointChunk contains the parameters that are specific set for points. This includes point size and point antialiasing.

It also wraps the ARB_point_parameters and NV_point_sprite extensions.

ARB_point_parameters allows the specification of points whose size changes depending on the distance to the viewer, including the mapping of sizes smaller than a pixel to alpha. This is useful for objects rendered by points, e.g. particle systems or the so-called light point for runway lights in flight simulation.

The actual size of the point is derived from its given size, which is devided by a the reciprocal of a quadratic expression of the distance to the point in eye coordinates (sepcified by constantAttenuation, linearAttenuation and quadraticAttenuation). This size is then clamped into the minSize, maxSize range and possible clamped against OpenGL's internal size constraints. If the calculated size was smaller than the minSize the point's alpha is reduced proportionally.

MaterialChunk

The osg::MaterialChunk controls the material parameters, i.e. the parameters for phong lighting as used by glMaterial(). It also covers the commonly used parameters to enable/disable lighting and switching the influence of geometry colors on lighting (glColorMaterial). When lighting is enabled external colors like osg::Geometry colors are only used for the diffuse lighting component. In the unlit case they are always used.

PolygonChunk

The osg::PolygonChunk contains the parameters that are specific set for filled surfaces, i.e. polygons. This includes face culling and front face definition as well as front and back face rendering modes, polygon antialiasing, offset and stippling. As there is only one set of offset parameters for all the primitives, the offsetting for points and lines is also handled in this chunk, which admittedly is a bit awkward.

RegisterCombinersChunk

The osg::RegisterCombinersChunk chunk is a direct mapping of the nVidia RegisterCombiners extension. It is based on the GL_NV_register_combiners2 extension, i.e. it also supports per-stage constants.

TexGenChunk

The osg::TexGenChunk wraps texture coordinate generation functions. The texture coordinate generation for all 4 coordinates is wrapped in a single chunk, including the optional plane parameters. It supports the standard OpenGL texture generation functions like object linear, eye linear, sphere map etc. In addition to those it is possible to specify a beacon (one of each coordinate axis). If the beacon is set, the plane parameter are interepreted to be in the local coordinate system of the beacon. The main use for this is to move the reference coordinate system for the texture coordinates around by moving another Node. It can also serve for generating texture coordinate relative to an object's position in the world, but independent of the camera. It is something between object linear, which uses the local coordinates before any transformations, and eye linear, which includes all transformations including the camera.

TextureChunk

The osg::TextureChunk contains a single texture image and it's related parameters, which include the filters and texture environment mode and color. 1,2 and 3 dimensional textures are handled by this chunk uniformly and textures can also automatically be scaled to the next power of two (for 2D textures). It can also handle a multi-frame osg::Image by selecting one of the frames. If necessary (i.e. if mipmappibng filters are used) mipmaps will be calculated automatically. Hint! Don't use mipmaps for fast changing textures (i.e. movies), as mipmap generation takes a lot of time.

Multiple texture chunks (right now 4) can be used simultaneously for multi-texturing.

Hint! To do multi-texturing in the absense of a specific multi-texture material you can just append additional texture chunks to a osg::ChunkMaterial or one of its descendents.

Textures can also be prioritized, which aids the OpenGL texture manager in cases where not all textures fit into texture memory. This is useful for scenes where a limited set of textures is used all the time and some other textures are only used sometimes. Giving the always used textures a higher priority can reduce the amount of texture transfer and significantly increase performance. In general the texture manager does a reasonable job, so unless you know exactly what you're doing, don't bother fiddling with the priority. Scenes that use more textures than fit into texture memory will always incur a noticable performance penalty. Hint! Currently it is not advisable to change the priority dynamically.

The TextureChunk supports the ARB_texture_env_combine (and ARB_texture_env_crossbar) extension. Use the env* Fields to set the parameters, see the OpenSG Extension registry for a detailed description (http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_combine.txt).

On systems that support it (i.e. nVidia cards) you can also use the texture shader extension(s). These are defined by the shader* Fields, see http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_shader.txt for a detailed description.

Note: to use the texture shaders, all active texture units need to have a valid shaderOperation (i.e. different from GL_NONE). Whether to enable shaders is triggered by the shaderOperation of texture unit 0.

TextureTransformChunk

Chunk for texture coordinate transformations, uses a simple matrix to transform texture coordinates.

Multiple texture transform chunks (right now 4) can be used simultaneously for multi-texturing.

TransformChunk

Chunk for transformations, uses a simple matrix to transform coordinates.

Note that these chunks are created by the system internally from the osg::Transform and osg::ComponentTransform cores and shouldn't be directly used by an application.

ProgramChunk

The OpenGL ARB has added two programmability extensions to the OpenGL core, which allows the users to replace the built-in vertex or fragment pipeline with their own programs. These extensions are extremely similar, and thus the common features have been implemented in an abstract base chunk, the osg::ProgramChunk.

The program is just a string, which can be directly set by the application, as a convenience it can be read from a file. It will only be compiled (and consequently checked for error) when it used for rendering the first time.

Depending on the type of program it has a differing set of specific parameters to work on, but they all have the ability to pass specific parameters from the outside. These have osg::Vec4f values and are just identified by an index. Usually they will be assigned to a named variable in the program to signify their meaning. To make their use easier to understand they can also be named in OpenSG, and can be accessed by their name. OpenSG does not (yet) try to find the name to index mapping automatically, the application is responsible for maintaing the correspondence here. The parametrs set in OpenSG are passed to the porgam as the ProgramLocalParameters. There is currently no way to change the ProgramEnvironmentParameters in OpenSG, as there is no central management instance.

VertexProgramChunk

The osg::VertexProgramChunk wraps the GL_ARB_vertex_program extension. The extension is much too big to be reproduced here (~100 pages), see the specification for details.

FragmentProgramChunk

The osg::FragmentProgramChunk wraps the GL_ARB_fragment_program extension. This extension is also much too big to be reproduced here (~100 pages), see the specification for details.
Generated on Thu Aug 25 04:12:27 2005 for OpenSG by  doxygen 1.4.3