Advanced OpenGL Technique Jian Huang, CS 594, Fall 2002 Redbook: Chapters 6.1, 9.5, 9.6, 10 List of Topics • Blending • Multi-texturing • Frame buffers – Stencil buffer – A-buffer (accumulation buffer) • Fragment Tests Alpha: the 4th Color Component • Measure of Opacity – simulate translucent objects • glass, water, etc. – composite images – antialiasing – ignored if blending is not enabled glEnable( GL_BLEND ) Compositing for Semi-transparency • Requires sorting! (BTF vs. FTB) • “over” operator - Porter & Duff 1984 • a : opacity C(0)in Cin C, a Ci, ai Cout Cout Cin (1 a) C a C(N)out C i in C i 1out Fragment • Fragment in OGL: after the rasterization stage (including texturing), the data are not yet pixel, but are fragments – Fragment is all the data associated with a pixel, including coordinate, color, depth and texture coordinates. Blending in OGL • If a fragment makes it to FB, the pixel is read out and blended with the fragment’s color and then written back to FB • The contributions of fragment and FB pixel is specified: glBlendFunc( src, dst ) Blending Function • Four choices: – – – – GL_ONE GL_ZERO GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA • Blending is enabled using glEnable(GL_BLEND) • Note: If your OpenGL implementation supports the GL_ARB_imaging extension, you can modify the blending equation as well. 3D Blending with Depth Buffer • A scene of opaque and translucent objects – Enable depth buffering and depth test – Draw opaque objects – Make the depth buffer read only, with glDepthMask(GL_FALSE) – Draw the translucent objects (sort those triangles still, but which order, FTB or BTF?) How Many Buffers Are There? • In OpenGL: – Color buffers: front, back, front-left, front-right, back-left, back-right and other auxiliaries – Depth buffer – Stencil buffer – Accumulation buffer • Exactly how many bits are there in each buffer, depends on – OGL implementation – what you choose • Each buffer can be individually cleared Selecting Color Buffer for Writing and Reading • Drawing and reading can go into any of front, back, front-left, front-right, back-left, back-right and other auxiliaries • glDrawBuffer: select buffer to be written or drawn into – Can have multiple writing buffer at the same time • glReadBuffer: select buffer as the source for – – – – glReadPixels glCopyPixels glCopyTexImage (copy from FB to a texture image) glCopyTexSubImage Accumulation Buffer • Problems of compositing into color buffers – limited color resolution (e.g. 8 bits/channel) • clamping • loss of accuracy • Accumulation buffer acts as a “floating point” color buffer – accumulate into accumulation buffer – transfer results to frame buffer Accumulation Buffer • OGL don’t directly write into A-buffer • Typically, a series of images are rendered to a standard color buffer and then accumulated, one at a time, into the A-buffer. • Then, the result in A-buffer has to be copied back to a color buffer for viewing • A-buffer may have more bits/color Accessing Accumulation Buffer • glAccum(op, value ) operations – within the accumulation buffer: • GL_ADD, GL_MULT – from read buffer • GL_ACCUM, GL_LOAD – transfer back to write buffer • GL_RETURN – glAccum( GL_ACCUM, 0.5) multiplies each value in read buffer by 0.5 and adds to accumulation buffer – How do you average N images?! Accumulation Buffer Applications • • • • • Compositing Full Scene Anti-aliasing Depth of Field Filtering Motion Blur Full Scene Antialiasing • • • • Jittering the view (how?? ) Each time we move the viewer, the image shifts Different aliasing artifacts in each image Averaging images using accumulation buffer averages out these artifacts • Like super-sampling in ray-tracing Depth of Focus • Keeping a Plane in Focus • Jitter the viewer to keep one plane unchanged How do you jitter the viewer ???? Move the camera in a plane parallel to the focal plane. What else? • Can you do soft shadows? – Jitter the light sources • What about motion blur – Jitter the moving object in the scene – glAccum(GL_MULT, decayFactor) A Fragment’s Journey Towards FB • Many Tests (on/off with glEnable) – – – – scissor test - an additional clipping test alpha test - a filtering test based on alpha stencil test - a pixel mask test depth test - fragment occlusion test Scissor Box • Additional Clipping test – glScissor( x, y, w, h ) • any fragments outside of box are clipped • useful for updating a small section of a viewport • affects glClear() operations Alpha Test • Reject pixels based on their alpha value • glAlphaFunc(func, value) – – – – GL_NEVER GL_LESS GL_EQUAL GL_LEQUAL GL_GREATER GL_NOTEQUAL GL_GEUQAL GL_ALWAYS • For instance, use as a mask for texture – How would you render a fence? Stencil Test • Used to control drawing based on values in the stencil buffer • Fragments that failt the stencil test are not drawn – Example: create a mask in stencil buffer and draw only objects not in mask area Stencil Buffer • Don’t render into stencil buffer – Control stencil buffer values with stencil function – Can change stencil buffer values with each fragment passing or failing the test Controlling Stencil Buffer • For each pixel, what do I do? Look: – glStencilFunc( func, ref, mask ) • compare value in buffer with (ref AND mask) and (stencil_pixel AND mask) using func • func is one of standard comparison functions – glStencilOp( fail, zfail, zpass ) • • • • • Allows changes in stencil buffer based on: Failing stencil test Failing depth test Passing depth test GL_KEEP, GL_INCR, GL_REPLACE, GL_DECR, GL_INVERT, GL_ZERO Creating a Mask • Initialize Mask glInitDisplayMode( …|GLUT_STENCIL|… ); glEnable( GL_STENCIL_TEST ); glClearStencil( 0x0 ); glStencilFunc( GL_ALWAYS, 0x1, 0x1 ); glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE ); Using Stencil Mask • glStencilFunc( GL_EQUAL, 0x1, 0x1 ) draw objects where stencil = 1 • glStencilFunc( GL_NOT_EQUAL, 0x1, 0x1 ); • glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); draw objects where stencil != 1 Dithering • glEnable( GL_DITHER ) • Dither colors for better looking results • Used to simulate more available colors – Say, newspapers • OGL will modify the color of a fragment with a dithering table Logical Operations on Fragments • Combine fragment and pixel color using bitwise logical operations: glLogicOp( mode ) • Common modes – – – – – – GL_CLEAR GL_SET GL_COPY, GL_COPY_INVERTED GL_NOOP GL_INVERT GL_AND GL_NAND GL_OR GL_NOR GL_XOR GL_AND_INVERTED GL_AND_REVERSE GL_EQUIV GL_OR_INVERTED GL_OR_REVERSE Texturing • Texture functions: glTexEnv( ), specifies how texture values are combined with the color values of each fragment • Texture environment mode: Tables 9-4,5 – – – – GL_DECAL GL_REPLACE GL_MODULATE GL_BLEND Multi-Texturing • Should have at least 2 texture units if multitexturing is supported • Each texture unit: – – – – – Texture image Filtering parameters Environment application Texture matrix stack Automatic texture-coordinate generation (doesn’t seem obvious, but very have very creative apps) Texture Matrix Stack • At least 2 matrices deep • 4x4 matrix • Can take texture coordinates in homogeneous space (s, t, r, q) More extensions • • [Segal 1992], need OpenGL extensions. Multi-texturing is made extremely interesting and creative. Please check nvidia.com for white papers on these. Not in the current redbook published in 1997. #ifndef GL_VERSION_texture_env_combine #define GL_COMBINE #define GL_ADD_SIGNED #define GL_INTERPOLATE #define GL_CONSTANT #define GL_PRIMARY_COLOR #define GL_PREVIOUS #define GL_COMBINE_RGB #define GL_COMBINE_ALPHA #define GL_SOURCE0_RGB #define GL_SOURCE1_RGB #define GL_SOURCE2_RGB #define GL_SOURCE0_ALPHA #define GL_SOURCE1_ALPHA #define GL_SOURCE2_ALPHA #define GL_OPERAND0_RGB #define GL_OPERAND1_RGB #define GL_OPERAND2_RGB #define GL_OPERAND0_ALPHA #define GL_OPERAND1_ALPHA #define GL_OPERAND2_ALPHA #define GL_RGB_SCALE 0x8570 0x8574 0x8575 0x8576 0x8577 0x8578 0x8571 0x8572 0x8580 0x8581 0x8582 0x8588 0x8589 0x858A 0x8590 0x8591 0x8592 0x8598 0x8599 0x859A 0x8573 OpenGL Multitexture Extension • Standardized and widely available – Introduces concept of multiple texture units • Two or more texture units • Existing texture API extended to implicitly use active texture unit glActiveTextureARB(GL_TEXTUREn_ARB) – Each unit has its own complete and independent OpenGL texture state • Texture image, filtering modes, texture environment, texture matrix OpenGL Multitexture Quick Tutorial – Configuring up a given texture unit: glActiveTextureARB(GL_TEXTURE1_ARB); Sets active texture unit glBindTexture(GL_TEXTURE_2D, texObject); glTexImage2D(GL_TEXTURE_2D, …); Implicitly glTexParameterfv(GL_TEXTURE_2D, …); update glTexEnvfv(GL_TEXTURE_ENV, …); state of glTexGenfv(GL_S, …); active glMatrixMode(GL_TEXTURE); texture glLoadIdentity(); unit – Setting texture coordinates for a vertex: glMultiTexCoord4f(GL_TEXTURE0_ARB, s0, t0, r0 ,q0); glMultiTexCoord2f(GL_TEXTURE1_ARB, s1, t1); glMultiTexCoord3f(GL_TEXTURE2_ARB, s2, t2, r2); glVertex3f(x, y, z); OpenGL Multitexture Texture Environments • Chain of Texture Environment Stages Pre-texturing color glColor3f(r,g,b) #0 glMultiTexCoord2f( GL_TEXTURE0_ARB, …) glMultiTexCoord2f( GL_TEXTURE1_ARB, …) Lookup & filter GL_MODULATE #1 Lookup & filter GL_DECAL #2 glMultiTexCoord2f( GL_TEXTURE2_ARB, …) Lookup & filter GL_BLEND Post-texturing color Extending the OpenGL Texture Environment • ARB_multitexture is just the start – Standard OpenGL has just GL_REPLACE, GL_MODULATE, GL_DECAL, and GL_BLEND – ENV_texture_env_add introduces GL_ADD – ENV_texture_env_combine • Powerful “(AB + C) scale + bias” • A, B, C variables use various color inputs – Future texture environments even more powerful Examples of More Powerful Texture Environments • NVIDIA GPU OpenGL extensions – TNT and later GPUs support NV_texture_env_combine4 • A * B + C * D computation • multiple texture inputs available in a single stage • enables single-pass emboss bump mapping – GeForce and later GPUs support NV_register_combiners • dot products, signed math, much more • register processing model for non-sequential data flows Cube Map Texturing • Direct Use of Cube Maps – Latest hardware supports this • DirectX 7 support • OpenGL extension support – Hardware directly performs cube map accesses • Requires hardware support for good performance – Cube map construction much easier Using Cube Maps in OpenGL • Very easy to use ARB extension – New texture target: GL_TEXTURE_CUBE_MAP_ARB • Used for manipulating cube map as a whole – Six cube map “face” targets • • • • • Used for manipulating particular cube map faces GL_TEXTURE_CUBE_MAP_dir_axis _ARB dir is { POSITIVE, NEGATIVE } axis is { X, Y, Z } Use 2D texture image API (glTexImage2D, etc) Cube Map Support • Official OpenGL standard now – OpenGL cube map support was introduced by NVIDIA • GeForce drivers have EXT_texture_cube_map extension – OpenGL Architectural Review Board (ARB) recently accepted the extension as an ARB standard • renamed ARB_texture_cube_map • but same identical functionality • semantics & enumerant values same as the EXT version – Other vendors such as ATI planning cube map support OpenGL Cube Map Setup Usage Binding to a cube map texture glEnable(GL_TEXTURE_CUBE_MAP_ARB); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cmap); Loading cube map faces glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, level, format, width, height, border, format, type, positiveXpixels); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, level, format, width, height, border, format, type, negativeXpixels); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, level, format, width, height, border, format, type, negativeYpixels); •. . . similarly load other three faces . . . OpenGL Cube Map Rendering Usage • Enabling a cube map texture glEnable(GL_TEXTURE_CUBE_MAP_ARB); • Explicit cube map coordinates glTexCoord3f(vx, vy, vz); // (vx,vy,vz) is unnormalized direction vector • Generated cube map coordinates (recommended) glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_NORMALIZE); Advantages of Cube Maps • Compared to Other Approaches – View-independent • Unlike sphere mapping – Uses a single texture unit • Unlike dual-paraboloid mapping – Entire texture resolution is sampled • Unlike sphere or dual-paraboloid approaches – Improved environment sampling Getting Back to Object Space • No magic here. Just undo the transformation. Gldouble objX, objY, objZ; // get the modelview, project, and viewport glGetDoublev( GL_MODELVIEW_MATRIX, mv_mat ); glGetDoublev( GL_PROJECTION_MATRIX, proj_mat ); glGetIntegerv( GL_VIEWPORT, viewport ); // get the current depth buffer g_depth_view = new GLfloat[winWidth * winHeight]; glReadPixels( 0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT, depth_view ); for( y = 0; y < winHeight; y ++ ) // go through every pixel in frame buffer for( x = 0; x < winWidth; x ++ ) { if ( *depth_view < 1.00 ) gluUnProject(x, y, *depth_view, mv_mat, proj_mat, viewport, &objX, &objY, &objZ); depth_view ++; }