Title: Introduction to OpenGL Part 4
1Introduction to OpenGL(Part 4)
- Ref OpenGL Programming Guide (The Red Book)
2Topics
- Part 1
- Introduction
- Geometry
- Viewing
- Light Material
- Display List
- Part 2
- Alpha Channel
- Polygon Offset
- Part 3
- Image
- Texture Mapping
- Part 4
- Framebuffers
- Selection Feedback
3OpenGL
4Types of Buffers
- color (front/back, left/right, aux)
- Front/back animation
- Left/right stereo vision
- Aux not available on PC (use framebuffer object
FBO instead)
- depth buffer depth test
- VC 24 bits available
- Value 0.0,1.0
- stencil buffer restrict drawing to certain
portions of the screen - VC 8 bits available
- accumulation buffer accumulating composite image
5Using Framebuffers
- clearing buffers
- clearing individual buffer is expensive
- Use glClear with bitwise-ORed masks to clear
multiple buffers - selecting color buffers for writing/clearing
- glDrawBuffer useful in FBO (framebuffer object)
6Masking Buffers
- Before OpenGL writes data into the enabled color,
depth, or stencil buffers, a masking operation is
applied to the data, as specified with one of the
following commands. - A bitwise logical AND is performed with each mask
and the corresponding data to be written
7Masking Buffers (cont)
- void glColorMask(GLboolean red, GLboolean green,
GLboolean blue, GLboolean alpha) - void glDepthMask(GLboolean flag)
- void glStencilMask(GLuint mask)
- If a 1 appears in mask, the corresponding bit in
the stencil buffer is written where a 0 appears,
the bit is not written. - The default values of all the GLboolean masks are
GL_TRUE, and the default values for the two
GLuint masks are all 1's
8Only Green Mask TRUE
9Per-fragment Operation Sequence
- Fragments the pieces after rasterization, sent
to framebuffers if they survive these tests - glScissor
- restrict drawing to part of the window
- a simpler (and faster) version of stencil test
(that does not need stencil buffer) - application gui panel
Dithering and logical op not covered here
10Scissor Test
- While the scissor test is enabled, only pixels
that lie within the scissor box can be modified
by drawing commands. - Including glClear (shown right)
- Note validity of current raster position is
determined by frustum (world coordinate) while
scissor test affects the window coordinate - Single-pixel window glScissor (x,y,1,1)
See also stencil_close
11Fragment Operations (cont)
- Alpha test
- accept/reject a fragment based on its alpha value
- implement transparency
- use this test to filter opaque objects
- see-through decal (billboarding) reject the
transparent fragments (from ruining the depth
buffer)
- Stencil Test
- require stencil buffer
- glStencilFunc, glStencilOp
12Stenciling
13Basic Applications
- Restrict rendering to limited portions of the
screen - Stenciling
- Decal
- Shadow and lightmap
14Mimicking Stencil
- Compose stencil template
- Control template then render
- Multi-pass rendering
silhouette
15Decal Using Stencil Buffers
Stencil to resolve z-fighting
16Shadow and Lightmap
Shadow and light blended with the textured
polygon underneath
17Technical Details
- glStencilFunc (fun, ref, mask)
- func Specifies the test function. Eight tokens
are valid GL_NEVER, GL_LESS, GL_LEQUAL,
GL_GREATER, GL_GEQUAL, GL_EQUAL, GL_NOTEQUAL, and
GL_ALWAYS. - If it's GL_LESS, for example, then the fragment
passes if reference value is less than the value
in stencil buffer - ref Specifies the reference value for the stencil
test. ref is clamped to the range 0, 2n - 1,
where n is the number of bitplanes in the stencil
buffer. - VC n 8
- mask Specifies a mask that is ANDed with both the
reference value and the stored stencil value when
the test is done
18Technical Details (cont)
- glStencilOp (fail, zfail, zpass)
- fail Specifies the action to take when the
stencil test fails. - zfail Specifies stencil action when the stencil
test passes, but the depth test fails. - zpass Specifies stencil action when both the
stencil test and the depth test pass, or when the
stencil test passes and either there is no depth
buffer or depth testing is not enabled. - Six symbolic constants are accepted GL_KEEP,
GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, and
GL_INVERT.
Set value to ref
Bitwise invert
19Stenciling
- Steps to draw 2 coplanar rectangles
- Make the stencil for yellow one first (by drawing
the green polygon) - Draw the yellow one with the stencil
- Draw the green one
20Stenciling (cont)
Stencil buffer
Color buffer
21Decaling
0 Base (-5,0)?(5,6) 1 R
(-3,1)?(2,4) 2 G (1,2)?(3,5) 3 B
(0,0)?(4,3)
Foreground blocker
- Draw everything else (set up the depth buffer)
- Draw base set the blocker id to be 8 rest 0
- Arrange the decal id in increasing order
- The decals can be drawn in any order
Test the program
22StencilOp(fail, zfail, zpass)
Color buffer
Stencil buffer
23StencilOp(fail, zfail, zpass)
Color buffer
Stencil buffer
Drawn in different order!
24Generating Silhouette
Stencil Buffer
Debug with GLIntercept
25See also
- Different line style
- Hidden line removal
- Haloed lines
26Stencil Planar Shadow
- Shadow matrix to project model onto a flat shadow
receiver - Blending stencil buffer techniques involved
27CSG (constructive solid geometry)
Cone INTERSECT Sphere
Cone SUBTRACT Sphere
Sphere UNION Cone
28Reflection
Dinosaur is reflected by the planar floor.
Easy hack, draw dino twice, second time
hasglScalef(1,-1,1) to reflect through the floor
Notice right images reflection falls off the
floor!
29Stencil Reflection
Clear stencil to zero.Draw floor polygon with
stencil set to one.Only draw reflection where
stencil is one.
Reflection and shadow
30Shadow Volume Using Stencil Buffers
Triangle blockinglight source.
Use stencil to tag whetherpixel is inside or
outsideof the shadow volume. Two passes light
pixels outsidevolume no lighting forpixels
inside the volume.
Shadow volumeprojected by trianglefrom the
light source.
31More Complicated Case
32Hybrid Shadows
Shadow volumes
Planar projected shadows
33Accumulation Buffer
- series of images generated on standard color
buffers accumulated one at a time into the
accumulation buffers result copied back into a
color buffer for viewing
34Accumulation Buffer (cont)
- scene antialiasing, motion blur, photographic
depth of field - softshadow, jittering
- analogy multiple exposures
- takes longer, but higher quality
- accum.buffer may have higher precision
- 16 bits for each RGBA channels
- scene antialiasing by spatially jittering the
image
35Accumulation Buffer APIs
- glClearAccum (0,0,0,0)
- glGetIntegerv (GL_ACCUM_RED_BITS, value)
- 16 for each RGBA channels
- glAccum(GL_ACCUM, 1.f/counts)
- glAccum(GL_RETURN, 1.f)
36Accumulation Buffer
scene antialiasing
motion blur
depth of field
37Ref
38FSAA with Multi-Sampling(ref)
39Motion Blur w/o Accum.Buffer
Details scene dynamically render to texture
modulate with a polygon (1,1,1,a)
40Scene Anti-aliasing
- Can be done in real-time w/o accumulation buffer
- By outlining the silhouette edges
- See Tom Hall
FPS 10.8
FPS 9.6
41OpenGL
42How to do Picking?
- Revisit unproject.c
- A line segment between (x1, y1, zNear) and (x2,
y2, zFar) - Check which object got hit
- Complexity problem?!
- Can do better?
Simple tracking on XZ plane
43Selection (Basic Idea)
- draw scene into framebuffer
- enter selection mode and redraw the scene
- the content of framebuffer unchanged until you
exit the selection mode - when exit, returns a list of primitives that
intersected the viewing volume - as an array of names (integer) and hit records
- Picking a variation of selection
- triggered by mouse mouse defines v.volume
44Selection (Steps)
- glSelectBuffer (maxselects, selectbuffer)
- glRenderMode (GL_SELECT)
- glInitNames, glPushName (0)
- Something needs to be pushed on the empty stack
(otherwise, it cannot be loaded) - define viewing volume
- Need to save current projection matrix for
further rendering - issue drawing commands
- Load a name then draw something if the thing
drawn is in v.volume, it generates a hit (with
the name) - glRenderMode (GL_RENDER)
- Return the number of hits
- process select buffer for hits
45Name Stack
- name GLuint
- glInitNames
- causes the name stack to be initialized to its
default empty state - glPushName/glPopName
- as the name implies
- glLoadName
- replace the top of the stack
- need to push something right after InitNames for
first load - commands ignored unless in selection mode
46Hit Record
- Primitive intersecting v.vol causes a hit
- stack pointer points to the beginning of
selection array and updates when hit occurs - culled polygons generate no hit
- composite objects (w/ single name) generate one
hit - hit records arent updated until glRenderMode is
called
- each hit record
- number of names on the name stack
- min and max window-coord z values
- 0,1
- contents of name stack w/ bottommost element first
47void selectObjects(void) GLuint
selectBuf512 GLint hits glSelectBuffer
(512, selectBuf) (void) glRenderMode
(GL_SELECT) glInitNames()
glPushName(0) glPushMatrix ()
glMatrixMode (GL_PROJECTION) glLoadIdentity
() glOrtho (0.0, 5.0, 0.0, 5.0, 0.0, 10.0)
glMatrixMode (GL_MODELVIEW) glLoadIdentity
() glLoadName(1) drawTriangle (2.0, 2.0,
3.0, 2.0, 2.5, 3.0, -5.0) glLoadName(2)
drawTriangle (2.0, 7.0, 3.0, 7.0, 2.5, 8.0,
-5.0) glLoadName(3) drawTriangle (2.0,
2.0, 3.0, 2.0, 2.5, 3.0, 0.0) drawTriangle
(2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -10.0)
glPopMatrix () hits glRenderMode
(GL_RENDER) processHits (hits, selectBuf)
void display(void) glClearColor (0.0, 0.0,
0.0, 0.0) glClear(GL_COLOR_BUFFER_BIT
GL_DEPTH_BUFFER_BIT) drawScene ()
selectObjects () glFlush()
void drawScene (void) glMatrixMode
(GL_PROJECTION) glLoadIdentity ()
gluPerspective (40.0, 4.0/3.0, 1.0, 100.0)
glMatrixMode (GL_MODELVIEW) glLoadIdentity
() gluLookAt (7.5, 7.5, 12.5, 2.5, 2.5, -5.0,
0.0, 1.0, 0.0) glColor3f (0.0, 1.0, 0.0) /
green / drawTriangle (2.0, 2.0, 3.0, 2.0,
2.5, 3.0, -5.0) glColor3f (1.0, 0.0, 0.0) /
red / drawTriangle (2.0, 7.0, 3.0, 7.0,
2.5, 8.0, -5.0) glColor3f (1.0, 1.0, 0.0) /
yellow / drawTriangle (2.0, 2.0, 3.0, 2.0,
2.5, 3.0, 0.0) drawTriangle (2.0, 2.0, 3.0,
2.0, 2.5, 3.0, -10.0) drawViewVolume (0.0,
5.0, 0.0, 5.0, 0.0, 10.0) void processHits
(GLint hits, GLuint buffer) unsigned int
i, j GLuint names, ptr printf ("hits
d\n", hits) ptr (GLuint ) buffer for
(i 0 i lt hits i) / for each hit /
names ptr printf (" number of names
for hit d\n", names) ptr printf("
z1 is g", (float) ptr/0x7fffffff) ptr
printf(" z2 is g\n", (float) ptr/0x7fffffff)
ptr printf (" the name is ")
for (j 0 j lt names j) / for each name
/ printf ("d ", ptr) ptr
printf ("\n")
48Process Hits
- When returning to RENDER mode,
- All hit records got recorded in a GLuint array as
follows - of names, zmin, zmax, names
- Names for an object need not be a single integer
- object type, object number, object part,
49Picking
- restrict drawing to a small region of the
viewport (near the cursor) - mouse click to initiate the selection mode
- Issues
- interpreting mouse (x,y)!
- hierarchical pick name stack manipulation
- 3D pick (picking and depth values)
50gluPickMatrix
- creates a projection matrix that can be used to
restrict drawing to a small region of the viewport
Often called from mouse callback need to convert
glut to OpenGL mouse coordinates
51void drawSquares(GLenum mode) GLuint i, j
for (i 0 i lt 3 i) if (mode
GL_SELECT) glLoadName (i) for (j
0 j lt 3 j ) if (mode
GL_SELECT) glPushName (j)
glColor3f ((GLfloat) i/3.0, (GLfloat) j/3.0,
(GLfloat) boardij/3.0)
glRecti (i, j, i1, j1) if (mode
GL_SELECT) glPopName ()
void processHits (GLint hits, GLuint
buffer) unsigned int i, j GLuint ii,
jj, names, ptr printf ("hits d\n",
hits) ptr (GLuint ) buffer for (i 0
i lt hits i) / for each hit / names
ptr printf (" number of names for this
hit d\n", names) ptr printf(" z1 is
g", (float) ptr/0x7fffffff) ptr
printf(" z2 is g\n", (float) ptr/0x7fffffff)
ptr printf (" names are ") for
(j 0 j lt names j) / for each name /
printf ("d ", ptr) if (j 0)
/ set row and column / ii
ptr else if (j 1) jj
ptr ptr
printf ("\n") boardiijj
(boardiijj 1) 3 void
pickSquares(int button, int state, int x, int
y) GLuint selectBuf512 GLint hits
GLint viewport4 if (button !
GLUT_LEFT_BUTTON state ! GLUT_DOWN)
return glGetIntegerv (GL_VIEWPORT,
viewport) glSelectBuffer (512, selectBuf)
(void) glRenderMode (GL_SELECT)
glInitNames() glPushName(0) glMatrixMode
(GL_PROJECTION) glPushMatrix ()
glLoadIdentity () gluPickMatrix ((GLdouble)
x, (GLdouble) (viewport3 - y),
5.0, 5.0, viewport) gluOrtho2D (0.0, 3.0,
0.0, 3.0) drawSquares (GL_SELECT)
glMatrixMode (GL_PROJECTION) glPopMatrix ()
glFlush () hits glRenderMode
(GL_RENDER) processHits (hits, selectBuf)
glutPostRedisplay()
52Example picking spheres and cubes
53Hints on Using Selection
- 2D application
- handle your own picking
- 3D
- organize your program and data structure so that
it is easy to draw list of object in either
selection or rendering mode - Use name creatively
54Feedback
- key difference what information is sent back
- transformed primitives is sent back to an array
of floating point values (window coordinate) - tokens of primitive type and other data for that
primitive
- steps
- glFeedbackBuffer
- glRenderMode (GL_FEEDBACK)
- draw primitives
- glRenderMode (GL_RENDER)
- parse the feedback array
55void drawGeometry (GLenum mode) glBegin
(GL_LINE_STRIP) glNormal3f (0.0, 0.0, 1.0)
glVertex3f (30.0, 30.0, 0.0) glVertex3f
(50.0, 60.0, 0.0) glVertex3f (70.0, 40.0,
0.0) glEnd () if (mode GL_FEEDBACK)
glPassThrough (1.0) glBegin (GL_POINTS)
glVertex3f (-100.0, -100.0, -100.0) /
will be clipped / glEnd () if (mode
GL_FEEDBACK) glPassThrough (2.0)
glBegin (GL_POINTS) glNormal3f (0.0, 0.0,
1.0) glVertex3f (50.0, 50.0, 0.0) glEnd
() / Write contents of one vertex to stdout
/ void print3DcolorVertex (GLint size, GLint
count, Lfloat buffer) int i printf ("
") for (i 0 i lt 7 i) printf
("4.2f ", buffersize-(count)) count
count - 1 printf ("\n")
/ Write contents of entire buffer. (Parse
tokens!) / void printBuffer(GLint size, GLfloat
buffer) GLint count GLfloat token
count size while (count) token
buffersize-count count-- if (token
GL_PASS_THROUGH_TOKEN) printf
("GL_PASS_THROUGH_TOKEN\n") printf ("
4.2f\n", buffersize-count) count--
else if (token GL_POINT_TOKEN)
printf ("GL_POINT_TOKEN\n")
print3DcolorVertex (size, count, buffer)
else if (token GL_LINE_TOKEN)
printf ("GL_LINE_TOKEN\n")
print3DcolorVertex (size, count, buffer)
print3DcolorVertex (size, count, buffer)
else if (token GL_LINE_RESET_TOKEN)
printf ("GL_LINE_RESET_TOKEN\n")
print3DcolorVertex (size, count, buffer)
print3DcolorVertex (size, count, buffer)
void display(void) GLfloat
feedBuffer1024 GLint size glMatrixMode
(GL_PROJECTION) glLoadIdentity () glOrtho
(0.0, 100.0, 0, 100.0, 0.0, 1.0)
glClearColor (0.0, 0.0, 0.0, 0.0)
glClear(GL_COLOR_BUFFER_BIT) drawGeometry
(GL_RENDER) glFeedbackBuffer (1024,
GL_3D_COLOR, feedBuffer) (void) glRenderMode
(GL_FEEDBACK) drawGeometry (GL_FEEDBACK)
size glRenderMode (GL_RENDER) printBuffer
(size, feedBuffer)
56Feedback (cont)
- feedback picking
- more refined picking (not just pick object, but
some point on the object) - feedback buffer type
- 2D/3D/4D COLOR TEXTURE
- glPassThrough
- tokens that helps parsing the feedback data
- feedback array syntax
- (table 12-2)
- an application
- rendereps.c
- use feedback buffer info to write EPS
57End of Part 4
58GLIntercept
- An OpenGL debugging facility that intercepts
OpenGL calls to create informative logs - Comes with some built-in logging scripts
- Rename the one you choose to gliConfig.ini
- The one particular useful for stencil buffer
debugging is gliConfig_XMLFrame.ini - Ctrl-shift-key to create frame log
- View the resulting XML in IE
59Copy OpenGL32.dll and the chosen/renamed
gliConfig.ini to the directory where EXE resides
Each ctrl-shift-F creates a Frame log
Use IE to open the XML
60gliConfig_XMLFrame.ini
By default, it only does color buffer logging If
you need to see depth and/or stencil
buffers, modify these two lines.
61Example (Stencil Silhouette)
(pre,post,diff)
Red means no difference Green means same pixels
Click to enlarge
62Example (cont)
BACK