Skip to main content
Skip table of contents

3D Stimulus Presentation with the VIEWPixx /3D

This guide will cover different strategies for using the VIEWPixx /3D and 3DPixx active shutter glasses as a stereoscopic display. Code examples are provided throughout.

_MG_0284.jpg

A participant wearing 3D active shutter glasses

A single VIEWPixx /3D can present 3D stimuli up to 120 Hz (60 Hz/eye). Two VIEWPixx /3Ds in a traditional haploscope method (without shutter glasses), support 120 Hz/eye.

There are several methods of presenting 3D stimuli on the VIEWPixx /3D, which we will discuss below. The first three methods use temporal interleaving of left/right images, synchronized with the 3D shutter glasses, on a single VIEWPixx /3D. The final two methods use two VIEWPixx /3Ds in a traditional haploscope-style installation to combine spatially disparate images on the left and right eyes simultaneously.

General instructions for preparing for 3D stimulus presentation

There are several recommendations for initializing the VIEWPixx /3D for stereoscopic presentation, regardless of the specific presentation strategy used. They are:

  • Enable the scanning backlight. The scanning backlight on your VIEWPixx /3D optimizes the display for crisp frame transitions, minimizing ghosting and crosstalk between video frames. This is the ideal mode for 3D presentation. For more details on the scanning backlight, see this section of our guide to the VIEWPixx.

  • Allow a warm-up period of >30 minutes to allow the VIEWPixx /3D to come to a stable temperature. If the screen is not fully warmed up you may see more ghosting in 3D stimuli.

  • Verify the resolution in your display settings. The display settings for each method are shown below. Ensure your operating system display settings use the recommended resolution, and scaling is set to 100%.

Method

Resolution

Refresh rate(s)

Frame-sequential stereo

1920 x 1080

120 Hz
100 Hz

Stereo blue lines

1920 x 1080

120 Hz

Top-bottom mode (see instructions below)

1920 x 2322

60 Hz

Haploscope modes

1920 x 1080

120 Hz

  • Restart your experiment software whenever you change the screen resolution. Some software, notably MATLAB, only checks your screen resolution on startup. You need to restart the program to detect a new screen resolution.

  • Use full-screen windows. Borders or smaller stimulus presentation windows may derail synchronization and produce strange results.

  • Avoid maximum and minimum pixel values (e.g., full black, full white). Transitions to these values can show increased crosstalk compared to other values (e.g., 0.9, 0.1).

  • Ensure video mode is set to the default ('C24'). Not necessary for M16 mode.

  • Use LCD3D60Hz mode (older models of VIEWPixx /3D only). For VIEWPixx /3D units sold before 2019, we recommend enabling LCD3D60Hz for improved display output. Examples are shown below. This feature is not required for newer units.

  • Use the correct VESA phase and waveform for your brand of shutter glasses. Not required for haploscope modes. These settings ensure the correct synchronization signal is passed to the glasses. The settings should be implemented at the beginning of your experiment script (see code examples below). See the following details for NVIDIA and Volfoni glasses. For other glasses' manufacturers, we recommend contacting our support team for assistance.

Manufacturer

VESA Waveform

VESA Phase

NVIDIA

‘NVIDIA’
2 (in MATLAB)

100

Volfoni

‘VOLFONI'
5 (in MATLAB)

100

  • (Volfoni users) Use the Volfoni loader to adjust the glasses' shutter speed to optimize for brighter stimuli or minimized crosstalk. This optional step can be used to fine-tune the performance of the Volfoni version of the 3DPixx. For more details on the loader, and to download the application, see http://volfoni.com/en/support-2/.

Temporally interleaved modes

Temporally interleaved 3D modes present left and right eye images sequentially on a single display. The left and right eye images are paired with a signal emitted by the IR (or RF) emitter driving the active 3D shutter glasses.

The signal indicates to the 3D glasses which shutter should be open on a given frame. Thus the shutter will open for video frames assigned to the corresponding eye, and close for other frames, creating the stereoscopic effect.

In temporally-interleaved 3D, the 3D signal must remain synchronized with the display. If the signal becomes de-synchronized at any point, the wrong image will be presented to the wrong eye.

Time (4).png

