Advanced features in opengl

37
levon altunyan SPECIAL FEATURES IN OPENGL

description

 

Transcript of Advanced features in opengl

Page 1: Advanced features in opengl

levon altunyan

S P E C I A L F E AT U R E S I N O P E N G L

Page 2: Advanced features in opengl

S P E C I A L F E AT U R E S I N O P E N G L

levon altunyan

Homework

Abteilung Informatik und AngewandteKognitionswissenschaft Lehrstuhl Computergraphik u.

Wissenschaftliches RechnenFaculty of Engineering

University of Duisburg-Essen

April 24, 2009, 2009 - Juni 18, 2009

Page 3: Advanced features in opengl

Levon Altunyan: Special features in OpenGL, Homework, © April 24,2009, 2009 - Juni 18, 2009

supervisors:Prof. Dr. Wolfram Luther

location:campus Duisburg

time frame:April 24, 2009, 2009 - Juni 18, 2009

Page 4: Advanced features in opengl

C O N T E N T S

i introduction 1

1 introduction 2

ii special features in opengl 3

2 improving performance 4

2.1 Display List 5

2.2 Vertex Arrays 6

2.3 Marbles Example 8

3 alpha blending and antialiasing 13

3.1 Changing the Blending Equation 14

3.2 Disk Blender 15

4 Fog 17

4.1 Fog Equations 18

4.2 Fog Coordinates 18

5 Selection and Feedback 20

5.1 Selection 20

5.2 The Basic Steps 23

5.3 Feedback 23

5.4 The Feedback Buffer 24

5.5 Feedback Data 24

6 Fragment Operations 26

6.1 Multisample Operations 26

6.2 Alpha Test 27

6.3 Stencil Test 27

6.4 Dissolve Effect with Stencil Buffer 28

7 summary 31

bibliography 32

iv

Page 5: Advanced features in opengl

L I S T O F F I G U R E S

Figure 1 Arrays for position, color, and texture coordi-nate attributes 6

Figure 2 Triangle Strip 7

Figure 3 Immediate Mode [2] 9

Figure 4 Vertex Array On [2] 10

Figure 5 Display Lists On [2] 11

Figure 6 Disk Blender - Example 1 16

Figure 7 Disk Blender - Example 2 16

Figure 8 Fog Example [2] 19

Figure 9 Selection Hierchy [4] 22

Figure 10 Selection Example [1] 24

Figure 11 Using Stencil to Dissolve Between Images [5] 29

L I S T O F TA B L E S

Table 1 Valid Vertex Array Sizes and Data Types 8

Table 2 OpenGL Blending Factors 14

Table 3 Available Blend Equation Modes 15

Table 4 Three OpenGL Supported Fog Equations 18

Table 5 Feedback Buffer Types 25

Table 6 Feedback Buffer Tokens 25

Table 7 Fragment Test 27

Table 8 Stencil Update Values 28

A C R O N Y M S

API Application Programming Interface

v

Page 6: Advanced features in opengl

Part I

I N T R O D U C T I O N

Page 7: Advanced features in opengl

1I N T R O D U C T I O N

OpenGL (Open Graphics Library) is a standard specification defininga cross-language, cross-platform API for writing applications thatproduce 2D and 3D computer graphics. The interface consists of over250 different function calls which can be used to draw complex three-dimensional scenes from simple primitives. OpenGL was developedby Silicon Graphics Inc. (SGI) and is widely used in CAD, virtualreality, scientific visualization, information visualization, and flightsimulation. It is also used in video games, where it competes withDirect3D on Microsoft Windows platforms.The features which OpenGL provides can be divided to two differentbig groups - basic and special ones. This work is dealing with someof the functions which fall into the group of advanced methods. Sincethe list of topics which are under the special features category is vast,the number of discussed topics is restricted to the most importantones suggested in literature [6].

2

Page 8: Advanced features in opengl

Part II

S P E C I A L F E AT U R E S I N O P E N G L

Page 9: Advanced features in opengl

2I M P R O V I N G P E R F O R M A N C E

Fundamental progresshas to do

with the reinterpretation of basic ideas.

— Alfred North Whitehead

In this section two techniques (display lists and vertex arrays code)for optimization of the OpenGL code will be described. Furthermore,the information and procedures needed to render geometry struc-tures will be explained. Moreover, an example which uses the listedmethods will be given.

In many graphics applications, and in virtually all games, main-taining an interactive frame rate and smooth animation is of utmostimportance. Although rapid advancements in graphics hardwarehave lessened the need to optimize every single line of code, pro-grammers still need to focus on writing efficient code that, throughthe graphics Application Programming Interface (API), harnesses thefull power of the underlying hardware. The work done every timeyou call an OpenGL command is not inconsequential. Commandsare compiled, or converted, from OpenGL’s high-level commandlanguage into low-level hardware commands understood by thehardware. For complex geometry, or just large amounts of vertexdata, this process is performed many thousands of times, just todraw a single image on screen. This is, of course, the aforementionedproblem with immediate mode rendering. How does our new knowl-edge of the command buffer help with this situation? Often, thegeometry or other OpenGL data remains the same from frame toframe. For example, a spinning torus is always composed of thesame set of triangle strips, with the same vertex data, recalculatedwith expensive trigonometric functions every frame. The only thingchanging frame to frame is the model view matrix. A solution to thisneedlessly repeated overhead is to save a chunk of precomputed datafrom the command buffer that performs some repetitive renderingtask, such as drawing the torus. This chunk of data can later becopied back to the command buffer all at once, saving the manyfunction calls and compilation work done to create the data. OpenGLprovides a facility to create a preprocessed set of OpenGL commands(the chunk of data) that can then be quickly copied to the commandbuffer for more rapid execution.

4

Page 10: Advanced features in opengl

2.1 display list 5

2.1 display list

This precompiled list of commands is called a display list, and cre-ating one or more of them is an easy and straightforward process,which has the following properties:

• Used in immediate mode to organize data and improve perfor-mance

• Maximize performance by knowing when and how to usedisplay lists

• Reduce cost of repeatedly transmitting data over a network ifrepeatedly used commands are stored in a display list.

Some graphics hardware may store display lists in dedicated memoryor may store the data in an optimized form that is more compatiblewith the graphics hardware or software. The advantages of displaylist can be divided to the following groups suggested by [1]:

