Clever Uses of OpenGL Kurt Akeley CS248 Lecture 16 15 November 2007 http://graphics.stanford.edu/courses/cs248-07/ Emphasis Is on OpenGL mechanisms and their application OpenGL is a power tool It can be applied in clever and non-obvious ways Is not full coverage of useful graphics algorithms Many will not be covered But what we do cover will be useful CS248 Lecture 16 Kurt Akeley, Fall 2007 Reference Advanced Graphics Programming Using OpenGL Tom McReynolds (NVIDIA) David Blythe (Microsoft, Direct3D 10 architect) CS248 Lecture 16 Kurt Akeley, Fall 2007 Informal taxonomy of clever uses Accumulation Z-buffer Transparent surfaces Multisample antialiased surfaces with pre-filtered lines Image composition Texture Contour mapping Image warping Billboards Implementing pre-filter antialiasing with texture lookup Volume rendering Polygon offset Coplanar primitives Hidden-line rendering Stencil Capping Shadow volumes GPGPU CS248 Lecture 16 Kurt Akeley, Fall 2007 Invariance On a single machine Appendix A Invariant enable/disable Consistent input sequence E.g., use glFrontFace to reverse facing direction, rather than reordering the vertexes or reflecting by scaling Cross-platform Be careful! OpenGL’s design emphasized cross-platform compatibility But there are still many differences between platforms Endian issues and support CS248 Lecture 16 Kurt Akeley, Fall 2007 Accumulation CS248 Lecture 16 Kurt Akeley, Fall 2007 Accumulation Basic idea: Build up a final image in the framebuffer by depth buffering and/or blending multiple images Examples Z-buffer Transparent surfaces Multisample solids with pre-filtered antialiased lines Image composition CS248 Lecture 16 Kurt Akeley, Fall 2007 Z-buffer glEnable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST); glDepthFunc(GL_NEVER | GL_LESS | GL_EQUAL | GL_LEQUAL | GL_GREATER | GL_NOTEQUAL | GL+GEQUAL | GL_ALWAYS); glDepthFunc(GL_ALWAYS); // invariant disable glDepthMask(GL_TRUE); glDepthMask(GL_FALSE); if (Zfrag depthfunc if (Rcolormask) if (Gcolormask) if (Bcolormask) if (Acolormask) if (depthmask) } CS248 Lecture 16 // enable writing // disable writing Zpixel) { Rpixel Gpixel Bpixel Apixel Zpixel Rfrag; Gfrag; Bfrag; Afrag; Zfrag; Kurt Akeley, Fall 2007 Transparent surfaces glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); draw opaque objects glDepthMask(GL_FALSE); // key OpenGL mode glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_CULL_FACE); // optional glCullFace(GL_BACK); draw transparent surfaces in any order glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); CS248 Lecture 16 Kurt Akeley, Fall 2007 Multisample and pre-filter antialiasing glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_MULTISAMPLE); draw solid objects (triangles) glDepthMask(GL_FALSE); glDisable(GL_MULTISAMPLE); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glDisable(GL_LIGHTING); // optional draw pre-filter antialiased lines in any order glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDepthMask(GL_TRUE); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); CS248 Lecture 16 Kurt Akeley, Fall 2007 Image composition (fade) glEnable(GL_BLEND); glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE); glBlendColor(0, 0, 0, first weight); glDrawPixels(first image); glBlendColor(0, 0, 0, second weight); glDrawPixels(second image); glDisable(GL_BLEND); CS248 Lecture 16 Kurt Akeley, Fall 2007 Image composition (over) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ZERO); glDrawPixels(first image); gllendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDrawPixels(second image); glDisable(GL_BLEND); CS248 Lecture 16 Kurt Akeley, Fall 2007 Texture CS248 Lecture 16 Kurt Akeley, Fall 2007 Texture Basic idea: Use texture mapping mechanisms for creative purposes Examples Contour mapping Image warping Billboards Implementing pre-filter antialiasing texture lookup Volume rendering CS248 Lecture 16 Kurt Akeley, Fall 2007 Contour mapping glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_TEXTURE_1D); glEnable(GL_TEXTURE_GEN_S); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv(GL_S, GL_EYE_PLANE, vec4f(f, 0, 10, 0, 0)); draw objects without specifying texture coordinates glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_1D); glDisable(GL_TEXTURE_GEN_S); Today a vertex shader is a more general TexGen mechanism. But the notion of generated texture coordinates remains important. CS248 Lecture 16 Kurt Akeley, Fall 2007 Image warping glEnable(GL_TEXTURE_2D); for (y=0; y<(height-1); ++y) { glBegin(GL_QUAD_STRIP); for (x=0; x<width; ++x) { glTexCoord2fv(tex[index(x,y)]); glVertex2fv (vtx[index(x,y)]); glTexCoord2fv(tex[index(x,y+1)]); glVertex2fv (vtx[index(x,y+1)]); } glEnd(); } CS248 Lecture 16 Kurt Akeley, Fall 2007 Billboards Poster-child application of geometry shaders! Application Vertex assembly Vertex operations Primitive assembly Primitive operations Rasterization Fragment operations Advanced Graphics Programming Using OpenGL Figure 13.4 Framebuffer Display CS248 Lecture 16 Kurt Akeley, Fall 2007 The magic of machine shops Sewing machines make clothes But machine tools make machine tools And computers are this century’s machine tools Hagley Machine Shop, Wilmington, DE Photo by Incaz, Flickr CS248 Lecture 16 Kurt Akeley, Fall 2007 Pre-filter antialiasing via texture lookup Another ideal geometry-shader application // draw pre-filtered point at (x,y) const float h = 1.5; // 3x3 filter glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x-h, y-h); glTexCoord2f(0, 1); glVertex2f(x-h, y+h); glTexCoord2f(1, 1); glVertex2f(x+h, y+h); glTexCoord2f(1, 0); glVertex2f(x+h, y-h); glEnd(); Application Vertex assembly Vertex operations Primitive assembly Primitive operations Rasterization (0 1) (1 1) (x-h y+h) (x+h y+h) Fragment operations Framebuffer (0 0) CS248 Lecture 16 (1 0) (x-h y-h) (x+h y-h) Display Kurt Akeley, Fall 2007 Volume rendering Advanced Graphics Programming Using OpenGL Figure 20.12 Advanced Graphics Programming Using OpenGL Figure 20.13 CS248 Lecture 16 Kurt Akeley, Fall 2007 Polygon Offset CS248 Lecture 16 Kurt Akeley, Fall 2007 Polygon offset Basic idea: Avoid depth fighting by biasing Z values Examples Coplanar primitives Hidden lines Silhouette edges CS248 Lecture 16 Kurt Akeley, Fall 2007 Polygon mode glPolygonMode(GLenum face, GLenum mode); GL_FILL, GL_LINE, GL_POINT Face culling happens before conversion to lines or points! GL_FRONT, GL_BACK, GL_FRONT_AND_BACK GL_FILL CS248 Lecture 16 GL_LINE GL_POINT Kurt Akeley, Fall 2007 Polygon offset Correspond to polygon modes glEnable/glDisable(GL_POLYGON_OFFSET_FILL | GL_POLYGON_OFFSET_LINE | GL_POLYGON_OFFSET_POINT); glPolygonOffset(GLfloat factor, GLfloat units); 2 2 æ¶ zw ö æ¶ zw ö ÷ ÷ ç çç ÷ ÷ zw¢ = zw + units ×r + factor × çç + ÷ ÷ ç ÷ è ¶ yw ø ÷ è¶ xw ø Triangle (on edge) Line (on edge) Minimum resolvable zbuffer difference -z View position CS248 Lecture 16 Kurt Akeley, Fall 2007 Coplanar primitives glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(maxwidth/2, 1); draw planar surface glDepthMask(GL_FALSE); glDisable(GL_POLYGON_OFFSET_FILL); draw points, lines, and polygons on the planar surface glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDepthMask(GL_TRUE); CS248 Lecture 16 Kurt Akeley, Fall 2007 Hidden lines glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glColorMask(false, false, false, false); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(maxwidth/2, 1); draw solid objects glDepthMask(GL_FALSE); glColorMask(true, true, true, true); glColor3f(linecolor); glDisable(GL_POLYGON_OFFSET_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); draw solid objects again glDisable(GL_DEPTH_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDepthMask(GL_TRUE); CS248 Lecture 16 Kurt Akeley, Fall 2007 Silhouette lines (true hidden-line drawing) glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glColorMask(false, false, false, false); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(maxwidth/2, 1); draw solid objects Additions to the hiddenline algorithm (previous slide) highlighted in red glDepthMask(GL_FALSE); glColorMask(true, true, true, true); glColor3f(1, 1, 1); glDisable(GL_POLYGON_OFFSET_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); draw solid objects again draw true edges // for a complete hidden-line drawing glDisable(GL_DEPTH_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDepthMask(GL_TRUE); glDisable(GL_CULL_FACE); CS248 Lecture 16 Kurt Akeley, Fall 2007 Stencil CS248 Lecture 16 Kurt Akeley, Fall 2007 Stencil Basic idea: Implement a simple state machine in every pixel Examples Capping Shadow volumes CS248 Lecture 16 Kurt Akeley, Fall 2007 Stencil glEnable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST); glStencilFunc(GLenum func, GLint ref, GLuint mask); GL_NEVER, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL, GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS glStencilOp(GLenum fail, GLenum zfail, GLenum zpass); Bitmask, not Boolean flag glStencilMask(GLuint mask); CS248 Lecture 16 GL_KEEP, GL_ZERO, GL_REPLACE (with ref), GL_INCR, GL_DECR, GL_INVERT Kurt Akeley, Fall 2007 Z-buffer operation (again) if (Zfrag depthfunc if (Rcolormask) if (Gcolormask) if (Bcolormask) if (Acolormask) if (depthmask) } CS248 Lecture 16 Zpixel) { Rpixel Gpixel Bpixel Apixel Zpixel Rfrag; Gfrag; Bfrag; Afrag; Zfrag; Kurt Akeley, Fall 2007 Stencil operation if ((ref & mask) stencilfunc (Spixel if (Zfrag depthfunc Zpixel) { if (Rcolormask) Rpixel if (Gcolormask) Gpixel if (Bcolormask) Bpixel if (Acolormask) Apixel if (depthmask) Zpixel StencilOp(zpass); } else { StencilOp(zfail); } } else { StencilOp(fail); } CS248 Lecture 16 & mask)) { Rfrag; Gfrag; Bfrag; Afrag; Zfrag; Z-buffer operation Stencil implements a state machine in each pixel . (A programmable action occurs in every cases) Kurt Akeley, Fall 2007 Capping glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); for (int i=0; i<max; ++i) { drawWithCap(model, i); // remains enabled … drawWithCap(int model, int i) { setMaterial(model, i); glEnable(GL_CLIP_PLANE0); glEnable(GL_STENCIL_TEST); glEnable(GL_CULL_FACE); glStencilFunc(GL_GEQUAL, 1, 3); glCullFace(GL_BACK); glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); drawModel(model, i); // don’t change capped pixels // render frontfacing only // clear stencil to 0 glCullFace(GL_FRONT); // render backfacing only glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // set stencil to 1 drawModel(model, i); glDisable(GL_CULL_FACE); glDisable(GL_CLIP_PLANE0); glStencilFunc(GL_EQUAL, 1, 3); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); drawCap(); glDisable(GL_STENCIL_TEST); CS248 Lecture 16 } // draw only where stencil is 1 // set stencil to 2 Kurt Akeley, Fall 2007 Shadow volumes Similar to capping: Render the scene Render shadow volumes Don’t change color or depth Use stencil to determine in/out Reduce intensities of pixels in shadow Common game technique E.g., Quake, Doom Simple frustum culling fails! Must keep light sources and occluders that cast shadows on geometry within the frustum CS248 Lecture 16 Kurt Akeley, Fall 2007 GPGPU CS248 Lecture 16 Kurt Akeley, Fall 2007 GPGPU Basic idea: General-purposes computing on GPUs Take advantage of the huge compute power of modern GPUs CS248 Lecture 16 Kurt Akeley, Fall 2007 Multi-pass vector processing (2000) Treat OpenGL as a very long instruction word Compute vector style Apply inst. to all pixels Build up final image in many passes Peercy, Olano, Airey, and Ungar, Interactive Multi-Pass Programmable Shading, SIGGRAPH 2000 (Figure adapted from the SIGGRAPH paper) CS248 Lecture 16 #include “marble.h” surface marble() { varying color a; uniform string fx; uniform float x; x = ½; fx = “noisebw.tx”; FB = texture(tx, scale(x,x,x)); repeat(3) { x = x * 0.5; FB *= 0.5; FB += texture(tx, scale(x,x,x)); } FB = lookup(FB,tab); a = FB; FB = diffuse; FB *= a; FB += environment(“env”); } Kurt Akeley, Fall 2007 GPGPU Still operates on images Conceptually 2-D arrays of data elements Deemphasizes VLIW thinking Most pipeline stages are not used What is used: Rasterization (to generate and schedule data elements) Fragment operations (specifically the programmable shader) Texture lookup and filter (gather, not a stream processor) Fragment/framebuffer operations (usually limited to write) Emphasizes data-parallel programmability Clever solutions have been developed for Scatter Reduction Sorting … CS248 Lecture 16 Kurt Akeley, Fall 2007 Modern GPGPU Graphics APIs (OpenGL, Direct 3D) being replaced: CUDA (NVIDIA) CTM (AMD) Great results being achieved: Technical: 10x performance improvement in some cases Business: multi-billion dollars anticipated soon Coming soon: IEEE double precision arithmetic Greater exposure of hardware details (AMD) Intel Larrabee … CS248 Lecture 16 Kurt Akeley, Fall 2007 Summary Powerful OpenGL mechanisms (some introduced by IRIS/OpenGL): 8-way comparison and masks (depth, stencil, alpha, …) Texture features: 3-D TexGen and Texture coordinate matrix Homogeneous coordinates Application to all primitives (not just triangles) glPolygonOffset Stencil (state machine in a pixel) Shaders have devalued some of these (e.g., TexGen) but most remain valuable It’s fun and productive to devise clever uses of OpenGL CS248 Lecture 16 Kurt Akeley, Fall 2007 Assignments No class next week Next lecture: Color theory (Tuesday 27 November) Reading assignment: FvD 13.2 through 13.6 CS248 Lecture 16 Kurt Akeley, Fall 2007 End CS248 Lecture 16 Kurt Akeley, Fall 2007