Temporally-interleaved 3D

There are three general methods for temporally interleaved stereo using the VIEWPixx /3D: Frame-sequential stereo, Stereo Blue Lines and Top-Bottom mode.

Frame-sequential stereo (not recommended)

In frame-sequential stereo, images are interleaved temporally. Even and odd video frames are presented to the left and right eye, respectively. Image alternation is controlled manually (e.g., drawing left and right eye images and flipping them one after another) or via dedicated stereo draw buffers alternately sampled during stimulus presentation.

Time (4).png

Frame-sequential stereo

This method is highly vulnerable to frame dropping and 3D desynchronization. We do not recommend this method.

Stereo Blue Lines

Stereo Blue Lines explicitly encode each video frame to target the correct eye. This preserves stereo synchronization even if your system is dropping frames.

Stereo Blue Line is easy to implement:

  1. Organize your stimuli as you would for frame-sequential stereo.

  2. To assign a frame to the right eye: Set the bottom row of pixels in the frame to an intensity greater than mid-grey [128, 128, 128]

  3. To assign a frame to the left eye: Set the bottom row of pixels in the frame to an intensity less than mid-grey [128, 128, 128]

Drawings (7).png

Blue Lines added to the bottom of each image to ensure they are shown to the correct eye. The lines are exaggerated for visibility.

Some software will automate Blue Line generation for you. We generally recommend drawing the line yourself. It is simple and ensures you are formatting your video frames correctly.

MATLAB Example
MATLAB
function helloWorldVPx3D()
%A simple demonstration of Stereo Blue Lines. 
%Draws "hello" and "world" to the left and right eyes.
%Helper functions initialize the VIEWPixx /3D and draw the blue lines on
%the correct frame.

% Initialize
initializeVIEWPixx3D();

% Initialize Psychtoolbox window
screenNumber = max(Screen('Screens'));
[windowPtr, rect] = PsychImaging('OpenWindow', screenNumber, 0);

% Initialize stimuli
helloText = 'Hello';
worldText = 'World';

% Start loop drawing the message
while true
    DrawFormattedText(windowPtr, helloText, 'center', 'center', 255);
    drawBlueLine(windowPtr, rect, 1);
    Screen('Flip', windowPtr);

    DrawFormattedText(windowPtr, worldText, 'center', 'center', 255);
    drawBlueLine(windowPtr, rect, 0);
    Screen('Flip', windowPtr);
    
    %Check for escape
    [~, ~, keyCode] = KbCheck;
    if keyCode(KbName('Escape'))
        break;
    end
end

% Shut down
sca;
Datapixx('Close');
end

%%% Some helper functions 

function initializeVIEWPixx3D()
% All VPixx hardware commands to set the right mode 
Datapixx('Open');
Datapixx('SetVideoMode', 0); %C24
Datapixx('EnableVideoStereoBlueline');
Datapixx('SetVideoStereoVesaWaveform', 2); %NVIDIA
Datapixx('SetVideoStereoVesaPhase', 100);
Datapixx('RegWr');

%For older models of VIEWPixx /3D, uncomment the following
%Datapixx('EnableVideoLcd3D60Hz');
%Datapixx('RegWr');
end

function drawBlueLine(windowPtr, rect, frame)
% Helper function to draw lines on the appropriate image
% if Frame = 0 draw right eye blueline
% if Frame = 1, draw left eye no blueline
% Call immediately before flip
if frame == 0
    frameColor = [255, 255, 255];
else
    frameColor = [0, 0, 0];
end
rowStart = [rect(1), rect(4)-1];
rowEnd = [rect(3), rect(4)-1];
Screen('DrawLine', windowPtr, frameColor, rowStart(1), rowStart(2), rowEnd(1), rowEnd(2),2);
end
Python Example
PY
#A simple demonstration of Stereo Blue Lines. 
#Draws "hello" and "world" to the left and right eyes.
#Helper functions initialize the VIEWPixx /3D and draw the blue lines on
#the correct frame.

from psychopy import core, visual
from psychopy.hardware import keyboard
from pypixxlib.viewpixx import VIEWPixx3D
from pypixxlib._libdpx import DPxEnableVidLcd3D60Hz, DPxSetVidVesaPhase