• Matrix operations. Most matrix operations require OpenGL tocompute inverses. Both the computed matrix and its inversemight be stored by a particular OpenGL implementation in adisplay list.

• Raster bitmaps and images. The format in which the raster datais specified is not likely to be the ideal one for the hardware.When a display list is compiled, OpenGL might transform thedata into the representation preferred by the hardware. Thiscan have a significant effect on the speed of raster characterdrawing, since character strings usually consist of a series ofsmall bitmaps.

• Lights, material properties, and lighting models. When a sceneis drawn with complex lighting conditions one might changethe materials for each item in the scene. Setting the materialscan be slow since it might involve significant calculations. If weput the material definitions in display lists, these calculationsdon’t have to be done each time we switch materials, since onlythe results of the calculations need to be stored; as a result,rendering light scene might be faster.

• Polygon stipples patterns.

Furthermore, the user should also consider the following disadvan-tages:

Page 11: Advanced features in opengl

2.2 vertex arrays 6

• Very small lists may not perform well since there is someoverhead when executing a list

• Immutability of the contents of a display list.

– Display list cannot be changed and their contents cannotbe read.

– If data needs to be maintained separately from the displaylist (e.g. continued data processing) then a lot of additionalmemory may be required.

2.2 vertex arrays

Figure 1: Arrays for position, color, and texture coordinate attributes

The second method to optimize an OpenGL code is the use ofvertex arrays. OpenGL requires many function calls to render geo-metric primitives. OpenGL has vertex array routines that allow usto specify a lot of vertex related data with just a few arrays and toaccess that data with equally few function calls. Assuming the caseof a mesh which represents a triangle strip illustrated in Figure 2,each of the circled vertices is a redundant vertex. In other words,each of these vertices is shared by more than three triangles, butsince a triangle strip can represent, at most, three triangles per vertex,each of the circled vertices needs to be sent to the video card morethan once. This results in using additional bandwidth to send the

Page 12: Advanced features in opengl

2.2 vertex arrays 7

Figure 2: Triangle Strip

data to the video card. In addition, the vertex is likely to transformedand lit more than once. These two operations waste bandwidth andprocessing cycles. To address these issues, OpenGL include vertexarrays. Vertex arrays offer the following advantages:

• Large batches of data can be sent with a small number offunction calls.

• Through the use of indexed vertex arrays, vertices can be sendexactly once per triangle mesh, reducing bandwidth and po-tentially avoiding redundant transformation and lighting.

Using vertex array routines, all 20 vertices in a 20-sided polygon canbe put into one array and called with one function. If each vertexalso has a surface normal, all 20 surface normals can be put intoanother array and also called with one function. Arranging datain vertex arrays may increase the performance of the application.Using vertex arrays reduces the number of function calls, whichimproves performance. Also, using vertex arrays may allow reuseof already processed shared vertices. There are three steps to usingvertex arrays to render geometry:

1. Activate (enable) up to eight arrays, each storing a differenttype of data: vertex coordinates, surface normals, RGBA col-ors, secondary colors, color indices, fog coordinates, texturecoordinates, or polygon edge flags.

2. Put data into the array or arrays. The arrays are accessed by theaddresses of (that is, pointers to) their memory locations. In theclient-server model, this data is stored in the client’s addressspace.

Page 13: Advanced features in opengl

2.3 marbles example 8

3. Draw geometry with the data. OpengGL obtains the data fromall activated arrays by dereferencing the pointers. In the client-server model, the data is transferred to the servers addressspace. There are three ways to do this:

• Accessing individual array elements (randomly hoppingaround)

• Creating a list of individual array elements (methodicallyhopping around)

• Processing sequential array elements

The dereferencing method of choice may depend on the type ofproblem which is encountered. Version 1.4 of OpenGL adds supportfor multiple array access from a single function call. [1]

Table 1: Valid Vertex Array Sizes and Data TypesCommand Elements Valid Data Types

glColorPointer 3,4 GL_BYTE,GL_UNSIGNED_BYTE,GL_SHORT ,GL_UNSIGNED_SHORT ,

GL_INT ,GL_UNSIGNED_INT ,GL_FLOAT ,GL_DOUBLE

glEdgeFlagPointer 1 None specified (always GLboolean)glFogCoordPointer 1 GL_FLOAT ,GL_DOUBLE

glNormalPointer 3 GL_BYTE,GL_SHORT ,GL_INT ,GL_FLOAT ,GL_DOUBLE,

glSecondaryColorPointer 3 GL_BYTE,GL_UNSIGNED_BYTE,GL_SHORT ,GL_INT ,GL_UNSIGNED_INT ,

GL_FLOAT ,GL_DOUBLE

glTexCoordPointer 1,2,3,4 GL_SHORT ,GL_INT

GL_FLOAT ,GL_DOUBLE,glVertexPointer 2,3,4 GL_SHORT ,GL_INT ,

GL_FLOAT ,GL_DOUBLE,

With the discussed methods, the vertex arrays will look similar toFigure 1, with each vertex attribute stored in a separate array. Eachof these arrays is passed independently via one of the gl*Pointer()functions, and when a draw command is made, OpenGL assemblesdata from each array to form complete vertices.

2.3 marbles example

As an example of the use of Display lists and Vertex arrays a shortdemo program (Marbles) presented by Astle et al. [2] is included.A large number of bouncing marbles inside a glass case with a

Page 14: Advanced features in opengl

2.3 marbles example 9

Figure 3: Immediate Mode [2]

mirrored floor is drawn. Each marble shared the same data but iscolored and positioned independently. Immediate mode is used bydefault. Using the following keys enable the vertex array and displaylist special features:<SPACE> Toggles vertex arrays for the marbles using glDrawEle-ments().<TAB> Toggles display lists for everything.<C> Toggles compiled vertex arrays.A definite improvement in frame rate when enabling vertex arrays

should be observed on fig. 4. Display lists (fig. 5) may or may not im-prove performance, depending on the underlying hardware. Whendisplay lists are enabled, the marbles freeze in place. This is dueto the fact that each marble is positioned independently inside ofthe display list. Once the display list is compiled, the data within itcan’t be changed, so the marbles can’t move relative to each other.However, the marbles can be moved as a group. Furthermore, whenenabling compiled vertex arrays, the marble colors may change to asingle color. This is because all of the marbles share the same base setof data. When the vertices get locked and cached away, the changesin the material may not get picked up. Let’s look at the most relevantcode for this example. First, after generating marbles, the vertexarrays are set up as follows:

bool CGfxOpenGL::Init(){...InitializeMarbles():

Page 15: Advanced features in opengl

2.3 marbles example 10

Figure 4: Vertex Array On [2]

glVertexPointer(3, GL_FLOAT, 0, m_positions);glNormalPointer(GL_FLOAT, 0, m_texCoords);glTexCoordPointer(3, GL_FLOAT, 0, m_texCoords);...}

The texture coordinate data is being used for both texture coordi-nates and normals because with cube-mapped spheres, the valuesare idenctical.The relevant code for display lists happens in Render(), as shownbelow:

void CGfxOpenGL::Render(){...if (m_useList){// use the existing list if there is oneif (m_list){glCallList(m_list);return;}else // otherwise, create a new one{m_list = glGenLists(1);glNewList(m_list, GL_COMPILE_AND_EXECUTE);

Page 16: Advanced features in opengl

2.3 marbles example 11

Figure 5: Display Lists On [2]

}}

glLightfv(GL_LIGHTO, GL_POSITION, LIGHT_POSITION);

DrawFloor();DrawReflection();DrawMarbles(GL_FALSE);DrawBox();

if(m_useList)glEndList();

Finally, the vertex arrays are put to use inside of DrawMarbles():

void CGfxOpenGL::DrawSphere(){if (m_useVertexArrays){for (int i = 0; i < m_numStrips; ++i){glDrawElements(GL_TRIANGLE_STRIP, m_vertsPerStrip,GL_UNSIGNED_INT, &m_indexArray[i * m_vertsPerStrip]);}}else // draw using immediate mode instead{

Page 17: Advanced features in opengl

2.3 marbles example 12

for (int i = 0 ; i < m_numStrips; ++i){glBegin(GL_TRIANGLE_STRIP);for (int j = 0; j < m_vertsPerStrip; ++j){int index = m_indexArray[i * m_vertsPerStrip + j];glNormal3fv(m_texCoords[index].v);glTexCoord3fv(m_texCoords[index].v);glVertex3fv(m_positions[index].v);}glEnd();}}}

Page 18: Advanced features in opengl

3A L P H A B L E N D I N G A N D A N T I A L I A S I N G

The blending function combines color values from a source and a des-tination. The final effect is that parts of our scene appear translucent.The color blending functions support effects such as transparencythat can be used to simulate windows, drink glasses, and other trans-parent objects. Blending in OpenGL provides pixel-level control ofRGBA color storage in the color buffer. Blending operations cannotbe used in color index mode and are disabled in color index win-dows. To enable blending in RGBA windows, you must first callglEnable(GL_BLEND). After this, you call glBlendFunc with twoarguments: the source and the destination colors’ blending functions.By default, these arguments are GL_ONE and GL_ZERO, respec-tively, which is equivalent to glDisable(GL_BLEND). Transparencyis perhaps the most typical use of blending, often used for windows,bottles, and other 3D objects that you can see through. Transparencycan also be used to combine multiple images, or for "soft" brushes ina paint program. This combination takes the source color and scalesit based on the alpha component, and then adds the destinationpixel color scaled by 1 minus the alpha value. Stated more simply,this blending function takes a fraction of the current drawing colorand overlays it on the pixel on the screen. The alpha component ofthe color can be from 0 (completely transparent) to 1 (completelyopaque), as follows:Rdestination = Rsource ∗Asource + Rdestination ∗ (1−Asource)Gdestination = Gsource ∗Asource +Gdestination ∗ (1−Asource)Bdestination = Bsource ∗Asource +Bdestination ∗ (1−Asource)Because only the source alpha component is used, there is no needthat the underlying graphics board supports alpha color planes inthe color buffer. This is important because the standard MicrosoftOpenGL implementation does not support alpha color planes. Some-thing to remember with alpha-blended transparency is that thenormal depth-buffer test can interfere with the effect you’re trying toachieve. To make sure that transparent polygons and lines are drawnproperly, they should be always drawn from back to front.

Table 2 may seem a bit bewildering, so let’s look at a commonblending function combination described by Wright et al.[3]:glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);This function tells OpenGL to take the source (incoming) color andmultiply the color (the RGB values) by the alpha value. Add this tothe result of multiplying the destination color by one minus the alphavalue from the source. Say, for example, that one has the color Red

13

Page 19: Advanced features in opengl

3.1 changing the blending equation 14

Table 2: OpenGL Blending FactorsFunction RGB Blend Factors: Alpha Blend Factor:

GL_ZERO (0,0,0) 0

GL_ONE (1,1,1) 1

GL_SRC_COLOR (Rs,Gs,Bs) As

GL_ONE_MINUS_SRC_COLOR (1, 1, 1) − (Rs,Gs,Bs) 1−As

GL_DST_COLOR (Rd,Gd,Bd) Ad

GL_ONE_MINUS_DST_COLOR (1, 1, 1) − (Rd,Gd,Bd) Ad

GL_SRC_ALPHA (As,As,As) As

GL_ONE_MINUS_SRC_ALPHA (1, 1, 1) − (As,As,As) 1−As

GL_DST_ALPHA (Ad,Ad,Ad) Ad

GL_ONE_MINUS_DST_ALPHA (1, 1, 1) − (Ad,Ad,Ad) 1−Ad

GL_CONSTANT_COLOR (Rc,Gc,Bc) Ac

GL_ONE_MINUS_CONSTANT_COLOR (1, 1, 1) − (Rc,Gc,Bc) 1−Ac

GL_CONSTANT_ALPHA (Ac,Ac,Ac) Ac

GL_ONE_MINUS_CONSTANT_ALPHA (1, 1, 1) − (Ac,Ac,Ac) 1−Ac

GL_SRC_ALPHA_SATURATE (f,f,f)11

1 Where f=min(As,1−Ad)

