Antialiasing Polygons with OpenGL

The computer screen displays graphics with atomic pixels. A pixel can only display one color. When a diagonal line is to be shown, it may become jaggy like a saw. Antialiasing is used to smooth out such roughness normally with a method called sampling.

The following code generates the following output:

When compared to a non-antialiased version, we can see the difference very easily:

When using antialiasing, you have to disable the depth test and specify a specific blend function to be used. In this example, back cull face is used for proper rendering.

#ifdef WIN32
#include <windows.h>
#endif
#include <glut.h>
void Initialize(void);
void Display(void);
void Reshape(int w, int h);
void Keyboard (unsigned char key, int x, int y);
void DrawSolidCube(void);
bool AntialiasToggle = false;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	Initialize();
	glutMainLoop();
	return 0;
}
void Initialize(void)
{
	int argc;
	char * argv[] = {"dummy",0};
	argc = 1;
	glutInit(&argc, (char **)&argv[0]);
	glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_ALPHA);
	glutInitWindowSize(300, 300);
	glutInitWindowPosition(-1, -1); // Let window to determine the startup position
	glutCreateWindow("An Antialiased Cube");
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Sets the background color - R, G, B,    and alpha
	glShadeModel(GL_SMOOTH); // One of GL_SMOOTH or GL_FLAT
	glBlendFunc (GL_SRC_ALPHA_SATURATE, GL_ONE);
	glColorMaterial(GL_FRONT,GL_AMBIENT); // Makes the coloring work for basic primitives
	glCullFace(GL_BACK);
	glEnable(GL_LIGHT0); // Enable a single light source
	glEnable(GL_LIGHTING);
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_CULL_FACE);
	glutDisplayFunc(Display); // Register Display() function
	glutReshapeFunc(Reshape); // Register Reshape() function
	glutKeyboardFunc(Keyboard); // Register Keyboard() function
}

void Reshape(int w, int h)
{
	glViewport(0,0,w,h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-1.0,1.0,-1.0,1.0,1.0,-1.0);
	gluPerspective(30,1,1,20);
	glTranslatef(0,0,-2.5);
}

void Keyboard (unsigned char key, int x, int y)
{
// Keyboard events can be intepreted here with a switch-case structure
	AntialiasToggle = !AntialiasToggle;
	glutPostRedisplay();
}
void Display(void)
{
	if (AntialiasToggle)
	{
		glClear(GL_COLOR_BUFFER_BIT);
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glEnable(GL_POLYGON_SMOOTH);
	}
	else
	{
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);
		glDisable(GL_POLYGON_SMOOTH);
	}
	DrawSolidCube();
	glutSwapBuffers(); // swap the display buffer to show the new results
}
void DrawSolidCube(void)
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPushMatrix();
	glColor4f(0,0,0.8f,1); // sets the color
	glRotatef(30,0.2,0.2,0); // rotate it for a 3D view
	glutSolidCube(0.8); // parameter is the length of each edge
	glPopMatrix();
}


: : go back : :