60
Fall 2009 revised 1 Introduction to OpenGL (Part 4) Ref: OpenGL Programming G uide (The Red Book)

Fall 2009 revised1 Introduction to OpenGL (Part 4) Ref: OpenGL Programming Guide (The Red Book)

Embed Size (px)

Citation preview

Fall 2009 revised 1

Introduction to OpenGL(Part 4)

Ref: OpenGL Programming Guide (The Red Book)

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

3

OpenGL

Framebuffers

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

8

Only Green Mask TRUE

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

12

Stenciling

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

15

Decal Using Stencil Buffers

Stencil to resolve z-fighting

16

Shadow and Lightmap

Shadow and light blended with the textured polygon underneath

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

20

Stenciling (cont)Stencil bufferColor buffer

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!

24

Generating Silhouette

Stencil Buffer

Debug with GLIntercept

25

See also

Different line styleHidden line removalHaloed lines

Cheap silhouette

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);

36

Accumulation Buffer

depth of field

scene antialiasing

motion blur

37

Ref

38

FSAA with Multi-Sampling(ref)

glMultiSample

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

41

OpenGL

Selection and Feedback

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();}

53

Example: picking spheres and cubes

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

58

End of Part 4

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

63

Example (cont)

BACK