def initializeVPx3D():
    #All VPixx hardware commands to set the right mode for the VIEWPixx 3D
    my_device = VIEWPixx3D()
    my_device.setVideoMode('C24')
    my_device.setVideoVesaBlueline(True)
    my_device.setVesaWaveform('NVIDIA')
    DPxSetVidVesaPhase(100)
    my_device.writeRegisterCache()
    
    #For older models of VIEWPixx /3D, uncomment the following
    #DPxEnableVidLcd3D60Hz()
    #my_device.writeRegisterCache()    
    return my_device
    

def drawBlueLine(win, frame=0):
    #if Frame = 0, draw right eye blueline
    #if Frame = 1 draw left eye no blueline
    #Call immediately before flip
    if frame==0: 
        frameColor = [255,255,255]
    else:
        frameColor = [0,0,0]
            
    rowStart= [-win.size[0]/2, -win.size[1]/2]
    rowEnd =[win.size[0]/2, -win.size[1]/2]
        
    line = visual.Line(
            win=win,
            units = 'pix',
            start=rowStart,
            end=rowEnd,
            interpolate = False,
            colorSpace = 'rgb255',
            lineColor = frameColor)
    line.draw()
    
    
#Begin Experiment
kb = keyboard.Keyboard()
VPx = initializeVPx3D()
win = visual.Window(
        screen = 1,
        monitor =None, 
        fullscr=True,
        color='black',
        units = "pix"
        )

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

while True:

    hello.draw()
    drawBlueLine(win, frame=1)
    win.flip()

    world.draw()
    drawBlueLine(win, frame=0)
    win.flip()

    keys = kb.getKeys(keyList=['escape'])
    if keys:
        break
    
win.close()
core.quit()

‘Blue line’ is the name for historical reasons, but it’s a misnomer. The colour of the line is not important. As long as your pixel values are brighter than mid-grey ([128, 128, 128] in RGB255) it will work as intended.

PsychoPy users: Blue Lines must be drawn with interpolation turned off. Otherwise, the pixel values will blend with the background colour and may not trigger proper polarization.

Top-Bottom Mode

Top-Bottom mode requires a special version of vputil to run. You can download this custom version from: https://www.vpixx.com/developer/vputil3d.exe. This version of vputil may throw a server mismatch error. This can be safely ignored.

In Top-Bottom mode, left and right eye images are stacked on top of one another in a single double-height video frame, with a blank bar between them. This composite frame passed to our hardware at 60 Hz. The hardware deconstructs and presents the left and right eye images sequentially (1920 x 1080 @ 120 Hz).

Time (12).png

Top-bottom mode for the VIEWPixx /3D

This mode was originally designed for use with 3D stimuli designed in Unity and Unreal game engines. However, it may be useful for other high-level stimulus-generation software such as PsychoPy Builder. Because this mode receives left and right eye images on the same video frame from the GPU, there is no risk of de-synchronization of 3D. Occasionally frame drops are not likely to be visible.

There are two steps to implementing Top-Bottom Mode on the VIEWPixx /3D. First, you must configure the monitor to accept the 1920 x 2322 resolution using our vputil command-line utility and your display settings. Then you need to pass a few commands to the hardware via API to ensure you are operating in 3D mode.

Configuring your display for Top-Bottom Mode

First, change the display resolution in our command-line utility, vputil.

  1. Connect the VIEWPixx /3D to the stimulus computer via USB and video cables. Power on the monitor.

  2. In vputil, enter the command edid and hit enter.

  3. Several resolution and refresh rate options will be presented to you. Select [1] 1920 x 2322 @ 60 Hz hit enter. Repeat this step for the second edid slot. Answer “N” to the NVIDIA question.

    vputil.png

    Setting custom resolution in vputil for Top-Bottom mode

  4. Restart your VIEWPixx /3D.

  5. Restart your experiment software if necessary.

Note you must repeat these steps with a resolution of [2] 1920 x 1080 @ 120 Hz to return to standard operating mode.

Once you have configured your display output, you can begin programming your experiment.

MATLAB example
MATLAB
function VPx3D_TopBottom()
%This demo draws a red and green square in the left and right eye views,
%respectively. Helper functions initialize and draw the blanking interval. 