(1.0f, 0.0f, 0.0f, 0.0f) already in the color buffer. This is the destinationcolor, or Cd. If something is drawn over this with the color blueand an alpha of 0.6 (0.0f, 0.0f, 1.0f, 0.6f),the final color would becomputed as shown here:Cd = destination color = (1.0f, 0.0f, 0.0f, 0.0f)Cs = source color = (0.0f, 0.0f, 1.0f, 0.6f)S = source alpha = 0.6D = one minus source alpha = 1.0 - 0.6 = 0.4Now, the equationCf = (Cs * S) + (Cd * D)evaluates toCf = (Blue * 0.6) + (Red * 0.4)The final color is a scaled combination of the original red value andthe incoming blue value. The higher the incoming alpha value, themore of the incoming color is added and the less of the original coloris retained. This blending function is often used to achieve the effectof drawing a transparent object in front of some other opaque object.This technique does require, however, that you draw the backgroundobject or objects first and then draw the transparent object blendedover the top. [3]

3.1 changing the blending equation

The blending equation showed earlier, is the default blending equa-tion. One can actually choose from five different blending equations,

Page 20: Advanced features in opengl

3.2 disk blender 15

Table 3: Available Blend Equation Modes

Mode Function:GL_FUNC_ADD (default) Cf = (Cs ∗ S) + (Cd ∗D)

GL_FUNC_SUBTRACT Cf = (Cs ∗ S) − (Cd ∗D)

GL_FUNC_REVERSE_SUBTRACT Cf = (Cs ∗D) − (Cd ∗ S)GL_MIN Cf = min(Cs,Cd)

GL_MAX Cf = max(Cs,Cd)

each given in Table 3 and selected with the following function: voidglBlendEquation(GLenum mode);

In addition to glBlendFunc, one has even more flexibility with thisfunction:void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenumsrcAlpha, GLenum dstAlpha);Whereas glBlendFunc specifies the blend functions for source anddestination RGBA values, glBlendFuncSeparate allows to specifyblending functions for the RGB and alpha components separately.Finally, as shown in Table 3, the GL_CONSTANT_COLOR,GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA,and GL_ONE_MINUS_CONSTANT_ALPHA values all allow a con-stant blending color to be introduced to the blending equation. Thisconstant blending color is initially black (0.0f, 0.0f, 0.0f, 0.0f), but itcan be changed with this function: void glBlendColor(GLclampf red,GLclampf green, Glclampf blue, GLclampf alpha); [3]

3.2 disk blender

To demonstrate some of the many blending combinations the diskblender example is included [2]. Disk blender is drawn with a blackbackground with an alpha of 1.0. A green disk with some trans-parency is drawn first, without blending. Then a semi-transparentred disk is drawn on top of it with blending enabled. By pressingthe S, D, and E keys, one can cycle through all of the available sourcefactors, destination factors, and blend equations. Screenshots of theprogram are shown in Figures 6 and 7.

Page 21: Advanced features in opengl

3.2 disk blender 16

Figure 6: Src:GL_SRC_ALPHA Dst:GL_ONE_MINUS_SRC_ALPHAEqn:GL_FUNC_ADD [2]

Figure 7: Src:GL_ZERO Dst:GL_ONE_MINUS_SRC_ALPHA Eqn:GL_MIN[2]

Page 22: Advanced features in opengl

4F O G

Another easy-to-use special effect that OpenGL supports is fog. Withfog, OpenGL blends a fog color that one specifies with geometryafter all other color computations have been completed. The amountof the fog color mixed with the geometry varies with the distance ofthe geometry from the camera origin. The result is a 3D scene thatappears to contain fog. Fog can be useful for slowly obscuring ob-jects as they "disappear" into the background fog; or a slight amountof fog will produce a hazy effect on distant objects, providing apowerful and realistic depth cue. Turning fog on and off is as easyas using the following functions: glEnable/glDisable(GL_FOG);The means of changing fog parameters (how the fog behaves) is touse the glFog function. There are several variations on glFog:void glFogi(GLenum pname, GLint param);void glFogf(GLenum pname, GLfloat param);void glFogiv(GLenum pname, GLint* params);void glFogfv(GLenum pname, GLfloat* params);First the use of glFog is shown glFogfv(GL_FOG_COLOR, fLow-Light); // Set fog color to match background When used with theGL_FOG_COLOR parameter, this function expects a pointer to anarray of floating-point values that specifies what color the fog shouldbe. Here, we used the same color for the fog as the backgroundclear color. If the fog color does not match the background (there isno strict requirement for this), as objects become fogged, they willbecome a fog-colored silhouette against the background. Next onecan specify for example how far away an object must be before fogis applied and how far away the object must be for the fog to befully applied (where the object is completely the fog color), with thefollowing lines:glFogf(GL_FOG_START, 5.0f); // How far away does the fog startglFogf(GL_FOG_END, 30.0f); // How far away does the fog stopThe parameter GL_FOG_START specifies how far away from theeye fogging begins to take effect, and GL_FOG_END is the distancefrom the eye where the fog color completely overpowers the colorof the object. The transition from start to end is controlled by thefog equation. A typical use is the linear fog equation specified withGL_LINEAR: glFogi(GL_FOG_MODE,GL_LINEAR); // Which fogequation to use [3]

17

Page 23: Advanced features in opengl

4.1 fog equations 18

Table 4: Three OpenGL Supported Fog Equations

Fog Mode: Fog Equation:GL_LINEAR f =

(end−c)(end−start)

GL_EXP f = e(−d∗c)

GL_EXP2 f = e(−d∗c)2

4.1 fog equations

The fog equation calculates a fog factor that varies from 0 to 1 as thedistance of the fragment moves between the start and end distances.OpenGL supports three fog equations: GL_LINEAR, GL_EXP, andGL_EXP2. These equations are shown in Table 4.

