Simple Transparency

Most special effects in OpenGL rely on some type of blending. Blending is used to combine the color of a given pixel that is about to be drawn with the pixel that is already on the screen. How the colors are combined is based on the alpha value of the colors, and/or the blending function that is being used. Alpha is a 4th color component usually specified at the end. In the past you have used GL_RGB to specify color with 3 components. GL_RGBA can be used to specify alpha as well. In addition, we can use glColor4f() instead of glColor3f().

Most people think of Alpha as how opaque a material is. An alpha value of 0.0 would mean that the material is completely transparent. A value of 1.0 would be totally opaque.

The Blending Equation

If you are uncomfortable with math, and just want to see how to do transparency, skip this section. If you want to understand how blending works, this section is for you.

(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)

OpenGL will calculate the result of blending two pixels based on the above equation. The s and r subscripts specify the source and destination pixels. The S and D components are the blend factors. These values indicate how you would like to blend the pixels. The most common values for S and D are (As, As, As, As) (AKA source alpha) for S and (1, 1, 1, 1) - (As, As, As, As) (AKA one minus src alpha) for D. This will yield a blending equation that looks like this:

(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))

This equation will yield transparent/translucent style effects.

Blending in OpenGL

In GL, to set up blending we first need to enable it just like everything else. Then we set the equation, and turn off depth buffer writing when drawing transparent objects, since we still want objects behind the translucent shapes to be drawn.

We'll be using the code from lesson seven. We start off by adding two new variables to the top of the code. I'll rewrite the entire section of code for clarity.
#include <windows.h>		// Header File For Windows
#include <gl\gl.h>		// Header File For The OpenGL32 Library
#include <gl\glu.h>		// Header File For The GLu32 Library
#include <gl\glaux.h>		// Header File For The GLaux Library

static HGLRC hRC;		// Permanent Rendering Context
static HDC hDC;			// Private GDI Device Context

BOOL	keys[256];		// Array Used For The Keyboard Routine
BOOL	light;			// Lighting ON/OFF
BOOL	lp;			// L Pressed?
BOOL	fp;			// F Pressed?
BOOL    blend;			// Blending OFF/ON? ( NEW )
BOOL	bp;			// B Pressed? ( NEW )

GLfloat	xrot;			// X Rotation
GLfloat	yrot;			// Y Rotation
GLfloat xspeed;			// X Rotation Speed
GLfloat yspeed;			// Y Rotation Speed

GLfloat	z=-5.0f;		// Depth Into The Screen

GLfloat LightAmbient[]=  { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]=	 { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };

GLuint	filter;			// Which Filter To Use
GLuint	texture[3];		// Storage for 3 textures

Add the following two lines somewhere in the InitGL() section of code. What this line does is sets the drawing brightness of the object to full brightness with 50% alpha. This means when blending is enabled, the object will be 50% transparent. The second line sets the type of blending we're going to use.
	glColor4f(1.0f,1.0f,1.0f,0.5f);		// Full Brightness, 50% Alpha ( NEW )
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);	// Blending Function For Translucency Based On Source Alpha Value

Look for the following section of code, it can be found at the very bottom of lesson seven.
if (keys[VK_LEFT])
{
	yspeed-=0.01f;
}

Right under the above code, we want to add the following lines. The lines below watch to see if the 'B' key has been pressed. If it has been pressed, the computer checks to see if blending is off or on. If blending is on, the computer turns it off. If blending was off, the computer will turn it on.
	if (keys['B'] && !bp)
	{
		bp=TRUE;
		blend = !blend;
		if(blend)
		{
			glEnable(GL_BLEND);					// Turn Blending On
			glDisable(GL_DEPTH_TEST);				// Turn Depth Testing Off
		}
		else
		{
			glDisable(GL_BLEND);					// Turn Blending Off
			glEnable(GL_DEPTH_TEST);				// Turn Depth Testing On
		}
	}
	if (!keys['B'])
	{
		bp=FALSE;
	}

But how can we specify the color if we are using a texture map? Simple, in modulated texture mode, each pixel that is texture mapped is multiplied by the current color. So, if the color to be drawn is (0.5, 0.6, 0.4), we multiply it times the color and we get (0.5, 0.6, 0.4, 0.2) (alpha is assumed to be 1.0 if not specified).

Thats it! Blending is actually quite simple to do in OpenGL.

Note (11/13/99)

I ( NeHe ) have modified the blending code so the output of the object looks more like it should. Using Alpha values for the source and destination to do the blending will cause artifacting. Causing back faces to appear darker, along with side faces. Basically the object will look very screwy. The way I do blending may not be the best way, but it works, and the object appears to look like it should when lighting is enabled. Thanks to Tom for the initial code, the way he was blending was the proper way to blend with alpha values, but didn't look as attractive as people expected :)

The code was modified once again to address problems that some video cards had with glDepthMask(). It seems this command would not effectively enable and disable depth buffer testing on some cards, so I've changed back to the old fashioned glEnable and Disable of Depth Testing.

Alpha from texture map.

The alpha value that is used for transparency can be read from a texture map just like color, to do this, you will need to get alpha into the image you want to load, and then use GL_RGBA for the color format in calls to glTexImage2D().

Questions?

If you have any questions, feel free to contact me at stanis@cs.wisc.edu.

Tom Stanis

* DOWNLOAD Visual C++ Code For This Lesson.
* DOWNLOAD Visual Fortran Code For This Lesson. ( Conversion by Jean-Philippe Perois )
* DOWNLOAD Delphi Code For This Lesson. ( Conversion by Marc Aarts )
* DOWNLOAD Linux Code For This Lesson. ( Conversion by Richard Campbell )
* DOWNLOAD Irix Code For This Lesson. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Solaris Code For This Lesson. ( Conversion by Lakmal Gunasekara )
* DOWNLOAD Mac OS Code For This Lesson. ( Conversion by Anthony Parker )
* DOWNLOAD Power Basic Code For This Lesson. ( Conversion by Angus Law )
* DOWNLOAD BeOS Code For This Lesson. ( Conversion by Chris Herborth )
* DOWNLOAD Java Code For This Lesson. ( Conversion by Darren Hodges )