| 1 |
#include <OSGConfig.h> |
|---|
| 2 |
|
|---|
| 3 |
using namespace OSG; |
|---|
| 4 |
|
|---|
| 5 |
/*! \defgroup GrpSystemState OpenGL State Handling |
|---|
| 6 |
\ingroup GrpSystem |
|---|
| 7 |
|
|---|
| 8 |
The OpenGL State Handling Group contains the wrapper classes for OpenGL |
|---|
| 9 |
state. |
|---|
| 10 |
|
|---|
| 11 |
See \ref PageSystemState for details. |
|---|
| 12 |
*/ |
|---|
| 13 |
|
|---|
| 14 |
/*! \page PageSystemState State Handling |
|---|
| 15 |
|
|---|
| 16 |
\latexonly Starter:NewChapter \endlatexonly |
|---|
| 17 |
|
|---|
| 18 |
One of the main tasks of a scene graph system is efficiently managing the OpenGL |
|---|
| 19 |
state. |
|---|
| 20 |
|
|---|
| 21 |
Every primitive is rendered using the currently active OpenGL state, which |
|---|
| 22 |
includes things like material parameters, textures, transformation matrices |
|---|
| 23 |
etc. Changing OpenGL state can be very expensive and should be minimized as |
|---|
| 24 |
much as possible. Primitives using the same OpenGL state set should be grouped |
|---|
| 25 |
together, so that changing the state is not needed. |
|---|
| 26 |
|
|---|
| 27 |
But on top of that it is necessary to sort the different state sets so that the |
|---|
| 28 |
changed when changing from one to the other are minimized, too. For example all |
|---|
| 29 |
objects using the same texture should be rendered close together, as loading a |
|---|
| 30 |
texture into the graphics board can take a long time. |
|---|
| 31 |
|
|---|
| 32 |
Thus the different state sets used by the visible objects should be sorted |
|---|
| 33 |
into a sequence that minimizes the state changes necessary. Unfortuneately |
|---|
| 34 |
that problem is NP-complete (it's equivalent to the Traveling Salesman |
|---|
| 35 |
Problem). \anchor StateChunk To simplify it the rather large OpenGL state is |
|---|
| 36 |
divided into a small number of parts. Elements of the state that are usually |
|---|
| 37 |
changed together are grouped into a osg::StateChunk. |
|---|
| 38 |
|
|---|
| 39 |
\anchor StateChunkClass Every type of osg::StateChunk has an associated |
|---|
| 40 |
osg::StateChunkClass. The osg::StateChunkClass is used to |
|---|
| 41 |
identify the osg::StateChunk and associate it with a name and a low integer |
|---|
| 42 |
numeric Id. Some types of chunks can be used simulatenously in multiple |
|---|
| 43 |
instances in OpenGL, e.g. light sources or textures (in a multi-texture |
|---|
| 44 |
environment). The maximum number of concurrently active slots of the |
|---|
| 45 |
osg::StateChunk type is also stored in the osg::StateChunkClass. |
|---|
| 46 |
|
|---|
| 47 |
\anchor State The complete OpenGL state wrapper is the osg::State. It |
|---|
| 48 |
primarily contains a vector of osg::StateChunks. For every type of chunk there |
|---|
| 49 |
are as many slots as possibly concurrently active copies of the chunk. A chunk |
|---|
| 50 |
can be \ref StateChunk::activate "activated", which sets the OpenGL state |
|---|
| 51 |
it covers to its settings, if the settings differ from an internally defined |
|---|
| 52 |
default state. It is possible to \ref StateChunk::changeFrom "switch" |
|---|
| 53 |
from one instance of a state chunk to another instance of the same type. This |
|---|
| 54 |
tries to optimize and minimize the changes, to speed up switching. The cost of |
|---|
| 55 |
switching can be \ref StateChunk::switchCost "estimated", currently that |
|---|
| 56 |
estimation will always be 0, though. Finally a chunk can be \ref |
|---|
| 57 |
StateChunk::deactivate "deactivated", which resets the OpenGL state it |
|---|
| 58 |
covers to the default value. All the chunks in a osg::State can be managed at |
|---|
| 59 |
the same time by using the equivalent methods of the osg::State. |
|---|
| 60 |
|
|---|
| 61 |
\ext To add new chunks you need to derive it from osg::StateChunk. It needs to |
|---|
| 62 |
keep a static instance of osg::StateChunkClass and implement the public |
|---|
| 63 |
osg::StateChunk::getClass() method to allow access to it. The |
|---|
| 64 |
osg::StateChunkClass needs to define the name of the new chunk class and the |
|---|
| 65 |
number of possible concurrently active chunks for the new class. To implement |
|---|
| 66 |
the actual behaviour the osg::StateChunk::activate(), |
|---|
| 67 |
osg::StateChunk::changeFrom() and osg::StateChunk::deactivate() methods are |
|---|
| 68 |
needed. The osg::StateChunk::switchCost() method is in there already, but the |
|---|
| 69 |
semantics are not defined yet, and it is not used. Implement it, but leave it |
|---|
| 70 |
empty and always return 0. |
|---|
| 71 |
|
|---|
| 72 |
You will probably need to handle OpenGL extensions, see \ref PageSystemOGLExt |
|---|
| 73 |
for details on how to do that. The convention for naming the static variables |
|---|
| 74 |
for holding the extension and extension function handles is \c |
|---|
| 75 |
_extExtensionName (e.g. \c _extBlendSubtract for the \c GL_EXT_blend_subtract, |
|---|
| 76 |
extension) and \c _funcFunctionName (e.g. \c _funcBlendColor for \c |
|---|
| 77 |
glBlendColor). |
|---|
| 78 |
|
|---|
| 79 |
\endext |
|---|
| 80 |
|
|---|
| 81 |
\hint If you want to use state chunks in the scene graph, you can attach them to |
|---|
| 82 |
a osg::ChunkMaterial or one of its descendents. \endhint |
|---|
| 83 |
|
|---|
| 84 |
\dev The main motivation for osg::StateChunk::changeFrom() is to allow optimizations in terms of |
|---|
| 85 |
state changes. When switching between chunks that have similar settings, only |
|---|
| 86 |
the differences need to be passed to OpenGL. When and where it makes sense to |
|---|
| 87 |
pass it to OpenGL anyway instead of checking is still an open topic. \enddev |
|---|
| 88 |
|
|---|
| 89 |
Every chunk has a number of parameter which are pretty directly mapped to |
|---|
| 90 |
OpenGL parameters. Thus in many cases OpenGL constants are used to define |
|---|
| 91 |
different parameter values and enumerations. This allows usage of some OpenGL |
|---|
| 92 |
extensions directly by supplying the correct constants. |
|---|
| 93 |
|
|---|
| 94 |
OpenGL uses explicit enabling in most situations. To get around having to keep |
|---|
| 95 |
extra variables for enabling the value GL_NONE is used in many places to |
|---|
| 96 |
indicate a disabled feature. The documentation of the chunk notes where this is |
|---|
| 97 |
possible. |
|---|
| 98 |
|
|---|
| 99 |
The different types of state chunks are: |
|---|
| 100 |
|
|---|
| 101 |
<ul> |
|---|
| 102 |
|
|---|
| 103 |
<li>\ref PageSystemBlendChunk</li> |
|---|
| 104 |
|
|---|
| 105 |
<li>\ref PageSystemClipPlaneChunk</li> |
|---|
| 106 |
|
|---|
| 107 |
<li>\ref PageSystemCubeTextureChunk</li> |
|---|
| 108 |
|
|---|
| 109 |
<li>\ref PageSystemLineChunk</li> |
|---|
| 110 |
|
|---|
| 111 |
<li>\ref PageSystemPointChunk</li> |
|---|
| 112 |
|
|---|
| 113 |
<li>\ref PageSystemLightChunk</li> |
|---|
| 114 |
|
|---|
| 115 |
<li>\ref PageSystemMaterialChunk</li> |
|---|
| 116 |
|
|---|
| 117 |
<li>\ref PageSystemPolygonChunk</li> |
|---|
| 118 |
|
|---|
| 119 |
<li>\ref PageSystemRegisterCombinersChunk</li> |
|---|
| 120 |
|
|---|
| 121 |
<li>\ref PageSystemTexGenChunk</li> |
|---|
| 122 |
|
|---|
| 123 |
<li>\ref PageSystemTextureChunk</li> |
|---|
| 124 |
|
|---|
| 125 |
<li>\ref PageSystemTextureTransformChunk</li> |
|---|
| 126 |
|
|---|
| 127 |
<li>\ref PageSystemTransformChunk</li> |
|---|
| 128 |
|
|---|
| 129 |
<li>\ref PageSystemProgramChunk</li> |
|---|
| 130 |
|
|---|
| 131 |
<ul> |
|---|
| 132 |
|
|---|
| 133 |
<li>\ref PageSystemVertexProgramChunk</li> |
|---|
| 134 |
|
|---|
| 135 |
<li>\ref PageSystemFragmentProgramChunk</li> |
|---|
| 136 |
|
|---|
| 137 |
</ul> |
|---|
| 138 |
|
|---|
| 139 |
</ul> |
|---|
| 140 |
|
|---|
| 141 |
\section PageSystemBlendChunk BlendChunk |
|---|
| 142 |
|
|---|
| 143 |
The osg::BlendChunk handles OpenGL blending, i.e. the definition how incoming |
|---|
| 144 |
fragments are combined with the pixel already in the frame buffer, including |
|---|
| 145 |
alpha culling. |
|---|
| 146 |
|
|---|
| 147 |
The wrapped OpenGL functions are glBlendFunc and glAlphaFunc, |
|---|
| 148 |
see their documentation for details. It also handles the common |
|---|
| 149 |
blending-related OpenGL extensions EXT_blend_color, ARB_imaging, |
|---|
| 150 |
EXT_blend_subtract, EXT_blend_minmax and EXT_blend_logic_op, when they are |
|---|
| 151 |
supported by the hardware. |
|---|
| 152 |
|
|---|
| 153 |
\section PageSystemClipPlaneChunk ClipPlaneChunk |
|---|
| 154 |
|
|---|
| 155 |
The osg::ClipPlaneChunk controls user-defined clipping. It uses a beacon |
|---|
| 156 |
osg::Node reference to control the cordinate system where the clipping plane |
|---|
| 157 |
is defined, this allows attaching the ClipPlane to another object to move it |
|---|
| 158 |
around. The clipping plane itself is defined in the standard (a,b,c,d) form |
|---|
| 159 |
used by OpenGL. 6 user defined clipping planes are possible. |
|---|
| 160 |
|
|---|
| 161 |
\section PageSystemCubeTextureChunk CubeTextureChunk |
|---|
| 162 |
|
|---|
| 163 |
The osg::CubeTextureChunk is similar to TextureChunk and uses the same |
|---|
| 164 |
osg::StateChunkClass |
|---|
| 165 |
(i.e. can be used instead of a osg::TextureChunk, but not both at the same |
|---|
| 166 |
time), but has 5 more texture images. Note that all textures have to be square |
|---|
| 167 |
and have to have the same resolution. The textures are accessed using 3D |
|---|
| 168 |
texture coordinates, which are usually created using a osg::TexGenChunk. |
|---|
| 169 |
|
|---|
| 170 |
Cube textures are an extension that is only available in newer hardware. They |
|---|
| 171 |
can not be emulated, thus they are ignored when they are not supported by the |
|---|
| 172 |
active window. |
|---|
| 173 |
|
|---|
| 174 |
\section PageSystemLightChunk LightChunk |
|---|
| 175 |
|
|---|
| 176 |
The osg::LightChunk contains the parameter set for a single light source. It's |
|---|
| 177 |
parameters are taken straight from the glLight() manpage. The maximum number |
|---|
| 178 |
of concurrently active lights is currently set to 8. |
|---|
| 179 |
|
|---|
| 180 |
Note that these chunks are created by the system internally from the osg::Light |
|---|
| 181 |
sources and shouldn't be directly used by an application. |
|---|
| 182 |
|
|---|
| 183 |
\section PageSystemLineChunk LineChunk |
|---|
| 184 |
|
|---|
| 185 |
The osg::LineChunk contains the parameters that are specificly set for lines. |
|---|
| 186 |
This includes line width, stippling and antialiasing. |
|---|
| 187 |
|
|---|
| 188 |
\section PageSystemPointChunk PointChunk |
|---|
| 189 |
|
|---|
| 190 |
The osg::PointChunk contains the parameters that are specific set for points. |
|---|
| 191 |
This includes point size and point antialiasing. |
|---|
| 192 |
|
|---|
| 193 |
It also wraps the ARB_point_parameters and NV_point_sprite extensions. |
|---|
| 194 |
|
|---|
| 195 |
ARB_point_parameters allows the specification of points whose size changes |
|---|
| 196 |
depending on the distance to the viewer, including the mapping of sizes smaller |
|---|
| 197 |
than a pixel to alpha. This is useful for objects rendered by points, e.g. |
|---|
| 198 |
particle systems or the so-called light point for runway lights in flight |
|---|
| 199 |
simulation. |
|---|
| 200 |
|
|---|
| 201 |
The actual size of the point is derived from its given size, which is devided |
|---|
| 202 |
by a the reciprocal of a quadratic expression of the distance to the point in |
|---|
| 203 |
eye coordinates (sepcified by constantAttenuation, linearAttenuation and |
|---|
| 204 |
quadraticAttenuation). This size is then clamped into the minSize, maxSize |
|---|
| 205 |
range and possible clamped against OpenGL's internal size constraints. If the |
|---|
| 206 |
calculated size was smaller than the minSize the point's alpha is reduced |
|---|
| 207 |
proportionally. |
|---|
| 208 |
|
|---|
| 209 |
\section PageSystemMaterialChunk MaterialChunk |
|---|
| 210 |
|
|---|
| 211 |
The osg::MaterialChunk controls the material parameters, i.e. the parameters |
|---|
| 212 |
for phong lighting as used by glMaterial(). It also covers the commonly used |
|---|
| 213 |
parameters to enable/disable lighting and switching the influence of geometry |
|---|
| 214 |
colors on lighting (glColorMaterial). When lighting is enabled external colors |
|---|
| 215 |
like osg::Geometry colors are only used for the diffuse lighting component. In |
|---|
| 216 |
the unlit case they are always used. |
|---|
| 217 |
|
|---|
| 218 |
\section PageSystemPolygonChunk PolygonChunk |
|---|
| 219 |
|
|---|
| 220 |
The osg::PolygonChunk contains the parameters that are specific set for filled |
|---|
| 221 |
surfaces, i.e. polygons. This includes face culling and front face definition |
|---|
| 222 |
as well as front and back face rendering modes, polygon antialiasing, offset |
|---|
| 223 |
and stippling. As there is only one set of offset parameters for all the |
|---|
| 224 |
primitives, the offsetting for points and lines is also handled in this chunk, |
|---|
| 225 |
which admittedly is a bit awkward. |
|---|
| 226 |
|
|---|
| 227 |
\section PageSystemRegisterCombinersChunk RegisterCombinersChunk |
|---|
| 228 |
|
|---|
| 229 |
The osg::RegisterCombinersChunk chunk is a direct mapping of the nVidia |
|---|
| 230 |
RegisterCombiners extension. It is based on the GL_NV_register_combiners2 |
|---|
| 231 |
extension, i.e. it also supports per-stage constants. |
|---|
| 232 |
|
|---|
| 233 |
\section PageSystemTexGenChunk TexGenChunk |
|---|
| 234 |
|
|---|
| 235 |
The osg::TexGenChunk wraps texture coordinate generation functions. The |
|---|
| 236 |
texture coordinate generation for all 4 coordinates is wrapped in a single |
|---|
| 237 |
chunk, including the optional plane parameters. It supports the standard OpenGL |
|---|
| 238 |
texture generation functions like object linear, eye linear, sphere map etc. In |
|---|
| 239 |
addition to those it is possible to specify a beacon (one of each coordinate |
|---|
| 240 |
axis). If the beacon is set, the plane parameter are interepreted to be in the |
|---|
| 241 |
local coordinate system of the beacon. The main use for this is to move the |
|---|
| 242 |
reference coordinate system for the texture coordinates around by moving |
|---|
| 243 |
another Node. It can also serve for generating texture coordinate relative to |
|---|
| 244 |
an object's position in the world, but independent of the camera. It is something |
|---|
| 245 |
between object linear, which uses the local coordinates before any |
|---|
| 246 |
transformations, and eye linear, which includes all transformations including |
|---|
| 247 |
the camera. |
|---|
| 248 |
|
|---|
| 249 |
\section PageSystemTextureChunk TextureChunk |
|---|
| 250 |
|
|---|
| 251 |
The osg::TextureChunk contains a single texture image and it's related |
|---|
| 252 |
parameters, which include the filters and texture environment mode and color. |
|---|
| 253 |
1,2 and 3 dimensional textures are handled by this chunk uniformly and |
|---|
| 254 |
textures can also automatically be scaled to the next power of two (for 2D |
|---|
| 255 |
textures). It can also handle a multi-frame osg::Image by selecting one of the |
|---|
| 256 |
frames. If necessary (i.e. if mipmappibng filters are used) mipmaps will be |
|---|
| 257 |
calculated automatically. \hint Don't use mipmaps for fast changing textures |
|---|
| 258 |
(i.e. movies), as mipmap generation takes a lot of time. \endhint |
|---|
| 259 |
|
|---|
| 260 |
Multiple texture chunks (right now 4) can be used simultaneously for |
|---|
| 261 |
multi-texturing. |
|---|
| 262 |
|
|---|
| 263 |
\hint To do multi-texturing in the absense of a specific multi-texture |
|---|
| 264 |
material you can just append additional texture chunks to a osg::ChunkMaterial |
|---|
| 265 |
or one of its descendents. \endhint |
|---|
| 266 |
|
|---|
| 267 |
Textures can also be prioritized, which aids the OpenGL texture manager in |
|---|
| 268 |
cases where not all textures fit into texture memory. This is useful for |
|---|
| 269 |
scenes where a limited set of textures is used all the time and some other |
|---|
| 270 |
textures are only used sometimes. Giving the always used textures a higher |
|---|
| 271 |
priority can reduce the amount of texture transfer and significantly increase |
|---|
| 272 |
performance. In general the texture manager does a reasonable job, so unless |
|---|
| 273 |
you know exactly what you're doing, don't bother fiddling with the priority. |
|---|
| 274 |
Scenes that use more textures than fit into texture memory will always incur a |
|---|
| 275 |
noticable performance penalty. \hint Currently it is not advisable to change |
|---|
| 276 |
the priority dynamically. \endhint |
|---|
| 277 |
|
|---|
| 278 |
The TextureChunk supports the ARB_texture_env_combine (and |
|---|
| 279 |
ARB_texture_env_crossbar) extension. Use the env* Fields to set the |
|---|
| 280 |
parameters, see the OpenSG Extension registry for a detailed description |
|---|
| 281 |
(http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_combine.txt). |
|---|
| 282 |
|
|---|
| 283 |
On systems that support it (i.e. nVidia cards) you can also use the texture |
|---|
| 284 |
shader extension(s). These are defined by the shader* Fields, see |
|---|
| 285 |
http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_shader.txt for a |
|---|
| 286 |
detailed description. |
|---|
| 287 |
|
|---|
| 288 |
Note: to use the texture shaders, all active texture units need to have a |
|---|
| 289 |
valid shaderOperation (i.e. different from GL_NONE). Whether to enable |
|---|
| 290 |
shaders is triggered by the shaderOperation of texture unit 0. |
|---|
| 291 |
|
|---|
| 292 |
\section PageSystemTextureTransformChunk TextureTransformChunk |
|---|
| 293 |
|
|---|
| 294 |
Chunk for texture coordinate transformations, uses a simple matrix to |
|---|
| 295 |
transform texture coordinates. |
|---|
| 296 |
|
|---|
| 297 |
Multiple texture transform chunks (right now 4) can be used simultaneously for |
|---|
| 298 |
multi-texturing. |
|---|
| 299 |
|
|---|
| 300 |
\section PageSystemTransformChunk TransformChunk |
|---|
| 301 |
|
|---|
| 302 |
Chunk for transformations, uses a simple matrix to transform coordinates. |
|---|
| 303 |
|
|---|
| 304 |
Note that these chunks are created by the system internally from the |
|---|
| 305 |
osg::Transform and osg::ComponentTransform cores and shouldn't be directly |
|---|
| 306 |
used by an application. |
|---|
| 307 |
|
|---|
| 308 |
|
|---|
| 309 |
\section PageSystemProgramChunk ProgramChunk |
|---|
| 310 |
|
|---|
| 311 |
The OpenGL ARB has added two programmability extensions to the OpenGL core, |
|---|
| 312 |
which allows the users to replace the built-in vertex or fragment pipeline |
|---|
| 313 |
with their own programs. These extensions are extremely similar, and thus the |
|---|
| 314 |
common features have been implemented in an abstract base chunk, the |
|---|
| 315 |
osg::ProgramChunk. |
|---|
| 316 |
|
|---|
| 317 |
The program is just a string, which can be directly set by the application, |
|---|
| 318 |
as a convenience it can be read from a file. It will only be compiled (and |
|---|
| 319 |
consequently checked for error) when it used for rendering the first time. |
|---|
| 320 |
|
|---|
| 321 |
Depending on the type of program it has a differing set of specific parameters |
|---|
| 322 |
to work on, but they all have the ability to pass specific parameters from the |
|---|
| 323 |
outside. These have osg::Vec4f values and are just identified by an index. |
|---|
| 324 |
Usually they will be assigned to a named variable in the program to signify |
|---|
| 325 |
their meaning. To make their use easier to understand they can also be named in |
|---|
| 326 |
OpenSG, and can be accessed by their name. OpenSG does not (yet) try to find |
|---|
| 327 |
the name to index mapping automatically, the application is responsible for |
|---|
| 328 |
maintaing the correspondence here. The parametrs set in OpenSG are passed to |
|---|
| 329 |
the porgam as the ProgramLocalParameters. There is currently no way to change |
|---|
| 330 |
the ProgramEnvironmentParameters in OpenSG, as there is no central management |
|---|
| 331 |
instance. |
|---|
| 332 |
|
|---|
| 333 |
\section PageSystemVertexProgramChunk VertexProgramChunk |
|---|
| 334 |
|
|---|
| 335 |
The osg::VertexProgramChunk wraps the GL_ARB_vertex_program extension. The |
|---|
| 336 |
extension is much too big to be reproduced here (~100 pages), see the |
|---|
| 337 |
<a HREF="http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_program.txt"> |
|---|
| 338 |
specification</A> for details. |
|---|
| 339 |
|
|---|
| 340 |
\section PageSystemFragmentProgramChunk FragmentProgramChunk |
|---|
| 341 |
|
|---|
| 342 |
The osg::FragmentProgramChunk wraps the GL_ARB_fragment_program extension. This |
|---|
| 343 |
extension is also much too big to be reproduced here (~100 pages), see the |
|---|
| 344 |
<a HREF="http://oss.sgi.com/projects/ogl-sample/registry/ARB/fragment_program.txt"> |
|---|
| 345 |
specification</A> for details. |
|---|
| 346 |
|
|---|
| 347 |
*/ |
|---|