3D meshes Transparency and background color

Hi guys,
I have written a 3D mesh viewer. The way it works is that it reads the coordinates of the points of a set of triangles and then it renders them using OpenGL-classics. Now the problem is when I am trying to make the object transparent so I can see inside. When the background is black everything is fine. When the object’s alpha value goes to zero the object disappears. However, when the background is white the object disappears immediately before I move the slider which changes the alpha value. The code I am using is the following:

if (meshMode == TRANSPARENT)
{
glEnable(GL_BLEND);
glDepthMask(GL_FALSE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);

for (color = 0; color < colorsnumber; color++)
{
vMaterialColors[color].ambientFront[3] = meshAlpha;
vMaterialColors[color].diffuseFront[3] = meshAlpha;
}
}

// if we do not desire to hide the boundary mesh (meshMode == HIDE)
if (meshMode != HIDE)
{
glBegin(GL_TRIANGLES);

for (i = 0; i < bfacetsnumber; i++)
{
facet = facetSet_[i];
marker = bfacetmarkerlist[facet];

e1 = bfacetlist[3facet + 0];
e2 = bfacetlist[3
facet + 1];
e3 = bfacetlist[3*facet + 2];

v1 = pointlist + 3e1;
v2 = pointlist + 3
e2;
v3 = pointlist + 3*e3;

// we need minimum marker in case of negative markers
color = vColorIPalette[marker-minimummarker];
vMaterialColors[color].switchOn();

// calculate normal of the triangle with vertices v1,v2,v3
normal_at(normalspointout, v1, v2, v3, norm);
glNormal3dv(norm);

if (normalspointout)
{
glVertex3dv(v1);
glVertex3dv(v2);
glVertex3dv(v3);
}
else
{
glVertex3dv(v2);
glVertex3dv(v1);
glVertex3dv(v3);
}
}
glEnd();
}

Now I tried to change the first lines related to the blending to:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

This works nicely with white background and black background. However some of the mesh triangles appear with darker color than the other ones. As a result you do not see a transparent cube as you see in the first case, but a transparent cube of which some parts are rendered darker and give the feel that somebody has painted those parts of the cube with a darker color or something like the cube is made of different materials here or there. I do not know how to attach pictures on this forum for you to see exactly what the problem is.

Any ideas?

Transparency is hard to make right.
When enabling blending, check the following :

  1. backface culling : depending on you needs, you may want to disable it.
  2. depth testing : it assume the nearer surface completely occlude the farther ones, which is wrong whith blending. Disable it.
  3. drawing order : subtractive transparency is order dependent, you should sort your triangles to draw then from back to front. Search for “bucket sorting”, very fast.

Additive transparency (GL_SRC_ALPHA, GL_ONE) is order independant, so if you can accept it, point 3) can be skipped.

I managed to achieve that effect on white background without any sorting by calling twice the routine which draws my surface (a triangle list) by:

glEnable(GL_CULL_FACE);

glCullFace(GL_BACK);
drawSurfaceMesh();

glCullFace(GL_FRONT);
drawSurfaceMesh();

glDisable(GL_CULL_FACE);

However the technique above only works for convex surfaces. For non-convex ones when I use the
(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) I have a problem. When I use the (GL_SRC_ALPHA, GL_ONE) I do not have a problem at all if my background is black. However, the more my background foes to gray the more the object starts disappearing and when my background turns white the transparent object disappears completely.

Any more ideas?

I am also wondering, suppose I get into the trouble sorting the triangles with respect to the z coordinate of their center. I compile them inside a DisplayList and then render them from back to front. I assume that then everything will be great. However, what will happen when I rotate the object? Because the ones at the back will come in front?

If you have some idea, could you please write a code sample the way I explained what I did before so it becomes less painful to apply it directly?

Thanks in advance.

About your white background and blending problem, there were a similar problem few days ago here

In this thread, he used GL_SRC_ALPHA_SATURATE instead of GL_SRC_ALPHA, but the problem is pretty much the same. Lokk at the second post.

When I use the (GL_SRC_ALPHA, GL_ONE) I do not have a problem at all if my background is black. However, the more my background foes to gray the more the object starts disappearing and when my background turns white the transparent object disappears completely.

This mode, as I said earlier, is additive transparency.
What is “white + something” ? 255 + x ? When clamped, it always results in 255.

You can also try something like gl_dst_color, gl_zero. This will work on whitish backgrounds, but will stay black on black bg.

I believe that this is a weakness of OpenGL. When you compile a display list, the OpenGL should take care of sorting the triangles performing Culling for speeding up rendering e.t.c. This should be a kernel optimized by the vendors. We shouldn’t worry about that stuff. It seems though that we have to do the hard stuff ourselves.

I am wondering what is the case in Direct3D 9,10 ?

Culling by definition just removes back faces relating to the order in which face vertices are given. So this doesn’t take care og the mesh nature. You have to take care of it.

I believe that this is a weakness of OpenGL.

Transparency in the general case is a hard problem with rasterization hardware. D3D is no different.

Search for “depth peeling” for cutting edge stuff. It is quite slower and has its problems too.
Some background : http://www.vtk.org/Wiki/VTK/Depth_Peeling

I believe Nvidia has some demos.
EDIT here they are :
Old implem :
http://developer.nvidia.com/object/Interactive_Order_Transparency.html
Newer implem :
http://developer.download.nvidia.com/SDK/10/opengl/samples.html#dual_depth_peeling

  • As ZBuffer said, do sorting of the triangle indices(back-to-front). As sort value i use the z-value of (triangle center position transformed into camera space).

  • Render with normal blend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
    -> Works pretty well for me with almost no performance loss:)

  • You can’t use display lists then, since the triangle indices must be re-sorted every frame.
    -> Use VBOs(or plain vertex arrays) instead.

  • Limitation: When triangles intersect each other, triangle-sorting will not work correctly
    -> Depth peeling or triangle splitting. Never tried those…

Dear fellows,
thank you very much for the guidance and the advices. They are invaluable. Thank you also for your time.

  • You can’t use display lists then, since the triangle indices must be re-sorted every frame.
    -> Use VBOs(or plain vertex arrays) instead.

Hmmm. Vertex arrays I can do it. I know what to do. VBOs though I do not know what it is, I do not know how to do it and I do not know if it will speed things up. I had downloaded a few days ago and tested a demo (my card Nvidia GeForce 7300 Go) and I saw no increase in Frames Per Second with or without VBOs.

  • Limitation: When triangles intersect each other, triangle-sorting will not work correctly

My triangles do not intersect but share a common edge. Would that be ok?

Has anybody ever tried to render triangle strips instead of triangles to compare the performance triangle strips have to offer?

What about OpenGL Shading language or Nvidia Shading e.t.c.?

Hey did you read what I wrote on “depth peeling” ? That is for the shader stuff.

VBO are really great to stream geometry that changes every frame.
RTFM :
http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
tutorial :
http://www.ozone3d.net/tutorials/opengl_vbo.php

Sharing a common edge is ok with triangle sorting.

Triangle strips versus triangles : there can be some optimizations but it is quite hard to have that consistently. Search the forums here, it has already been heavily discussed.