In these equations, c is the distance of the fragment from the eyeplane, end is the GL_FOG_END distance, and start is the GL_FOG_STARTdistance. The value d is the fog density. Fog density is typically setwith glFogf: glFogf(GL_FOG_DENSITY, 0.5f); From the equationsabove one can note that GL_FOG_START and GL_FOG_END onlyhave an effect on GL_LINEAR fog. The distance to a fragment fromthe eye plane can be calculated in one of two ways. Some imple-mentations (notably NVIDIA hardware) will use the actual fragmentdepth. Other implementations (notably many ATI chipsets) use thevertex distance and interpolate between vertices. The former methodis sometimes referred to as fragment fog; and the later, vertex fog.Fragment fog requires more work than vertex fog, but often has ahigher quality appearance. Both of the previously mentioned im-plementations honor the glHint parameter GL_FOG_HINT. To ex-plicitly request fragment fog (better looking, but more work), callglHint(GL_FOG_HINT, GL_NICEST);For faster, less precise fog, one would call glHint(GL_FOG_HINT,GL_FASTEST);Remember that hints are implementation dependent, may changeover time, and are not required to be acknowledged or used by thedriver at all. Indeed, you can’t even rely on which fog method willbe the default! [3]

4.2 fog coordinates

Rather than letting OpenGL calculate fog distance, one can actuallydo this hiself. This value is called the fog coordinate and can be setmanually with the function glFogCoordf:void glFogCoordf(Glfloat fFogDistance);Fog coordinates are ignored unless one changes the fog coordinatesource with this function call:

Page 24: Advanced features in opengl

4.2 fog coordinates 19

Figure 8: Fog Example [2]

glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD); // use glFogCo-ord1fTo return to OpenGL-derived fog values, change the last param-eter to GL_FRAGMENT_DEPTH: glFogi(GL_FOG_COORD_SRC,GL_FRAGMENT_DEPTH);This fog coordinate when specified is used as the fog distance inthe equations of Table 4. Specifying own fog distance allows one tochange the way distance is calculated. For example, one may wantelevation to play a role, lending to volumetric fog effects.

The fog example on fig.8 shows several different examples of usingfog. A simple heightmap-based terrain, with a large quad drawn inblue at ground level to represent water, is being rendered. The topleft panel shows the terrain without any fog, the top right panel usesGL_LINEAR fog, the bottom left panel shows GL_EXP fog with afairly low density, and the bottom right panel shows GL_EXP2 fogwith fog coordinates set so that the fog is thicker where the terrainsis lower (near the water), thinning quickly at higher elevations. As aconclusion one can use fog to allow object to fade to a backgroundcolor as they get farther away, allowing the use of a smaller viewfrustum and thus avoiding having object pop into view as they enterthe frustum. Fog is controlled through gl_Fog(). One can take greatercontrol over how fog is calculated by using fog coordinates.[2]

Page 25: Advanced features in opengl

5S E L E C T I O N A N D F E E D B A C K

Selection and feedback are two powerful features of OpenGL thatenable to facilitate the user’s active interaction with a scene. Selectionand picking are used to identify an object or region of a scene inOpenGL coordinates rather than just window coordinates. Feedbackreturns valuable information about how an object or a primitiveis actually drawn in the window. One can use this informationto implement features such as annotations or bounding boxes inthe scene. One should note that the features in this chapter aretypically implemented in software (the driver), even for hardwareaccelerated OpenGL implementations. This means that rendering inselection mode, for example, will be very slow compared to hardwarerendering. A common means of accounting for this is to render lowerresolution "proxies," and render only objects that can be clicked onwhen performing selection. There are more advanced means ofdetermining object selection that may be preferable for real-timepicking. Using the techniques in this chapter makes adding this kindof functionality to the application fairly straightforward. One mayalso find that even with software rendering, the response time frommouse click may be more than fast enough for most purposes.[4]

5.1 selection

Selection is actually a rendering mode, but in selection mode, nopixels are actually copied to the frame buffer. Instead, primitives thatare drawn within the viewing volume (and thus would normallyappear in the frame buffer) produce hit records in a selection buffer.This buffer, unlike other OpenGL buffers, is just an array of integervalues. One must set up this selection buffer in advance and namethe primitives or the groups of primitives (objects or models) so theycan be identified in the selection buffer. After that the selection bufferis parsed to determine which objects intersected the viewing volume.After that the selection buffer is parsed to determine which objectsintersected the viewing volume. Named objects that do not appearin the selection buffer fell outside the viewing volume and wouldnot have been drawn in render mode. For picking, one specifies aviewing volume that corresponds to a small space beneath the mousepointer and then checks which named objects are rendered withinthat space. OpenGL supports an object selection mechanism in whichthe object geometry is transformed and compared against a selection

20

Page 26: Advanced features in opengl

5.1 selection 21

subregion (pick region) of the viewport. The mechanism uses thetransformation pipeline to compare object vertices against the viewvolume. To reduce the view volume to a screen-space subregion (inwindow coordinates) of the viewport, the projected coordinates ofthe object are transformed by a scale and translation transform andcombined to produce the matrix

T =

pxdx

0 0 px − 2qx−oxdx

0pydy

0 py − 2qy−oydy

0 0 1 0

0 0 0 0

-

where ox, oy, px, and py are the x and y origin and width andheight of the viewport, and qx, qy, dx, and dy are the origin andwidth and height of the pick region.[4] Objects are identified byassigning them integer names using glLoadName. Each object is sentto the OpenGL pipeline and tested against the pick region. If the testsucceeds, a hit record is created to identify the object. The hit recordis written to the selection buffer whenever a change is made to thecurrent object name. An application can determine which objectsintersected the pick region by scanning the selection buffer andexamining the names present in the buffer. The OpenGL selectionmethod determines that an object has been hit if it intersects the viewvolume. Bitmap and pixel image primitives generate a hit recordonly if a raster positioning command is sent to the pipeline and thetransformed position lies within the viewing volume. To generatehit records for an arbitrary point within a pixel image or bitmap,a bounding rectangle should be sent rather than the image. Thiscauses the selection test to use the interior of the rectangle. Similarly,wide lines and points are selected only if the equivalent infinitelythin line or infinitely small point is selected. To facilitate selectiontesting of wide lines and points, proxy geometry representing thetrue footprint of the primitive is used instead. One can name everysingle primitive used to render a scene of objects, but doing so israrely useful. More often, groups of primitives are named, thuscreating names for the specific objects or pieces of objects in thescene. Object names, like display list names, are nothing more thanunsigned integers. The names list is maintained on the name stack.After the name stack, is initialized can push names on the stackor simply replace the name currently on top of the stack. When ahit occurs during selection, all the names currently on the namestack are appended to the end of the selection buffer. Thus, a singlehit can return more than one name if needed. Many applications

Page 27: Advanced features in opengl

