"Speckled" Semitransparent Objects

I’m trying to display a semitransparent, 3D object which is roughly cylinder-shaped and has open ends. I’m not culling back faces. I’m finding that, when I look through one layer of faces, the object looks fine, but as I look through two or more layers of faces – such as the front surface and back surface of the cylinder – both surfaces seem to have ugly splotches on them. The splotches are “glued” to the object like a texture map. It looks like some of the faces might be fully opaque, while others might be fully transparent. Hopefully my description makes sense.

What am I doing wrong? Here is some info about my setup…

I’ve glEnabled both GL_BLEND and GL_COLOR_MATERIAL.

I set blending using…

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

I’ve set the color material using…

glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)

I set the material using…

glMeterialfv with face set to GL_FRONT (although the problem persists if it’s GL_FRONT_AND_BACK), pname set to GL_DIFFUSE and params set to the desired color (with alpha set below 1).

What am I doing incorrectly?

Thanks in advance!

When you render non-opaque geometry, you have to sort the polygons by their distance to the camera and draw them back to front. Either you sort the geometry on the client side, or
you implement the depth peeling algorithm in OpenGL.

That’s because the blending operation is order-dependent.

Thanks for the reply, overlay.

Just before the actual drawing commands, I found an errant line of code which caused the “speckling:”

glDepthMask(GL_TRUE)

I removed this, and now things no longer look speckled.

My code does not currently sort polygons by distance to the camera. The steps I’m performing are…

  1. Render all opaque objects in arbitrary order with the depth buffer in normal operation.

  2. Enable blending, set the depth buffer to read-only, and set the blend function with src=GL_SRC_ALPHA and dst=GL_ONE.

  3. Render all non-opaque objects in arbitrary order.

  4. Set the depth buffer back to normal, and disable blending.

My understanding is that drawing non-opaque objects back-to-front affects the final color of the pixel. For example, regardless of their distance from the camera, rendering a blue object before a red object will likely result in a different color than rending a red object before a blue object.

What should be done in the following situation? Let’s say I have two spheres, A and B. Sphere B is “embedded” in Sphere A. Let’s say that the camera is positioned such that the front-to-back Z order of the surfaces is:

  1. Front surface of Sphere A
  2. Front surface of Sphere B (because B is embedded in A)
  3. Back surface of Sphere A
  4. Back surface of Sphere B

Is it sufficient simply to draw Sphere B, then Sphere A, or would I need to split A and B into hemispheres, drawing them in the order BackHemisphere B, BackHemisphere A, FrontHemisphere B, FrontHemisphere A?

Thanks for the help thus far. I imagine that these questions have been asked countless times by countless other OpenGL rookies.

Yes you need to split A and B into 2 hemispheres.

Here is the main page for the OpenGL FAQ: http://opengl.org/resources/faq/technical/

You will be interested by section “15 Transparency, Translucency, and Blending”: http://opengl.org/resources/faq/technical/#indx0150

and notably

“15.050 Do I need to render my primitives from back to front for correct rendering of translucent primitives to occur?” http://opengl.org/resources/faq/technical/transparency.htm#blen0040

“If your hardware supports destination alpha, you can experiment with different glBlendFunc() settings that use destination alpha. However, this won’t solve all the problems with depth buffered translucent surfaces. The only sure way to achieve visually correct results is to sort and render your primitives from back to front.”

Thanks for the links!