% Initialize
initializeVIEWPixx3D();

% Initialize Psychtoolbox window
screenNumber = max(Screen('Screens'));
[windowPtr, ~] = PsychImaging('OpenWindow', screenNumber, 0);

% Initialize stimuli - arbitrarily picked a 120 pixel square in center of
% display. Left eye sees red (top image) and right eye sees green (bottom
% image)
leftEyeCenter = [1920/2,1080/2];
leftEyeBox = [leftEyeCenter(1)-60, leftEyeCenter(2)-60,leftEyeCenter(1)+60, leftEyeCenter(2)+60];
leftEyeCol = [255, 0, 0];

% Right eye is shifted down by 1080 plus blanking interval
rightEyeCenter = [1920/2,(1080+162)+1080/2];
rightEyeBox = [rightEyeCenter(1)-60, rightEyeCenter(2)-60, rightEyeCenter(1)+60, rightEyeCenter(2)+60];
rightEyeCol = [0, 255, 0];

% Start presentation loop 
while true
    Screen('FillRect', windowPtr, leftEyeCol, leftEyeBox);
    Screen('FillRect', windowPtr, rightEyeCol, rightEyeBox);
    drawBlankingInterval(windowPtr);
    Screen('Flip', windowPtr);
    
    %Check for escape
    [~, ~, keyCode] = KbCheck;
    if keyCode(KbName('Escape'))
        break;
    end
end

% Close the Psychtoolbox window
sca;
Datapixx('Close');
end

%%% Some helper functions 

function initializeVIEWPixx3D()
% All VPixx hardware commands to set the right mode 
Datapixx('Open');
Datapixx('SetVideoMode', 0); %C24
Datapixx('EnableVideoStereoBlueline');
Datapixx('SetVideoStereoVesaWaveform', 2); %NVIDIA
Datapixx('SetVideoStereoVesaPhase', 100);
Datapixx('RegWr');

%For older models of VIEWPixx /3D, uncomment the following
%Datapixx('EnableVideoLcd3D60Hz');
%Datapixx('RegWr');
end

function drawBlankingInterval(windowPtr)
% Helper function ensures blanking interval between top and bottom images 
% is in fact blank on each frame
rectCoords = [0, 1080, 1920, 1242];
rectColor = [0 0 0];
Screen('FillRect', windowPtr, rectColor, rectCoords);
end
PsychoPy example
PY
#This demo draws a red and green square in the left and right eye views,
#respectively. Helper functions initialize and draw the blanking interval. 

from psychopy import core, visual
from psychopy.hardware import keyboard
from pypixxlib.viewpixx import VIEWPixx3D
from pypixxlib._libdpx import DPxEnableVidLcd3D60Hz, DPxSetVidVesaPhase

def initializeVPx3D():
    #All VPixx hardware commands to set the right mode for the VIEWPixx 3D
    my_device = VIEWPixx3D()
    my_device.setVideoMode('C24')
    my_device.setVideoVesaBlueline(True)
    my_device.setVesaWaveform('NVIDIA')
    DPxSetVidVesaPhase(100)
    my_device.writeRegisterCache()
    
    #For older models of VIEWPixx /3D, uncomment the following
    #DPxEnableVidLcd3D60Hz()
    #my_device.writeRegisterCache()    
    return my_device

def drawBlankingInterval(win):
    # Helper function to ensure blanking interval between top and bottom images is blank
    rect_coords = [0, 1080, 1920, 1242]
    blank_rect = visual.Rect(
        win=win,
        width=rect_coords[2],
        height=rect_coords[3] - rect_coords[1],
        pos=[rect_coords[2] / 2, (rect_coords[1] + rect_coords[3]) / 2],
        fillColor='black',
        lineColor='black'
    )
    blank_rect.draw()

   
#Begin Experiment
#Note that we set the origin to top left corner (in PsychoPy, down/left is negative). 
#This is helpful for drawing in pixel space. If you prefer to use normalized units, modify the
#viewPos argument below.
kb = keyboard.Keyboard()
VPx = initializeVPx3D()
win = visual.Window(
        screen = 1,
        viewPos=[-960, 2322/2],
        monitor =None, 
        fullscr=True,
        color='black',
        units = "pix"
        )

