Path: cantaloupe.srv.cs.cmu.edu!ph From: ph+@cs.cmu.edu (Paul Heckbert) Newsgroups: comp.sys.sgi.graphics Subject: edge highlighting, summary (1/5) Date: 22 Nov 1996 21:25:34 GMT Organization: School of Computer Science, Carnegie Mellon ---------- initial posting > Newsgroups: comp.sys.sgi.graphics > Subject: how to do edge highlighting / hidden lines? > Date: Fri, 18 Oct 96 18:37:34 EDT > From: ph@HOSTESS.GRAPHICS.CS.CMU.EDU > > I want to draw polyhedra with highlighted edges (filled, shaded polygons, > but edges drawn with one pixel wide white lines, with z-buffering). > This has to work on Indy's and Indigo2's. > > Does Opengl support this, or am I on my own? > > Here are several solutions, some of which I've tried; > none of them appear very satisfactory: > > 1. > If you draw the edges using glBegin(GL_LINES) ... glEnd() > and draw the polygons in the usual way with glBegin(GL_POLYGON) ... glEnd(), > if you don't do anything special to offset the lines away from the polygons, > the lines will be eaten away (overwritten) in places by the filled polygons. > The "eating" is particularly severe when polygons are being viewed at > a grazing angle. The results with this method look very poor. > > 2. > If you do the above but offset the edge lines in the direction of the vertex > normal by a small object space vector before passing them to Opengl, the > results are semi-acceptable, but with perspective, the offset will sometimes > be so big as to create a visible gap, and it will sometimes be so small > that the lines are still eaten away. > > 3. > "man glPolygonOffsetEXT" says > This is useful for rendering hidden line images, for applying decals to > surfaces, and for rendering solids with highlighted edges. > Sounds like just the thing! But does it work? > The documentation is vague, but apparently this is offsetting in the > direction of the viewer (screen space z). > But based on my experiments (see code at http://www.cs.cmu.edu/~ph/src/edge.c), > it only seems to offset filled polygons, not lines (on an Indigo2, at least). > > 4. > If you have an "Infinite Reality Engine" then you can call > glReferencePlaneSGIX and it will do offsetting of lines correctly, > the documentation says. I don't have one of these machines, > and none of my users will. > > 5. > I could do this offsetting in software, but that requires me to do a few > vector operations per vertex to compute the offset vector in object space, > scale it, and apply it. One of the goals of SGI mahines and Opengl, > I thought, was to free the programmer of doing their own 3-D transformations. > > 6. > Another way to go is to use stencils (opengl red book, p. 402), but that > requires traversing each polygon 3 or 4 times, which is inelegant & slow. > > 7. > Yet another way to go is to use texture mapping, but that's too slow. > > 8. > Or I could draw the lines as thin rectangles parallel to the polygon > from which they come, about one pixel wide in screen space, using > glPolygonOffsetEXT, but that would require me to transform stuff into > screen space and back in software just to figure out the vertices for > the rectangle. > > 9. > I could draw cylinders with 4 or 6 sides with radius a fixed fraction of > my object size. This is not the effect I want. Sometimes the cylinders > would come out too fat, and sometimes too thin (& intermittent). > I want lines that are about one pixel wide. > > > So far, method 5 looks like the best solution. Is there a better solution > than 5? Surely I'm not the first person to confront this problem with > SGI's and Opengl. By the way, highlighting of edges is trivial to do with > HP's graphics library. > > > -Paul > > Paul Heckbert > Computer Science Dept., Carnegie Mellon University > 5000 Forbes Ave, Pittsburgh PA 15213-3891, USA > > ph@cs.cmu.edu http://www.cs.cmu.edu/~ph ---------- summary The consensus was that for most machines, method 3 (offsetting in screen z) is the best. If you've got an Infinite Reality Engine (or better) then use method 4 (reference planes). Method 6 also works, but requires three or more passes through the geometry and so is probably slower (I haven't tested it thoroughly, but that's my initial impression). Method 3 will work even better when OpenGL 1.1 becomes available. ---------- method 3: offsetting polygons / edges Mark Segal, Michael Jones, and Chris Schoeneman suggested I use glPolygonOffsetEXT not as I was attempting above, to pull the edges forward of the polygons, but to push the polygons behind the edges. Note, however, that glPolygonOffsetEXT is not supported for all platforms (it is an Opengl extension). Allen Akin sent me some Opengl code, hiddenline.c, originally written in GL by Kurt Akeley, that demonstrates this technique. Refer to that code to see how to check that the extension is available, to turn on offsetting, and to set the offset. Akeley used the call glPolygonOffsetEXT(1.0, 0.000001); to set the coefficients. The first argument controls a constant offset, the second is a coefficient on the polygon's slope (it's necessary to offset oblique polygons more than perpendicular ones). Experimentation showed that these values gave the best results. The second argument is about 2^-20, and works well for a 24 bit z-buffer, which is typical on SGI machines. This method works pretty well. It's not perfect, however: still some gaps and some erroneous polygon intersections. Sometimes back-facing polygons poke through the front facing ones near the silhouette, and if you're drawing faces in different colors then this shows up. In some cases I could turn off backfacing polygons, but that doesn't work for all models. You can see the bug with hiddenline.c if you turn some of the polygons nearly edge-on and look closely at the picture (with "mag", say). --- From: akin@sgi.com (Allen Akin) Date: Fri, 18 Oct 1996 19:02:22 -0700 Subject: Re: how to do edge highlighting / hidden lines? Most people use the polygon_offset extension. You're correct that it offsets only polygons, not lines, in OpenGL 1.0. So rather than pull the edges forward in order to make them visible, you must push the polygons away from the viewer. Are you using IRIX 6.2, and do you have the gl_dev.sw.samples subsystem installed? If so, there's an edge-highlighting example in /usr/share/src/OpenGL/demos/hiddenline Also, the man-page entry for glPolygonOffsetEXT is more helpful in IRIX 6.2 than it was in earlier releases. --- From: "Mark Segal" Date: Mon, 21 Oct 1996 10:21:12 -0700 Subject: Re: how to do edge highlighting / hidden lines? ... the version of glPolygonOffset that went into OpenGL 1.1 is a little different from the extension version. The 1.1 version allows controlling whether the the offset applies to points, line segments, or filled polygons (in conjunction with the polygon mode). But 1.1 isn't supported at the moment on any SGI machine (except maybe O2?). [Some Microsoft systems already have it.] So, sometime in the not too distant future you should be able to do what you want [offset the edges] on SGI machines (that are current then). But I guess for now you'll have to suffer with offsetting the polygons only. If you're interested, you can check out the OpenGL 1.1 behavior at http://reality.sgi.com/rck/glspec1.1/node58.html --- From: Allen Akin Subject: Re: hiddenline.c Date: Mon, 21 Oct 1996 10:45:00 -0700 [with glPolygonOffsetEXT in Opengl 1.0], since the size of the offset depends on the polygon's Z slope, adjacent polygons that differ in slope will crack apart. The highlighted edges cover some of the gaffes, but not all of them. The OpenGL 1.1 version of this feature allows you to draw a polygon's edges with an offset derived from the face, so it should be marginally better. I guess it'll take us another six months or so to provide OpenGL 1.1 on all platforms, though. --- Other info hiddenline.c sent to me by Allen Akin, SGI C / Opengl code that demonstrates this method *** Posted in a followup to this message. "man glPolygonOffsetEXT" from IRIX 6.2 improved man page explains it better *** Posted in a followup to this message. http://reality.sgi.com/rck/glspec1.1/node58.html Opengl 1.1 spec for polygon offset ---------- method 4: drawing edges with reference plane To my mind, it's inelegant to offset the lines by a variable amount as a function of the polygon slope. A more elegant solution is to draw all the pixels of the edge lines in a plane parallel to, and offset by a small constant amount from, the polygons they surround. This can currently be done with glReferencePlaneSGIX if you have an Infinite Reality Engine or better! To work correctly at concave corners (e.g. looking into the corner of a room), you'd need to draw each edge twice, once in the plane of each of the adjacent polygons. If the lines generate pixels with identical xy's and colors, but only the z's differ, then there will be no artifacts from drawing the edges twice. (I think it might even be possible to draw these lines with antialiasing and get a very clean picture). ---------- method 6: stencils The stencil method is described in Opengl Programming Guide, Neider et al (red book) page 402 Kurt Akeley The Hidden Charms of Z-Buffer Iris Universe Vol. 11 Spring 1990 A nice article that discusses how to set near & far clipping planes intelligently to avoid poor z-buffer resolution. Describes 4-pass stencil technique for old SGI GLX hardware, gives some GL code, so the code is a bit obsolete now. Kurt Akeley ABCs of the Z-Buffer SGI Pipeline, Vol 2, No 1, Jan. 1, 1991 Reprint of the "Hidden Charms" paper. According to http://www.sgi.com/Support/pipeline.html this article is available on line if you have SGI's "Support Advantage CD-ROM". *** Text version posted in a followup to this message. Russ Herrell, Joe Baldwin, Chris Wilcox, High-Quality Polygon Edging, IEEE Computer Graphics and Applications, July 1995, pp. 68-74. Describes a 3-pass stencil-like method; not Opengl. Written by folks at HP. stenedge.c posted to comp.sys.sgi.graphics on 20 Jan 1994 by Kurt Akeley C / GL code to do hidden line drawing using stencils *** Posted in a followup to this message. --- From: akin@sgi.com (Allen Akin) Date: Fri, 18 Oct 1996 19:02:22 -0700 Subject: Re: how to do edge highlighting / hidden lines? The stencil method (see the July 1995 CG&A) seems to yield the best results, though it's slow if your machine doesn't have hardware support for stencilling. --- From: Michael Jones Subject: Re: how to do edge highlighting / hidden lines? Date: Fri, 18 Oct 1996 23:07:01 -0700 Paul Heckbert wrote: > "man glPolygonOffsetEXT" says > But based on my experiments (see code at http://www.cs.cmu.edu/~ph/src/edge.c), > it only seems to offset filled polygons, not lines (on an Indigo2, at least). push the polygons away rather than pulling the lines forward. The IRIS Performer sample program perfly contains code for this in "style.c". > 4. > If you have an "Infinite Reality Engine" then you can call... yes, reference planes solve the problem with perfection -- but as you say, InfiniteReality solves every graphics problem except poverty. > 6. > Another way to go is to use stencils (opengl red book, p. 402), but that > requires traversing each polygon 3 or 4 times, which is inelegant & slow. actually, stencil takes no extra passes for this application: foreach polyhedron foreach polygon in the polygedron 1. enable z-buffering 2. enable "set stencil based on z-pass" mode 3. draw the polygon 4. disable z-buffering 5. enable "draw wherever stencil is set" mode 6. outline the polygon This gives perfect results in all cases for this application and only requires a 1-bit deep stencil buffer. [I believe there's a third pass required there, to clear the stencil buffer -Paul Heckbert] > 7. > Yet another way to go is to use texture mapping, but that's too slow. FYI #1: The dynamic terrain demo shown in the SGI booth at SIGGRAPH used exactly this method. > 8. > Or I could draw the lines as thin rectangles parallel to the polygon... FYI #2: The "wireframe" picture in the Renderman rendering-qualities sequence in the Renderman book (and in Foley & vanDam) used exactly this approach, with cylinders for lines and spheres for end-caps, all exactly inverse transformed to be of fixed screen width. ... Polygon Offset works and is fast. Stencil works and is pretty fast (very fast on some machines). Reference Plane works and is fast. All of these are supported by OpenGL. All of these are supported by IRIS Performer and only take a call or two to put into play. -- Be seeing you, Phone:415.933.1455 Fax:415.965.2658 MS:8U-590 Michael T. Jones Silicon Graphics, SSG--Advanced Graphics Division mtj@sgi.com 2011 N. Shoreline Blvd., Mtn. View, CA 94039-7311 118 Mario 64 Stars OpenGL/ImageVision/OpenInventor/Performer/Cosmo3D --- From: Chris Schoeneman Subject: Re: how to do edge highlighting / hidden lines? Date: Sat, 19 Oct 1996 20:28:42 -0700 Michael Jones wrote: > actually, stencil takes no extra passes for this application: > ... Wait a minute -- outlines on the polyhedra silhouette edges still exhibit stitching using this method because, on average, half the pixels of each line will fall outside the pixels covered by the polyhedra. This isn't the same problem as the depth buffer stitching, though, and the internal edges will be perfect. ---------- Paul Heckbert Computer Science Dept., Carnegie Mellon University 5000 Forbes Ave, Pittsburgh PA 15213-3891, USA ph@cs.cmu.edu http://www.cs.cmu.edu/~ph