5.1 selection 22

Figure 9: Selection Hierchy [4]

use instancing of geometric data to reduce their memory footprint.Instancing allows an application to create a single representationof the geometric data for each type of object used in the scene.If the application is modeling a car for example, the four wheelsof the car may be represented as instances of a single geometricdescription of a wheel, combined with a modeling transformationto place each wheel in the correct location in the scene. Instancingintroduces extra complexity into the picking operation. If a singlename is associated with the wheel geometry, the application cannotdetermine which of the four instances of the wheel has been picked.OpenGL solves this problem by maintaining a stack of object names.This allows an application, which represents models hierarchically,to associate a name at each stage of its hierarchy. As the car is beingdrawn, new names are pushed onto the stack as the hierarchy isdescended and old names are popped as the hierarchy is ascended.When a hit record is created, it contains all names currently inthe name stack. The application determines which instance of anobject is selected by looking at the content of the name stack andcomparing it to the names stored in the hierarchical representation ofthe model. Using the car model example, the application associatesan object name with the wheel representation and another objectname with each of the transformations used to position the wheel inthe car model. The application determines that a wheel is selectedif the selection buffer contains the object name for the wheel, andit determines which instance of the wheel by examining the objectname of the transformation. Fig.9 shows a partial graph of the modelhierarchy, with the car frame positioned in the scene and the four

Page 28: Advanced features in opengl

5.2 the basic steps 23

wheel instances positioned relative to the frame. When the OpenGLpipeline is in selection mode, the primitives sent to the pipeline donot generate fragments to the framebuffer. Since only the result ofvertex coordinate transformations is of interest, there is no needto send texture coordinates, normals, or vertex colors, or to enablelighting. [4]

5.2 the basic steps

The basic steps of using selection can be summurized as follows [1]:

1. Specify the array to be used for the returned hit records withglSelectBuffer(). Enter selection mode by specifying GL_SELECTwith glRenderMode().

2. Initialize the name stack using glInitNames() and glPush-Name().

3. Define a viewing volume that will be used for selection. Usually,this is different from the viewing volume so one has used todraw the scene originally, so one would probably want tosave and then restore the current transformation state withglPushMatrix() and glPopMatrix().

4. Alternately issue primitive drawing commands and commandsto manipulate the name stack so that each primitive of interesthas an appropriate name assigned.

5. Exit selection mode and process the returned selection data(the hit records).

An illustration of the selection mode and name stack, which detectswhether objects which collide with a viewing volume is given onfig.10. First, four triangles and a rectangular box representing aviewing volume are drawn (drawScene routine). The green triangleand yellow triangles appear to lie within the viewing volume, butthe red triangle appears to lie outside it. Then the selection mode isentered (selectObjects routine). Drawing to the screen ceases. To seeif any collisions occur, the four triangles are called. In this example,the green triangle causes one hit with the name 1, and the yellowtriangles cause one hit with the name 3.

5.3 feedback

Feedback, like selection, is a rendering mode that does not produceoutput in the form of pixels on the screen. Instead, information iswritten to a feedback buffer indicating how the scene would have

Page 29: Advanced features in opengl

5.4 the feedback buffer 24

Figure 10: Selection Example [1]

been rendered. This information includes transformed vertex data inwindow coordinates, color data resulting from lighting calculations,and texture data- essentially everything needed to rasterize theprimitives. One enters feedback mode the same way as selectionmode, by calling glRenderMode with a GL_FEEDBACK argument.First, the rendering mode should be resetted to GL_RENDER to fillthe feedback buffer and return to normal rendering mode.

5.4 the feedback buffer

The feedback buffer is an array of floating-point values specifiedwith the glFeedbackBuffer function:void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer);This function takes the size of the feedback buffer, the type andamount of drawing information wanted, and a pointer to the bufferitself. Valid values for type appear in Table 5. The type of dataspecifies how much data is placed in the feedback buffer for eachvertex. Color data is represented by a single value in color indexmode or four values for RGBA color mode.

5.5 feedback data

The feedback buffer contains a list of tokens followed by vertexdata and possibly color and texture data. One can parse for thesetokens (see Table 6) to determine the types of primitives that wouldhave been rendered. One limitation of feedback occurs when using

Page 30: Advanced features in opengl

5.5 feedback data 25

Table 5: Feedback Buffer Types

Color Data Vertex Texture Data Total Values Type CoordinatesGL_2D x, y N/A N/A 2

GL_3D x, y, z N/A N/A 3

GL_3D_COLOR x, y, z C N/A 3 + CGL_3D_COLOR_TEXTURE x, y, z C 4 7 + CGL_4D_COLOR_TEXTURE x, y, z, w C 4 8 + C

Table 6: Feedback Buffer Tokens

Token PrimitiveGL_POINT_TOKEN PointsGL_LINE_TOKEN Line

GL_LINE_RESET_TOKEN Line segment when line stipple is resetGL_POLYGON_TOKEN Polygon

GL_BITMAP_TOKEN BitmapGL_DRAW_PIXEL_TOKEN Pixel rectangle drawnGL_COPY_PIXEL_TOKEN Pixel rectangle copied

GL_PASS_THROUGH_TOKEN User-defined marker

multiple texture units. In this case, only texture coordinates from thefirst texture unit are returned.[7]

The point, bitmap, and pixel tokens are followed by data for asingle vertex and possibly color and texture data. This depends onthe data type from Table 5 specified in the call to glFeedbackBuffer.The line tokens return two sets of vertex data, and the polygon tokenis immediately followed by the number of vertices that follow. Theuser-defined marker (GL_PASS_THROUGH_TOKEN) is followed bya single floating-point value that is user defined.

Page 31: Advanced features in opengl

6F R A G M E N T O P E R AT I O N S