# Initialize stimuli - arbitrarily picked a 120 pixel square in center of display
left_eye_center = [1920 / 2, -1080 / 2]
# Center of right eye image is shifted down by 1080 plus blanking interval
right_eye_center = [1920 / 2, -1080 - 162 - 1080 / 2]

# Create squares for both eyes
left_eye_square = visual.Rect(
    win=win,
    width=120, height=120,
    pos=left_eye_center,
    fillColor='red',
    lineColor='red'
)

right_eye_square = visual.Rect(
    win=win,
    width=120, height=120,
    pos=right_eye_center,
    fillColor='green',
    lineColor='green'
)

# Main loop to draw the squares
while True:
    left_eye_square.draw()
    right_eye_square.draw()
    drawBlankingInterval(win)
    win.flip()
    
    # Check for escape key press
    keys = kb.getKeys()
    if 'escape' in keys:
        break

# Close the PsychoPy window
win.close()
core.quit()
PsychoPy Builder example

Implementing Top-Bottom mode in PsychoPy Builder is straightforward. We recommend creating a new monitor in the monitor center specifically for Top-Bottom mode, to ensure the proper resolution is used. Open the Monitor center, and create a new display with the correct 1920 x 2322 resolution:

builder.png

Create a new monitor in PsychoPy Builder

You can also insert a custom code block at the beginning of the experiment, to initialize the VIEWPixx /3D settings:

image-20240606-195255.png

Example code block for initializing the VIEWPixx. The same code can be found on lines 6-7 and 11-20 of the previous code-based example, if you would like to copy it.

Next, when creating your stimuli, draw images and text as a single double-height image. Images and text directed at the left eye should be placed in the top 1080 pixels of the image, and those directed at the right eye should be placed in the bottom 1080 pixels.

Don’t forget that there is a 162-pixel high blanking interval in the middle of the image. If you are using normalized spatial units, the center of the top (left eye) image is [0, -0.47] and the bottom (right eye) is [0, 0.47], etc.

Unity Example

Coming soon!

Haploscope modes

A haploscope is an optical device that uses a combination of lenses or mirrors to present the contents of two different screens to the left and right eyes simultaneously. While haploscopes can be challenging to align and synchronize, they are a reliable method of presenting stereoscopic images at high speeds (>60 Hz) with absolutely 0 crosstalk.

Drawings.png

A simple Wheatstone haploscope. The two displays are reflected onto 45-degree mirrors positioned in front of the left and right eyes.

Some researchers elect to use a pair of VIEWPixx /3Ds as the displays in a haploscope in order to take advantage of their excellent timing properties.

It is possible to drive the two displays in the haploscope from the graphics card as unique screens, provided the graphics card is powerful and no frame dropping occurs. However, if perfect synchronization is needed, VPixx has several additional solutions to support haploscopes comprised of our devices, namely Mirrored Greyscale Mode and M16 Mode.

Mirrored Greyscale Mode

Currently, this mode is only available for MATLAB users.

In this case, each display receives the same video but only shows the content of a specific colour channel (in greyscale). This allows for completely synchronized video output with unique content, driven by separate 8-bit colour channels.

The user can specify which colour channel drives which display. For example, the following schematic shows the left eye display driven by the red channel and the right eye by the green channel.

image-20240906-145730.png

Example mirrored greyscale stimuli and configuration.

To enable this mode, you must assign unique names to your two VIEWPixx /3Ds to be able to configure them individually in software commands. Next, you must daisy-chain the video output from one VIEWPixx /3D to another to ensure both displays use the same video signal. The steps are outlined in detail below:

  1. Connect the first VIEWPixx /3D to your PC via USB cable

  2. Open the vputil command line utility and assign the display a unique name via the dn command. For example, ‘dn LEFT’

  3. Disconnect the VIEWPixx /3D

  4. Repeat steps 1-2 for the second VIEWPixx /3D

  5. Re-connect the first VIEWPixx /3D. You should now have both monitors connected to your PC via USB.

  6. Connect video input of one VIEWPixx /3D to your PC graphics card. It does not matter which one.

  7. Connect the video output from this VIEWPixx /3D to the video input on the second VIEWPixx /3D monitor (see image above).

  8. Open MATLAB and configure the displays

