This may be somewhat naive, but I think it solves all of the cases that I want. If I have overlooked something, please set me straight…
First, let me specify that my “transparent” surfaces are more like (stained) glass or filters. The color of the surface describes what percentage of which components of light it will allow to pass. A colored piece of glass can NEVER add a color to something. Consider a piece of red glass with a blue object behind it. All you will see through the glass is black.
By contrast, alpha-blending is more like a gauzy surface. Alpha-blended surface CAN add colors to things. If you had a thin piece of red fabric with a blue object behind it, it would tend to look purple.
“Colored glass” transparency is more accurate than “alpha blended” transparency for windows, cockpits, etc. It does lack the ability to “reflect” color back at you – a real piece of red glass could still look slightly red even with no light behind it, due to reflections and internal reflections. This is especially noticeable if you are trying to do, say, a yellow forcefield around a spaceship – with no light behind the shield, you won’t be able to see the shield itself, and it will just look like you tinted the spaceship itself yellow. But, if what you are trying to render is a complex scene with plenty of light behind your objects (say, a landscape or a white “virtual bench” for a CAD system), then you will be able to see the transparent object just fine.
On the up side, your textures allow controlling the amount of transparency on a per-color basis, instead of just a per-pixel basis with alpha blending.
Alpha blending is order dependent, which is what leads to all of the headaches. Colored-glass transparency is simply modulation, which is just multiplication, and as we all know, multiplication (at least of scalars) is order-independent by nature. So if all of your transparent surfaces are more like colored glass than like gauzy fabrics, you can use modulation and render them in any order you want.
Some notes:
- You probably want to disable lighting calculations. Modulation can darken things VERY quickly, and if the lighting calculation decides that your glass isn’t very well lit, it’ll end up looking like smoked glass. Better to simply turn off lighting (or deliberately feed it messed up normals so that it tends to oversaturate, but “there there be dragons…”)
- Your “colored glass” textures will tend to look wildly oversaturated if you look at them in a paint program. That’s OK. You want them to look like a stained glass window sitting in front of a blinding spotlight. Otherwise you’ll darken things too much.
- And lastly, how to get modulation effects in blending, which many of you probably already know (but which I had somehow overlooked until recently): glBlendFunc(GL_DEST_COLOR, GL_ZERO) or glBlendFunc(GL_ZERO, GL_SRC_COLOR) (both will do the same thing)
I haven’t really thought about it, but replacing GL_ZERO with some other value might provide the ability to handle some of the “reflected color” aspects. Of course, it would probably also ruin the “order independence” of the process…
I only bring this up because none of my OpenGL programming resources ever mentioned using this for transparency. They all talk about the alpha channel and depth sorting, which is just hideous if you are trying to build a object oriented scene graph and don’t want to require objects to submit lists of polygons to a global depth sorter/renderer component. It just seems like a tremendous amount of effort has been put forward to make alpha blending work “right” when modulation was just sitting there for the taking. I apologize if this was well known, and I apologize profusely if this approach has well-known problems other than the “reflected color” one I mentioned. I would appreciate any advice from those of you who might have tried this approach.
Thanks,
Mac