A number of fragment operations are applied to rasterization frag-ments before they are allowed to update pixels in the framebuffer.Fragment operations can be separated into two categories, operationsthat test fragments, and operations that modify them. To maximizeefficiency, the fragment operations are ordered so that the fragmenttests are applied first. The most interesting tests for advanced render-ing are: alpha test, stencil test, and depth buffer test. These tests caneither pass, allowing the fragment to continue, or fail, discarding thefragment so it can’t pass on to later fragment operations or updatethe framebuffer. The stencil test is a special case, since it can produceuseful side effects even when fragments fail the comparison. All ofthe fragment tests use the same set of comparison operators: Never,Always, Less, Less than or Equal, Equal, Greater than or Equal,Greater, and Not Equal. In each test, a fragment value is comparedagainst a reference value saved in the current OpenGL state (includ-ing the depth and stencil buffers), and if the comparison succeeds,the test passes. The details of the fragment tests are listed in Table7. The list of comparison operators is very complete. In fact, it mayseem that some of the comparison operations, such as GL_NEVERand GL_ALWAYS are redundant, since their functionality can beduplicated by enabling or disabling a given fragment test. Thereis a use for them, however. The OpenGL invariance rules requirethat invariance is maintained if a comparison is changed, but not ifa test is enabled or disabled. So if invariance must be maintained(because the test is used in a multipass algorithm, for example), theapplication should enable and disable tests using the comparisonoperators, rather than enabling or disabling the tests themselves.[4]

6.1 multisample operations

Multisample operations provide limited ways to affect the fragmentcoverage and alpha values. In particular, an application can reducethe coverage of a fragment, or convert the fragment’s alpha value toanother coverage value that is combined with the fragment’s valueto further reduce it. These operations are sometimes useful as analternative to alpha blending, since they can be more efficient.

26

Page 32: Advanced features in opengl

6.2 alpha test 27

Table 7: Fragment Test

Constant ComparisonGL_ALWAYS always passGL_NEVER never pass

GL_LESS pass if incoming<refGL_LEQUAL pass if incoming6refGL_GEQUAL pass if incoming>refGL_GREATER pass if incoming>ref

GL_EQUAL pass if incoming=refGL_NOTEQUAL pass if incoming 6=ref

6.2 alpha test

The alpha test reads the alpha compont value of each fragment’scolor, and compares it against the current alpha test value. The testvalue is set by the application, and can range from zero to one. Thecomparison operators are the standard set listed in Table 7. Thealpha test can be used to remove parts of a primitive on a pixel bypixel basis. A common technique is to apply a texture containingalpha values to a polygon. The alpha test is used to trim a simplepolygon to a complex outline stored in the alpha values of the surfacetexture.[4]

6.3 stencil test

The stencil test performs two tasks. The first task is to condition-ally eliminate incoming fragments based on a comparison betweena reference value and stencil value from the stencil buffer at thefragment’s destination. The second purpose of the stencil test is toupdate the stencil values in the framebuffer. How the stencil bufferis modified depends on the outcome of the stencil and depth buffertests. There are three possible outcomes of the two tests: the stencilbuffer test fails, the stencil buffer test passes but the depth bufferfails, or both tests fail. OpenGL makes it possible to specify how thestencil buffer is updated for each of these possible outcomes. Theconditional elimination task is controlled with glStencilFunc. It setsthe stencil test comparison operator. The comparison operator canbe selected from the list of operators in Table 7. Setting the stencilupdate requires setting three parameters, each one corresponding toone of the stencil/depth buffer test outcomes. The glStencilOp com-mand takes three operands, one for each of the comparison outcomes.

Page 33: Advanced features in opengl

6.4 dissolve effect with stencil buffer 28

Table 8: Stencil Update Values

Constant DescriptionGL_KEEP stencil value unchangedGL_ZERO stencil value set to zero

GL_REPLACE stencil value replaced by stencil reference valueGL_INCR stencil value incrementedGL_DECR stencil value decremented

GL_INVERT stencil value bitwise inverted

Each operand value specifies how the stencil pixel correspondingto the fragment being tested should be modified. Table 8 shows thepossible values and how they change the stencil pixels. The stencilbuffer is often used to create and use per-pixel masks. The desiredstencil mask is created by drawing geometry (often textured with analpha pattern to produce a complex shape). Before rendering thistemplate geometry, the stencil test is configured to update the stencilbuffer as the mask is rendered. Often the pipeline is configured sothat the color and depth buffers are not actually updated when thisgeometry is rendered; this can be done with the glColorMask andglDepthMask commands, or by setting the depth test to always fail.

Once the stencil mask is in place, the geometry to be masked isrendered. This time, the stencil test is pre-configured to draw ordiscard fragments based on the current value of the stencil mask.More elaborate techniques may create the mask using a combinationof template geometry and carefully chosen depth and stencil com-parisons to create a mask whose shape is influenced by the geometrythat was previously rendered. [4]

6.4 dissolve effect with stencil buffer

Stencil buffers can be used to mask selected pixels on the screen.This allows for pixel by pixel compositing of images. One can drawgeometry or arrays of stencil values to control, per pixel, whatis drawn into the color buffer. One way to use this capability isto composite multiple images. A common film technique is the"dissolve", where one image or animated sequence is replaced withanother, in a smooth sequence. The stencil buffer can be used toimplement arbitrary dissolve patterns. The alpha planes of the colorbuffer and the alpha function can also be used to implement thiskind of dissolve, but using the stencil buffer frees up the alpha planesfor motion blur, transparency, smoothing, and other effects. The basic

Page 34: Advanced features in opengl

6.4 dissolve effect with stencil buffer 29

Programming with OpenGL: Advanced Rendering

1 1 1 1

1 1 1 1

1 1 1 1

1 1 1 11 1 1 1

1 1 1 1

1 1 1 1

1 1 1 1

0 0 0 00 0 0 00 0 0 0

0 0 0 00 0 0 0

0 0 0 00 0 0 0

0 0 0 0

First Scene Second Scenedrawn with

glStencilFunc(GL_EQUAL, 1, 1);

Pattern Drawn InStencil Buffer

Resulting Image

Figure 61. Using Stencil to Dissolve Between Images

14.1 Dissolves with Stencil

Stencil buffers can be used to mask selected pixels on the screen. This allows for pixel by pixelcompositing of images. You can draw geometry or arrays of stencil values to control, per pixel,what is drawn into the color buffer. One way to use this capability is to composite multiple images.

A common film technique is the “dissolve”, where one image or animated sequence is replaced withanother, in a smooth sequence. The stencil buffer can be used to implement arbitrary dissolve pat-terns. The alpha planes of the color buffer and the alpha function can also be used to implement thiskind of dissolve, but using the stencil buffer frees up the alpha planes for motion blur, transparency,smoothing, and other effects.

