I have always been a fan of nVidia graphics boards because of their support for 3D stereoscopic games. But the "consumer level" (non-Quadro) stereoscopic drivers only seem to work with games. I have always wondered how to create my own applications that can use the stereoscopic drivers on less-expensive gaming video boards. Now I have found a way.
The "consumer" stereoscopic driver from nVidia only works with "full screen" games. When I started experimenting with OpenGL, I assumed that using the call "glutFullScreen()" might be enough to get the stereoscopic drivers to kick in. But it is not.
The trick is to use the glutEnterGameMode() call. I did a lot of searching on the internet, and nowhere is it mentioned that you must call glutEnterGameMode() to get the nVidia "consumer level" stereoscopic drivers to work. That is why I am sharing this blog post.
My working system is on Windows XP. I am uncertain if this approach will work with Windows Vista/7. I am a bit concerned because nVidia seems to be selling a hardware stereoscopic product these days. I am worried that my custom stereoscopic theater, which uses a pair of polarized video projectors, won't work if I upgrade my Windows version.
Here is how you can do it too, on Windows XP:
- Ensure you have a supported nVidia graphics board in your computer. See the stereoscopic driver users' guide for more details.
- Get the stereoscopic driver from nVidia. The most recent version (91.31) released for Windows XP is from 2006. That is the one I am using. Consult this driver guide for more details.
- Install Python 2.6 and PyOpenGL version 3.0.0, so you can conveniently create OpenGL programs in python.
- Familiarize yourself with OpenGL programming. I got started by following the examples of the "red book", the OpenGL Programming Guide.
- Study my example program, below, to learn how to call glutGameModeString() and glutEnterGameMode().
Modify the display() method and the animate() method to show whatever you want!
#!/cygdrive/c/Python26/python
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import sys
def do_nothing(*args):
"""
Empty method for glutDisplayFunc during risky transition to game mode.
"""
pass
class HelloOpenGL(object):
"""
Creates a rotating wire frame cube using OpenGL.
Pressing the "f" key toggles full screen game mode.
This full screen mode works with nVidia stereoscopic
driver for Windows XP.
"""
def __init__(self):
self.animation_interval = 100 # milliseconds
self.rotation_angle = 0.0 # degrees, starting point
glutInit("Cube.py")
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glEnable(GL_DEPTH_TEST)
glutInitWindowSize(200, 200)
# Remember window id for when we return from game mode.
self.window_id = glutCreateWindow('Wire Cube')
self.initialize_gl_context()
# glutTimerFunc remains when GL context is replaced,
# so it does not go into self.initialize_gl_context()
glutTimerFunc(self.animation_interval, self.animate, 1)
glutMainLoop() # never returns
def clear_gl_callbacks(self):
"""
Set inoccuous callbacks during times when no valid context may be available.
"""
glutDisplayFunc(do_nothing)
glutMotionFunc(None)
glutKeyboardFunc(None)
def initialize_gl_context(self):
"""
When switching between full-screen and windowed modes,
initialize_gl_context() reinitializes state.
"""
glClearColor(0.5,0.5,0.5,0.0)
glutDisplayFunc(self.display)
# glutPassiveMotionFunc(self.mouse_motion)
glutMotionFunc(self.mouse_motion)
glutKeyboardFunc(self.keypress)
# establish the projection matrix (perspective)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
x,y,width,height = glGetDoublev(GL_VIEWPORT)
gluPerspective(
45, # field of view in degrees
width/float(height or 1), # aspect ratio
.25, # near clipping plane
200, # far clipping plane
)
def start_game_mode(self):
if glutGameModeGet(GLUT_GAME_MODE_ACTIVE):
return # already in game mode
glutGameModeString("800x600:16@60")
if glutGameModeGet(GLUT_GAME_MODE_POSSIBLE):
self.clear_gl_callbacks()
glutEnterGameMode()
self.initialize_gl_context()
def start_windowed_mode(self):
if glutGameModeGet(GLUT_GAME_MODE_ACTIVE):
self.clear_gl_callbacks()
glutLeaveGameMode()
# Remember the window we created at start up?
glutSetWindow(self.window_id)
self.initialize_gl_context()
def display(self):
"""
"display()" method is called every time OpenGL updates the display.
"""
# Erase the old image
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# Modelview must be set before geometry is sent
# or else crash when entering stereoscopic mode.
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(
0,-0.5,5, # eyepoint
0,0,0, # center-of-view
0,1,0, # up-vector
)
# Rotate about the origin as animation progresses
glRotate(self.rotation_angle, 0, 1, 0)
glPushMatrix()
try:
# Draw the cube
glutWireCube(2.0)
finally:
glPopMatrix()
glutSwapBuffers()
def mouse_motion(self, x, y):
pass
def keypress(self, key, x, y):
if key == '\033':
# Escape key leaves full screen mode
if glutGameModeGet(GLUT_GAME_MODE_ACTIVE):
self.start_windowed_mode()
elif key == "f":
# "f" key toggle full screen and windowed mode.
if glutGameModeGet(GLUT_GAME_MODE_ACTIVE):
self.start_windowed_mode()
else:
self.start_game_mode()
def animate(self, value):
"""
Periodically change the rotation angle for the cube animation.
This animate method() is called as a glutTimerFunc().
"""
self.rotation_angle += 1.0
while self.rotation_angle > 360.0:
self.rotation_angle -= 360.0
glutPostRedisplay()
# Be sure to come back for more
glutTimerFunc(self.animation_interval, self.animate, value+1)
# Run the HelloOpenGL application when this script is run directly.
if (__name__ == '__main__'):
HelloOpenGL()
2 comments:
Hi BIOSPUD, in your post you mentioned, your method may not work for win7. Does it work now? I may consider to buy an Quadro instead of my GeForce 560Ti if your method is not supported by the new driver. BTW, I even don't know how to get 3D vision with Quadro by OpenGL?!
Thanks for you advice.
Best regard
Douglas
Douglas -- Sadly the method in this post has not worked in a long time. The marketing dorks at nvidia have made it impossible to get stereo 3d on non-quadro video cards with opengl and 3d vision. Hopefully ATI will come up with something usable and eat their lunch. I know that you can get opengl stereo on nvidia quadro cards, but it is tedious. Google GL_BACK_LEFT for more information.
Post a Comment