Transparency in OpenGL

These are some notes I had typed up earlier in the semester but didn't get around to covering in lab. Its just a very brief tutorial on using alpha blending in OpenGL.

To illustrate the process, let's just draw two triangles at different depths in the DrawGL() function.

 glBegin(GL_TRIANGLES);
 	// Front triangle - red
 	glColor3f(1, 0, 0);
 	glVertex3f(-0.5,-0.5,0);
 	glVertex3f(0.5,-0.5,0);
 	glVertex3f(0,0.5,0);

 	// Back triangle - blue
  	glColor3f(0, 0, 1);
 	glVertex3f(-0.25,-0.25,-0.5);
 	glVertex3f(0.75,-0.25,-0.5);
 	glVertex3f(0.25,0.75,-0.5);
 glEnd();

You should see something like this.


You're used to only specifying RGB values for color via glColor3f(). To specify a transparency (alpha) value, you have to use glColor4f(r, g, b, a), where the last value is 0 for completely transparent and 1 for completely opaque (default).

For this example, now change the transparency of the triangles so that the front triangle is semi-transparent, i.e. alpha value of 0.5.

 // Front triangle - semi-transparent
 glColor4f(1, 0, 0, 0.5);
 ...
 // Back triangle - opaque
 glColor4f(0, 0, 1, 1);

If you compile this code, you should find that - whoops! - it looks exactly the same as before. This is because we have to enable transparency/blending.

 // In InitGL(), for example
 glEnable(GL_BLEND); // glDisable(GL_BLEND) to turn off
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Once you do this, you should see something like this.


It still doesn't work correctly. Why? Because we're drawing the transparent triangle before the farther opaque triangle -- when it is rasterized, OpenGL doesn't know that there will be blue pixels behind it later, it only knows about the white background.

To fix it, have to draw the further one first. In general, you should first draw opaque objects, then draw semi-transparent objects from back to front in order to have correct results.

If you change the render order so that the back triangle is drawn first:

 // Back triangle - opaque
 ...
 // Front triangle - semi-transparent
 ...

you should see a properly blended result.