Fast Silhouettes Article

Started by
18 comments, last by Jason Z 17 years, 6 months ago
I have posted an article that presents a (as far as I know) novel method for rendering silhouettes. The article is posted in my journal for those of you that are interested in checking it out. You can find it here along with a demo program for it: Journal Entry Hopefully this article will still end up on the main posting, but I don't know if it will or not. Please feel free to provide any feedback that you have, good or bad.
Advertisement
The pdf is just a blank page, at least in my browser?
Maybe try doing a save as, then open it from the desktop?
I did some stuff on silhouettes a while ago also (image), and I think there's at least one problem with your algorithm: it currently doesn't handle thick borders (as my image does). This is of course due to you working with and extruding edges, whereas the algorithm I devised offsets vertices to the exact corner of two neighbouring silhouette edges.

While I never did implement my algorithm on the GPU, I did find a paper of someone who did. I've just had another search for it, but unfortunately couldn't find it.

I'm not sure of the specifics anymore, but I know it only added an additional vertex for each existing vertex. It then added an additional attribute (a single value) which indicated if the vertex was of the original model (0.f), or of the newly added set (1.f).

Presumeably it created a new set of indices which would create fins along ALL edges. Then in the vertex shader the calculation for silhouette was done, and if it was determined that the edge was NOT a silhouette, the additional vertex was not offset. This created a degenerate triangle/quad, which the hardware should be able to strip away. If the edge WAS on the silhouette, the vertex was extended by a specific amount multiplied by the additional attribute. This caused the original vertices to stay where they were, and the added vertes (with value 1.f) to get the full offset.

The only thing I'm missing here is how the vertex shader was able to calculate if the edge was on a silhouette. But I guess that did work similar to how you are doing it. I'll see if I get a chance to check my backups, I think I might still have the paper somewhere.
Hi Rick,

Did you write a paper on your algorithm? It seems like my algorithm could be slightly modified to handle the situations that you mention - simply adding a normal per vertex to the silhouette mesh would be sufficient.

Did you produce a demo of your algorithm in action? If you did write up a paper, I would be very interested in seeing your work and comparing it with mine to see how we handled things differently.

Thanks for the response.
No, I didn't write anything up on my algorithm, but I should have a working version somewhere, along with source. I'll have to search my backups for those also.

I'll get back to you.
I also have an extremely fast silhouette algorithm of my own, which executes entirely in hardware on a fixed function OpenGL pipeline. The first time I coded it was on a Voodoo 3 back in 2002: http://arctangent.8k.com/oldprj/mod3.jpg This is a very old screenshot, when I get home to my computer I can make and post a higher quality shot using better tweaked code.

The algorithm draws silhouettes around objects by drawing all edges of an object, and letting the Z buffer decide which lines are actually an edge that needs to be drawn:

-Enable glPolygonOffset, so that polygon fills are rendered above lines of the same depth.

-Render all the geometry normally.

-If you are using the depth buffer function GL_LEQUAL, switch to GL_LESS at this time. (GL_LEQUAL could potentially introduce z-fighting with the outline vs. the polygon fills when objects are far away from the camera.)

-Render objects to be outlined, in black unlit wireframe.


This has the following effects:

-Most of the lines drawn will be behind the polygons fills, and will fail the z-test. It is (at least at the time I started doing this) faster to send an edge to the video card than to figure out whether or not it should be drawn.

-Lines at the edges of polygons will not be completely obstructed by polygon fills, and will be visible.

-When rotating a cartoon outline object, traditional algorithms that simply elect to draw or not draw a particular line, result in harsh edges and lines popping on and off. My z-buffer silhouette algorithm does not do this: a single line can be anywhere from not shown to thin, to thick, depending on viewing angle. A line does not simply pop on and off, it begins to appear a few pixels at a time, then as the object continues to rotate, a particular line will gain strength and thickness. Then as a feature on the surface of an object begins to rotate out of view, the line starts to thin out, until it is completely invisible again.
Interesting method DracoLacertae. Sounds like it would work well.

It is a bit at odds with what I was trying to do, since I was trying to have lines of the same thickness everywhere :D
I've found *some* source although I can't guarentee it's the latest. This zip file contains the source for the app (minus my engine) and an executable. You'll need the glut dll for it apparently (don't remember why).

The source to calculate the silhouettes should be in silhouetteDetection.cpp/.hpp, and it's used in mywindow.cpp in the RenderModel function. Most of the utility stuff should be fairly clear, but feel free to post if you have any questions.
Thanks a bunch for the demo - I will have to dig into the code later on tomorrow. Did you ever adapt your method to be able to render ridges and valleys as well? This was one of the main drivers behind my implementation - to be able to render ridges, valley, and silhouettes all at once.

Thanks again for the post, I'll give you some feedback on it as soon as I can.

This topic is closed to new replies.

Advertisement