MATLAB Example
MATLAB
%To enable mirrored greyscale mode
Datapixx('Open');
Datapixx('SelectDevice', 2, ‘LEFT’); % The 2 is for VIEWPixx
Datapixx('SetVideoGreyscaleMode', 1); %Red channel drives output
Datapixx('SelectDevice', 2, 'RIGHT');
Datapixx('SetVideoGreyscaleMode', 2); %Green channel drives the output
Datapixx('SelectDevice', -1); % Return to automatic device selection
Datapixx('RegWr');

%Experiment goes here. Draw all stimuli on the same display, with red channel
%for the left eye and green for the right eye.
 
% Then to turn this mode off
Datapixx('SelectDevice', 2, 'LEFT');
Datapixx('SetVideoGreyscaleMode', 0);
Datapixx('SelectDevice', 2, 'RIGHT');
Datapixx('SetVideoGreyscaleMode', 0);
Datapixx('SelectDevice', -1);
Datapixx('RegWr');
Datapixx('Close');

If you are using other VPixx functionalities (e.g., digital inputs) make sure you run the SelectDevice command to target the correct monitor, before implementing any calls to the hardware.

To set a VIEWPixx /3D to use a specific colour channel as greyscale, use the command:

MATLAB
Datapixx('SetVideoGreyscaleMode', mode);

Where the following modes are available:

0: Disable greyscale mode, and present normal RGB colors.
1: Present greyscale image defined by red color channel.
2: Present greyscale image defined by green color channel.
3: Present greyscale image defined by blue color channel.

M16 Mode

If you need some colour in your stereoscopic images, you can also use M16 mode. M16 is primarily a high bit-depth mode and concatenates the 8-bit R and G channels to form a 16-bit greyscale that is passed to both the main display (connected to the GPU) and a console display (chained to the main display’s Video Out port). On the VIEWPixx /3D hardware, this 16-bit value is reduced to 10 bits per colour output. See our guide to high-bit-depth modes for more details.

In M16, the console display is NOT connected to your PC, but to the Video Out 2 on your main display. Your PC will not detect the console as a display. By default, the console display will show a copy of the main display.

In M16, the blue colour channel indexes a colour lookup table (CLUT) defined by the user. The user can specify two 256x3 CLUTs for the main display and console. A single value is used to index both.

CLUT values can range from 0-1, with a resolution of 16 bits per colour. The 4 least significant bits will be ignored by the hardware.

Let’s consider a simple example. In M16 mode, I create two CLUTs. In the Main Display CLUT, row 1 is full blue (0,0,1). In the Console CLUT, row 1 is full white (1,1,1). I draw some text and assign it the value (0,0,1) which points to the first row of the CLUTs.

MATLAB
DrawFormattedText(windowPtr, "Hello", 'center', 'center', [0,0,1]);
Screen('Flip', windowPtr);

Drawings (6).png

Simplified CLUTs for the Participant Display and Console

You can also define a “transparency” colour. The display will ignore this colour if it appears in the indexed row of the CLUT. Assuming we make full blue our transparency, this is the output.

Drawings (3).png

Transparency colour used in the main display.

The limitation of this method is the available colour space on a given frame. If you need to use transparencies and draw unique colour content to each display, this further limits the available rows in the table. 

 Some researchers get around this limitation by regularly updating their colour lookup tables (e.g., between trials). However, a single image could not contain a rich colour scene unique to one display. 

Blending, interpolating and antialiasing can cause strange results when using CLUTs. It is best to avoid these in our high bit depth modes like M16. See What is Pixel Identity Passthrough? for more details.

On Windows, due to PTB’s scaling methods, row 1 is ignored. Row 2 is indexed as 1, Row 3 as 2, etc. The MATLAB example below demonstrates this.

MATLAB Example
MATLAB
%This simple script draws a greyscale rectangle in both eyes, and some text
%on the console display (transparent on main display)

%Set up
%Establish the correct colour and video settings
AssertOpenGL;
PsychImaging('PrepareConfiguration');
PsychImaging('AddTask', 'General', 'FloatingPoint32Bit');
PsychImaging('AddTask', 'General', 'EnableDataPixxM16OutputWithOverlay');
KbName('UnifyKeyNames');

