Upload
juliet-woodring
View
233
Download
0
Tags:
Embed Size (px)
Citation preview
2
Topics
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
4
Types 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
5
Using 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)
6
Masking 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
7
Masking 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
9
Per-fragment Operation Sequence
Fragments: the pieces after rasterization, sent to framebuffers if they survive these testsglScissor
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
10
Scissor 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 coordinateSingle-pixel window: glScissor (x,y,1,1);
See also stencil_closeSee also stencil_close
11
Fragment 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
13
Basic Applications
Restrict rendering to limited portions of the screen“Stenciling”
DecalShadow and lightmap
14
Mimicking Stencil
Compose stencil template Control template then renderMulti-pass rendering
silhouette
17
Technical DetailsglStencilFunc (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
18
Technical 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 refBitwise invert
19
StencilingSteps to draw 2 coplanar rectangles:
1. Make the stencil for yellow one first (by drawing the green polygon)
2. Draw the yellow one with the stencil3. Draw the green one
21
Decaling
[0] Base: (-5,0)(5,6)[1] R: (-3,1)(2,4)[2] G: (1,2)(3,5)[3] B: (0,0)(4,3)
Foregroundblocker
1. Draw everything else (set up the depth buffer)2. Draw base; set the blocker id to be 8; rest 03. Arrange the decal id in increasing order4. The decals can be drawn in any order
Test the program…
22
0 0 0 00 00 00 0
0 80 8
0 00 00 0
8 8
0 00 0
0 00 0
0 00 00 00 0
0 00 0
0 00 0
8 88 8
8 88 8
0 00 08 8
Color buffer
Stencil buffer
StencilOp(fail, zfail, zpass)
1 11 1
11
1 11 1
2 22 22 2 33 33
33
Foregroundblocker
23
0 0 0 00 00 00 0
0 80 8
0 00 00 0
8 8
0 00 0
0 00 0
0 00 00 00 0
0 00 0
0 00 0
8 88 8
8 88 8
0 00 08 8
Color buffer
Stencil buffer
StencilOp(fail, zfail, zpass)
1 11 1
11
1 11 1
2 22 22 2 33 33
33
Foregroundblocker
Drawn in different order!Drawn in different order!
26
Stencil Planar Shadow
Shadow matrix to project model onto a flat shadow receiverBlending + stencil buffer techniques involved
28
Reflection
Easy hack, draw dino twice, second time has
glScalef(1,-1,1) to reflect through the floor
Dinosaur is reflected by the planar floor.
Notice right image’s reflection falls off the floor!
29
Stencil Reflection
Clear stencil to zero.Draw floor polygon with stencil set to one.Only draw reflection where stencil is one.
Reflection and shadow
30
[Shadow Volume Using Stencil Buffers]
Triangle blockinglight source.
“Shadow” volumeprojected by trianglefrom the light source.
Use stencil to tag whetherpixel is inside or outsideof the shadow volume.
Two passes: light pixels outsidevolume; no lighting for
pixels inside the volume.
33
Accumulation 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
34
Accumulation Buffer (cont)
scene antialiasing, motion blur, photographic depth of field[softshadow, jittering]analogy: multiple exposurestakes longer, but higher quality
accum.buffer may have higher precision 16 bits for each
RGBA channels
scene antialiasing by spatially jittering the image
35
Accumulation 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);
39
Motion Blur w/o Accum.Buffer
Details: scene dynamically render to texture; modulate with a polygon (1,1,1,a)
40
Scene 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
42
How to do Picking?
Revisit unproject.cA 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
43
Selection (Basic Idea)
draw scene into framebufferenter 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
44
Selection (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 hitsprocess select buffer for hits
45
Name Stack
name: GLuintglInitNames 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
46
Hit 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 aren’t 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
47
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 < 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 < names; j++) { /* for each name */ printf ("%d ", *ptr); ptr++; } printf ("\n"); }}
void selectObjects(void){ GLuint selectBuf[512]; 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();}
48
Process 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,…]
About the depth value (refs: 1,2)
The depth is taken from the Z buffer (where it lies in the range [0,1]).It gets multiplied by 2^32 -1 (0xffff ffff)and is rounded to the nearest integer. Note that the depths you get are not linearly proportional to the distance to the viewpoint due to the nonlinear nature of the z buffer (See Opengl-2.ppt, p.44)
49
50
Picking
restrict drawing to a small region of the viewport (near the cursor)mouse click to initiate the selection modeIssues: interpreting mouse (x,y)! hierarchical pick: name stack
manipulation 3D pick (picking and depth values)
51
gluPickMatrix
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
52
void drawSquares(GLenum mode) { GLuint i, j; for (i = 0; i < 3; i++) { if (mode == GL_SELECT) glLoadName (i); for (j = 0; j < 3; j ++) { if (mode == GL_SELECT) glPushName (j); glColor3f ((GLfloat) i/3.0, (GLfloat) j/3.0, (GLfloat) board[i][j]/3.0); glRecti (i, j, i+1, j+1); 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 < 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 < 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"); board[ii][jj] = (board[ii][jj] + 1) % 3; }}void pickSquares(int button, int state, int x, int y){ GLuint selectBuf[512]; GLint hits; GLint viewport[4];
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) (viewport[3] - 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();}
54
Hints 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
55
[Feedback]
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
56
void 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 < 7; i++) { printf ("%4.2f ", buffer[size-(*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 = buffer[size-count]; count--; if (token == GL_PASS_THROUGH_TOKEN) { printf ("GL_PASS_THROUGH_TOKEN\n"); printf (" %4.2f\n", buffer[size-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 feedBuffer[1024]; 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);}
57
Feedback (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
59
GLIntercept
An OpenGL debugging facility that intercepts OpenGL calls to create informative logsComes with some built-in logging scriptsRename the one you choose to gliConfig.iniThe one particular useful for stencil buffer debugging is gliConfig_XMLFrame.iniCtrl-shift-key to create frame logView the resulting XML in IE
60
Copy 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
61
gliConfig_XMLFrame.ini
By default, it only does color buffer logging
If you need to see depth and/or stencil buffers,modify these two lines.
62
Example (Stencil Silhouette)
(pre,post,diff)Red means no differenceGreen means same pixels
Click to enlarge