Stereoscopic 3D example

Does anyone have sample code demonstrating a functional stereoscopic 3D display?

This is what I’ve tried:

from psychopy import visual, core

win = visual.Window([2560,1440], fullscr=True, monitor="testMonitor", units="deg", stereo=True)

hello = visual.TextStim(win=win, text='Hello')
world = visual.TextStim(win=win, text='World')

while True:
	win.setBuffer('left')
	hello.draw()

	win.setBuffer('right')
	world.draw()

	win.flip()

But it doesn’t work. No combination of buffer clearing or flipping between left/right renders generates 3D. As far as I can tell, the display doesn’t actually switch to stereoscopic mode, since the 3D Vision emitter on my PC doesn’t come on.

FWIW, this sample does work properly:

import sys

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

import time

def display():
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT)

	glDrawBuffer(GL_BACK_LEFT)
	glClearColor(1.0, 0.0, 0.0, 1.0) # red
	glClear(GL_COLOR_BUFFER_BIT)

	glDrawBuffer(GL_BACK_RIGHT)
	glClearColor(0.0, 0.0, 1.0, 1.0) # blue
	glClear(GL_COLOR_BUFFER_BIT)

	glutSwapBuffers()

def idle():
	glutPostRedisplay()

if __name__ == '__main__':
	glutInit(len(sys.argv), sys.argv)
	glutInitDisplayMode(GLUT_RGB | GLUT_STEREO | GLUT_DOUBLE)

	glutGameModeString("2560x1440:32@120")

	glutEnterGameMode()
	glutDisplayFunc(display)
	glutIdleFunc(idle)

	glutMainLoop()

Am I missing something simple? Does anyone have a working stereoscopic demo they can share?

I should’ve specified that I’m running Windows 10

Ok, it looks like I found the cause, but I don’t know enough about OpenGL extensions to know if my patch is the appropriate fix.

The pyglet backend checks for the GL_STEREO extension. My graphics card (NVIDIA GeForce GTX 1080 Ti with Game Ready Driver 397.93) does not report that this extension is supported. However, running it in stereo mode (by removing the win.stereo = False line), and it works as expected.

I did notice a supported extension called GL_NV_stereo_view_rendering, which is obviously vendor-specific, but I didn’t notice anything else that seemed to match. So I propose changing the check to this:

if win.stereo and not (GL.gl_info.have_extension('GL_STEREO') or GL.gl_info.have_extension('GL_NV_stereo_view_rendering')):

I’m happy to make a pull request on Github, but I’m not confident that this is the best solution.

I have come across something similar (see here). The extension check you mentioned sounds like a good idea.

Hi all, my solution:

  1. Put your 120 fps gaming screen into primary GPU slot (that one where images are shown when computer starting up, and which you are using when opening BIOS setup)

  2. Go to NVidia control panel

2.1 Setup Multiple Displays, make you 120 fps display Primary

2.2 Change Resolution, set your 120fps display to 120Hz refresh rate (144Hz does not worked for me)

2.3 Manage 3D Settings, Stereo - Enable On , other settings you can leave as is.

  1. go to file(you can use search tool to find it)

pygletbackend.py

in my case full path is C:\Users<username>\Anaconda3\envs\psychopy\Lib\site-packages\psychopy\visual\backends

  1. comment out all lines related to disabling stereo in case if GL_STEREO == False
#if win.stereo and not (GL.gl_info.have_extension('GL_STEREO') or GL.gl_info.have_extension('GL_NV_stereo_view_rendering')):
        #    logging.warning(
        #        'A stereo window was requested but the graphics '
        #        'card does not appear to support GL_STEREO')
        #    win.stereo = False

My setup:
Psychopy v2020.1.3
OS: Windows 10 x64 Pro for Workstations
CPU: Intel Xeon Silver 4110 2.10GHz
RAM: 64Gb
GPU: NVidia Quadro P4000
GPU Driver: 451.48 Quadro Desktop/Quadro Notebook Driver
Dispaly 0 (primary screen): Asus VG248QE 24" Full HD 1920x1080 144Hz 1ms HDMI Gaming Monitor
Display 1 (secondary screen): DELL P2719H
Shutter Glasses: NVidia 3D Vision Kit 2

Sample python code(modified version from comment above):

from psychopy import visual, core
win = visual.Window(
    [400,400],
    double_buffer=True,
    fullscr=False, 
    monitor="ASUS_144HZ", 
    screen=0,
    units="deg", 
    stereo=True,
    monitorFramePeriod=1000/120 # rate
    )
hello = visual.TextStim(win=win, text='Hello')
world = visual.TextStim(win=win, text='World')

while True:
    win.setBuffer('left')
    hello.draw()
    win.setBuffer('right')
    world.draw()
    win.flip()

Notes:
Do not worry that Streoscopic Setup is not available in NVidia Control Panel, it is included in driver thanks to backward compatibility, just turn Stereo as described abode.

I did not managed to understand what is the proper flag of GL signaling status of stereo, like GL_STEREO, that is why I commenting out entire code section preventing me from running stereo

For some reason windows and GPU don’t like the idea that fast screen connected to non-primary slot, so it took me a while to narrow down the issue and just swap the screens connectors.

Shutter glasses can run from USB with battery disconnected, but they need the IR filter(small dark glossy plastic thingy between eyes) to be in place (I have completely disassembled the glasses for my purpose)

Resolving all of these small issues took me several weeks, so I hope this might help someone here :slightly_smiling_face:

Best wishes,
Alex