%Open a full-screen window with a black background
screenNumber = max(Screen('Screens'));
[win, winRect] = PsychImaging('OpenWindow', screenNumber, [0,0,0]);

%Make sure to disable anti-aliasing if you are using the colour overlay, as
%this can produce strange results.
Screen('Preference', 'TextAntiAliasing', 0); 

%Get our overlay window for our CLUTs
overlay = PsychImaging('GetOverlayWindow', win);

%Generate our colour look-up table (CLUT) for our main display.
%CLUT values are 0-1; the output is 16 bit (0-65535). 

%!! ON WINDOWS!!
% PTB scales colour by 255/256, therefore CLUT counting starts at the second row.
% See example below.

%!! ON OS-X !!
%CLUT assignment seems to have issues with mapping onto CLUTs. Consider making multiple (~5) rows 
%The same colour and calling the middle row to ensure a buffer. 

%The clut is first populated with black and then the first two rows are changed to blue and red
myTable=repmat([0,0,0], [256,1]);
myTable(2,:) = [0,0,1]; %Row 1
myTable(3,:)= [1,0,0];  %Row 2
myTable(4,:)= [1,1,1];  %Row 3 ... etc

%Create a copy of the first CLUT for the console and set row 1 to full blue 
myConsoleTable = myTable;
myConsoleTable(2,:) = [1,1,1]; %Row 1 of console CLUT

%Pass the CLUTS to the hardware
Datapixx('Open');
Datapixx('SetVideoClut', [myTable; myConsoleTable]);

%Let's set blue to be the transparency
myTransparency = [0,0,1];
Datapixx('SetVideoClutTransparencyColor', myTransparency);
Datapixx('EnableVideoClutTransparencyColorMode');

%Pass all commands to the hardware
Datapixx('RegWr');

%Determine our target gray value as a proportion of the maximum possible
%value. Remember this is 16-bit grayscale. 
midGrayLevel = 0.5;

% Start loop drawing our stimuli
while true
    
    %Draw a rectangle in the top left corner of the window and flip. This will
    %appear on both displays.
    Screen('FillRect', win, midGrayLevel, [0, 0, 400, 400]);
    
    %Text will be white on console, transparent on main display
    DrawFormattedText(overlay, 'Hello', 'center', 'center', 1);
    Screen('Flip', win);
    
    %Check for escape
    [~, ~, keyCode] = KbCheck;
    if keyCode(KbName('Escape'))
        break;
    end
end

% Shut down
sca;
Datapixx('DisableVideoClutTransparencyColorMode');
Datapixx('RegWr');
Datapixx('Close');
Python Example

Coming soon!

Summary

In this VOCAL, we covered some general recommendations for using the VIEWPixx /3D as a stereoscopic display, and gave explanations and demonstrations of some methods for implementing 3D stimuli. The methods discussed in this guide are summarized in the table below:

Description

Maximum Refresh

Best Used For

Temporally interleaved modes (single VIEWPixx /3D and 3DPixx active shutter glasses)

Frame-sequential stereo

Temporally interleave left/right eye images

Up to 60 Hz/eye

Not recommended

Frame-sequential stereo with Blue Lines

Temporally interleave left/right eye images, blue line used to maintain synchronization of shutter glasses

Up to 60 Hz/eye

3D applications where video must be robust against desynchronization

Top-Bottom mode

Left and right eye images stacked in a double-height window; shown sequentially on display

60 Hz/eye

3D applications where video must be robust against desynchronization; ideal for high-level stimulus generation (e.g., Unity, PsychoPy Builder)

Haploscope modes (two synchronized VIEWPixx /3Ds)

Mirror greyscale mode

Greyscale mode where left and right eye displays are mirrored, and content is driven by different colour channels (converted to greyscale output)

120 Hz/eye

Perfect display synchronization with no crosstalk

M16 mode

Same video signal is duplicated on both displays via console output. Colour lookup tables and transparencies used to present unique content on each display.

120 Hz/eye

Perfect display synchronization with no crosstalk, limited colour

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.