GLUTStereo
An examples showing how to set up and use stereo with
GLUT under Mac OS X v10.2.3 or later.
GLUT stereo support requires setting a stereo pixel format
then using glutGameMode to get a full screen stereo drawable.
Stereo in a window is not supported at this time. Below is
an example of this set up:
glutInit(&argc, (char **)argv);
// stereo display mode for glut
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STEREO);
glutGameModeString("1024x768:32@120"); // must now use full screen game mode
// enter gamemode to get stereo context
// (may get invalid drawable warnings in console,
// this is normal and will be fixed in the future)
glutEnterGameMode();
Once the stereo context is set up the application simply
renders into the left and right back buffer and allows the
driver to pick the correct front buffer to display.
To correct render stereo one should use the parallel axis asymmetric
frustum perspective projection method as shown in this example. A
good source of information on this technique is Paul Bourke's
web site at
A number of example surfaces used are by Roger Bagula with Paul Bourke
contributing some of the surface rendering evaluation code. More
renderings of these and other surfaces can be found at
.
Surface rendering is has the simple, yet very effective on Mac OS X v10.2 and later,
optimization of being compiled in display lists in this example, though the required
use of two sided lighting likely will slow the rendering down.
Also, shown in this example is a simple, yet rotationally correct,
track ball algorithm with was originally adapted from the NSGL Teapot
example and converted to standard C code.
Note: to view stereo one must use stereo glasses this example is
designed to support stereographics glasses which require a blue
sync line at the bottom of the screen (in lieu of hardware syncing).
The code below is an example of how to draw the blue sync line.
void DrawBlueLine(GLint window_width, GLint window_height)
{
GLint i;
unsigned long buffer;
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
for(i = 0; i < 6; i++) glDisable(GL_CLIP_PLANE0 + i);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_LINE_STIPPLE);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_SHARED_TEXTURE_PALETTE_EXT);
glDisable(GL_STENCIL_TEST);
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisable(GL_TEXTURE_RECTANGLE_EXT);
glDisable(GL_VERTEX_PROGRAM_ARB);
for(buffer = GL_BACK_LEFT; buffer <= GL_BACK_RIGHT; buffer++) {
GLint matrixMode;
GLint vp[4];
glDrawBuffer(buffer);
glGetIntegerv(GL_VIEWPORT, vp);
glViewport(0, 0, window_width, window_height);
glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glScalef(2.0f / window_width, -2.0f / window_height, 1.0f);
glTranslatef(-window_width / 2.0f, -window_height / 2.0f, 0.0f);
// draw sync lines
glColor3d(0.0f, 0.0f, 0.0f);
glBegin(GL_LINES); // Draw a background line
glVertex3f(0.0f, window_height - 0.5f, 0.0f);
glVertex3f(window_width, window_height - 0.5f, 0.0f);
glEnd();
glColor3d(0.0f, 0.0f, 1.0f);
glBegin(GL_LINES); // Draw a line of the correct length
// (the cross over is about 40% across the screen from the left)
glVertex3f(0.0f, window_height - 0.5f, 0.0f);
if(buffer == GL_BACK_LEFT)
glVertex3f(window_width * 0.30f, window_height - 0.5f, 0.0f);
else
glVertex3f(window_width * 0.80f, window_height - 0.5f, 0.0f);
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(matrixMode);
glViewport(vp[0], vp[1], vp[2], vp[3]);
}
glPopAttrib();
}
void DrawBlueLine_Simple(GLint window_width, GLint window_height)
{
unsigned long buffer;
for(buffer = GL_BACK_LEFT; buffer <= GL_BACK_RIGHT; buffer++) {
GLint matrixMode;
GLint vp[4];
glDrawBuffer(buffer);
glGetIntegerv(GL_VIEWPORT, vp);
glViewport(0, 0, window_width, window_height);
glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glScalef(2.0f / window_width, -2.0f / window_height, 1.0f);
glTranslatef(-window_width / 2.0f, -window_height / 2.0f, 0.0f);
// draw sync lines
glColor3d(0.0f, 0.0f, 0.0f);
glBegin(GL_LINES); // Draw a background line
glVertex3f(0.0f, window_height - 0.5f, 0.0f);
glVertex3f(window_width, window_height - 0.5f, 0.0f);
glEnd();
glColor3d(0.0f, 0.0f, 1.0f);
glBegin(GL_LINES); // Draw a line of the correct length (the cross over is about 40% across the screen from the left
glVertex3f(0.0f, window_height - 0.5f, 0.0f);
if(buffer == GL_BACK_LEFT)
glVertex3f(window_width * 0.30f, window_height - 0.5f, 0.0f);
else
glVertex3f(window_width * 0.80f, window_height - 0.5f, 0.0f);
glVertex3f(window_width, window_height - 0.5f, 0.0f);
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(matrixMode);
glViewport(vp[0], vp[1], vp[2], vp[3]);
}
}