The basic approach to a stencil buffer dissolve is to render two different images, using the stencilbuffer to control where each image can draw to the framebuffer. This can be done very simply bydefining a stencil test and associating a different reference value with each image. The stencil bufferis initialized to a value such that the stencil test will pass with one of the images’ reference values,and fail with the other. An example of a dissolve partway between two images is shown in Figure 61.

At the start of the dissolve (the first frame of the sequence), the stencil buffer is all cleared to onevalue, allowing only one of the images to be drawn to the framebuffer. Frame by frame, the stencilbuffer is progressively changed (in an applicationdefined pattern) to a different value, one that passesonly when compared against the second image’s reference value. As a result, more and more of thefirst image is replaced by the second.

Over a series of frames, the first image “dissolves” into the second, under control of the evolvingpattern in the stencil buffer.

185

Figure 11: Using Stencil to Dissolve Between Images [5]

approach to a stencil buffer dissolve is to render two different images,using the stencil buffer to control where each image can draw tothe framebuffer. This can be done very simply by defining a stenciltest and associating a different reference value with each image. Thestencil buffer is initialized to a value such that the stencil test willpass with one of the images reference values, and fail with the other.An example of a dissolve partway between two images is shown inFigure 11.

At the start of the dissolve (the first frame of the sequence), thestencil buffer is all cleared to one value, allowing only one of theimages to be drawn to the framebuffer. Frame by frame, the stencilbuffer is progressively changed (in an applicationdefined pattern) toa different value, one that passes only when compared against thesecond images reference value. As a result, more and more of thefirst image is replaced by the second. Over a series of frames, thefirst image "dissolves" into the second, under control of the evolvingpattern in the stencil buffer. Here is a step-by-step description of adissolve.

1. Clear the stencil buffer with glClear(GL_STENCIL_BUFFER_BIT).

2. Disable writing to the color buffer, using glColorMask(GL_FALSE,GL_FALSE, GL_FALSE, GL_FALSE).

3. If the values in the depth buffer should not change, use glDepth-Mask(GL FALSE).

For this example, the stencil test will always fail, and the stenciloperation is set to write the reference value to the stencil buffer. Theapplication will also need to turn on stenciling before one couldbegin drawing the dissolve pattern.

1. Turn on stenciling; glEnable(GL STENCIL TEST).

2. Set stencil function to always fail; glStencilFunc(GL NEVER, 1,1).

Page 35: Advanced features in opengl

6.4 dissolve effect with stencil buffer 30

3. Set stencil op to write 1 on stencil test failure; glStencilOp(GLREPLACE, GL KEEP, GL KEEP).

4. Write the dissolve pattern to the stencil buffer by drawinggeometry or using glDrawPixels.

5. Disable writing to the stencil buffer with glStencilMask(GLFALSE).

6. Set stencil function to pass on 0; glStencilFunc(GL EQUAL, 0,1).

7. Enable color buffer for writing with glColorMask(GL TRUE,GL TRUE, GL TRUE, GL TRUE).

8. If you’re depth testing, turn depth buffer writes back on withglDepthMask.

9. Draw the first image. It will only be written where the stencilbuffer values are 0.

10. Change the stencil test so only values that are 1 pass; glStencil-Func(GL EQUAL, 1, 1).

11. Draw the second image. Only pixels with stencil value of 1 willchange.

12. Repeat the process, updating the stencil buffer, so that moreand more stencil values are 1, using your dissolve pattern, andredrawing image 1 and 2, until the entire stencil buffer has 1’sin it, and only image 2 is visible.

If each new frames dissolve pattern is a superset of the previousframes pattern, image 1 doesnt have to be re-rendered. This is be-cause once a pixel of image 1 is replaced with image 2, image 1 willnever be redrawn there. Designing the dissolve pattern with thisrestriction can improve the performance of this technique.[5]

Page 36: Advanced features in opengl

7S U M M A RY

In this work, an introduction to special features in OpenGL was given.First, two methods - display lists and vertex arrays- to improve codeperformance were presented. It was showned that applying thesetechniques should enable a higher frame rate to be achieved. Fur-thermore, it was presented how to use blending, and how to takeadvantage of OpenGL’s built-in fog. As a next subtopic, selectionand feedback, two powerful features of OpenGL that enable us tofacilitate the users active interaction with a scene were presented.The differences and simmilarities between Selection and Feedbackwere discussed. Thereafter, many of the mechanisms which rasteri-zation and fragment processing operations provide for modifying afragment value or discarding it outright were briefly analysed. Fur-thermore, an algorithmic approach of creating a dissolve effect withthe use of the stencil buffer was presented. In conclusion, the combi-nation of all the knowledge regarding special features in OpenGLpresented in this work should be enough to create a fairly complexOpenGL applications, even including simple games.

31

Page 37: Advanced features in opengl

B I B L I O G R A P H Y

[1] OpenGL Programming Guide The Redbook The OpenGL Pro-gramming Guide 6th Edition The Official Guide to LearningOpenGL Version 2.1. D. Shreiner, M. Woo, J. Neider and T. Davis.Addison Wesley. (Cited on pages v, 5, 8, 23, and 24.)

[2] D. Astle and K. Hawkins. Beginning OpenGL Game Programming.Course Technology. (Cited on pages v, 8, 9, 10, 11, 15, 16, and 19.)

[3] OpenGL® SUPERBIBLE Fourth Edition The Bluebook. R.Wright, B. Lipchak and N. Haemel. Addison Wesley. (Cited onpages 13, 14, 15, 17, and 18.)

[4] T. McReynolds and D. Blythe. Advanced Graphics ProgrammingUsing OpenGL. (Cited on pages v, 20, 21, 22, 23, 26, 27, and 28.)

[5] Tom McReynolds. Advanced Graphics Programming TechniquesUsing OpenGL. SIGGRAPH 1998 Course, 1998. (Cited on pages v,29, and 30.)

[6] D. Shreiner, E. Angel, and V. Shreiner. An Interactive IntroductionTo OpenGL Programming Course 54. 2001. (Cited on page 2.)

[7] R. S. Wright and M. Sweet. Opengl Superbible: The Complete Guideto Opengl Programming for Windows Nt and Windows 95. (Citedon page 25.)

32