GerhardKauer's picture

Stereoscopic Quad Buffer first experiences with OpenTk

Hi there,
if someone is interested in my first experiences, how to do some basic programming on quad buffered systems towards 3D (stereoscopic) using pol-shutter monitors, here are some simple hints. I know, that the example is very basic, on the other hand the first steps to a new technology are sometimes difficult and simple code could help more in that cases.

My hardware is as follows ( I do have two monitors and two graphic adaptors in my system, which is not necessary, but nice to have for me ):

1. BenQ G2200W (for my "normal" use)
2. BenQ XL2420 (as extended desktop, screen 2 for 3D watching) + Pol Shutter glasses

3. NVIDIA GeForce GTX460 (for some cuda stuff programming) connected to BenQ G2200W: Screen 1
4. NVIDIA Quadro 600 (cheap enough for my budget, doing quad buffering) connected to BenQ XL2420 : Screen 2

Newest OpenTK (thanks for producing- I love it!!!)
Visual Studio 2010 Ultimate

Following code is NOT stereoscopic, but for demonstration how to "send" one image to the left eye and the other to the "right" eye. The most lines of code are not of interest. The only things of interest are:
1. new GraphicsMode(32, 24, 8, 0,new ColorFormat(24),8,true),
2. -- Left eye
GL.DrawBuffer(DrawBufferMode.BackLeft);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Begin(BeginMode.Points);
...
GL.Color3(1.0f, 1.0f, 0.0f);
...
GL.End();
-- Right eye
GL.DrawBuffer(DrawBufferMode.BackRight);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Begin(BeginMode.Points);
...
GL.Color3(1.0f, 1.0f, 0.0f);
...
GL.End();

What I do not fully understand is the fact, that the parameter 'X' in the following code

new GraphicsMode(32, 24, 8, 0,new ColorFormat(24), X , true),

does not seem to be of that importance (works with X= 2, X= 4 X= 8)

don't know why. :-(

What's interesting is, that there are absolutely no problems in running the application with Stereo at Screen2, even if the programm launches on screen1. Simply drag the window to the "stereo-screen" 2 and the shutter glasses start their work.

To be seen: Bright dots on left eye
Darker dots on right eye.

It's simple from now on to sketch stereo-images correspondingly.

If someone is interested in my hardware-settings I could provide some hints for tuning Windows7 Nvidia to work well. You have to do some settings in the Nvidia control panel to run OpenGL (and therefore OpenTK ) fine.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// Released to the public domain. Use, modify and relicense at will.

using System;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Audio;
using OpenTK.Audio.OpenAL;
using OpenTK.Input;

namespace StarterKit
{
class Game : GameWindow
{
/// Creates a 800x600 window with the specified title.
public Game()
: base(800, 600, new GraphicsMode(32, 24, 8, 0,new ColorFormat(24),8,true), "OpenTK Quick Start Sample")
{
VSync = VSyncMode.On;

// ColorFormat colFmt= new ColorFormat(24);
// var mode = new GraphicsMode(32, 24, 8, 0,colFmt,2,true);
}

/// Load resources here.
/// Not used.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f);
GL.Enable(EnableCap.DepthTest);

int iAttachments=0;
int iWriteBuffers=0;

GL.GetInteger( GetPName.MaxColorAttachmentsExt, out iAttachments);
GL.GetInteger( GetPName.MaxDrawBuffers, out iWriteBuffers);
}

///
/// Called when your window is resized. Set your viewport here. It is also
/// a good place to set up your projection matrix (which probably changes
/// along when the aspect ratio of your window).
///
/// Not used.
protected override void OnResize(EventArgs e)
{
base.OnResize(e);

GL.Viewport(0,0,800,600);

}

///
/// Called when it is time to setup the next frame. Add you game logic here.
///
/// Contains timing information for framerate independent logic.
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);

if (Keyboard[Key.Escape])
Exit();
}

///
/// Called when it is time to render the next frame. Add your rendering code here.
///
/// Contains timing information.
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
/* DrawBuffersEnum[] bufs = new DrawBuffersEnum[2] { (DrawBuffersEnum)FramebufferAttachment.ColorAttachment0Ext,
(DrawBuffersEnum)FramebufferAttachment.ColorAttachment1Ext };*/

GL.PointSize(20.0f);
GL.Enable(EnableCap.PointSmooth);

//----------------------------- Left "eye" ---------------------
GL.DrawBuffer(DrawBufferMode.BackLeft);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Begin(BeginMode.Points);

GL.Color3(1.0f, 1.0f, 0.0f);
GL.Vertex2(0.0f, 0.0f);
GL.Color3(0.0f, 1.0f, 0.0f);
GL.Vertex2(0.5f, 0.5f);
GL.Color3(1.0f, 0.0f, 0.0f);
GL.Vertex2(-0.5f, -0.5f);
GL.End();

//----------------------------- Right "eye" ---------------------
//
GL.DrawBuffer(DrawBufferMode.BackRight);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Begin(BeginMode.Points);

GL.Color3(0.5f, 0.5f, 0.0f);
GL.Vertex2(0.0f, 0.1f);
GL.Color3(0.0f, 0.5f, 0.0f);
GL.Vertex2(0.5f, 0.6f);
GL.Color3(0.5f, 0.0f, 0.0f);
GL.Vertex2(-0.5f, -0.4f);
GL.End();

SwapBuffers();

}

///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
// The 'using' idiom guarantees proper resource cleanup.
// We request 30 UpdateFrame events per second, and unlimited
// RenderFrame events (as fast as the computer can handle).

using (Game game = new Game())
{
game.Run(30.0);
}
}
}
}


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
c2woody's picture
Quote:

What I do not fully understand is the fact, that the parameter 'X' in the following code
new GraphicsMode(32, 24, 8, 0,new ColorFormat(24), X , true)

It's the buffer value where ==1 means direct drawing (no buffer swapping), ==2 is the usual double buffer enabled mode etc.

GerhardKauer's picture

Dear c2woody,

wow, thanks, now I understand that last piece, also. Do you think values of 4, 8 and so on make more sense? In my case, would value 4 be recommendable, then?
I found it astonishing, that stereoscopic viewing was working with any of these values (2, 4 or 8) - as if it would not matter.

I am glad to say, that OpenTK really makes fun with my "low-cost" QuadBuffer. It is so amazing how easy programming is with OpenTK to get stereoscopic image viewing (compared to DirectX, which is a nightmare compared to OpenTK in this case).

And thanks for answering.

Best whishes
Gerhard

c2woody's picture

Have a look again what the last two parameters specify: number of buffers and stereo capabilities. So your request for "2, true" means "doublebuffered stereo context" (which will use 4 buffers therefore if you are on such hardware). So if you are using SwapBuffers as in your example you'll need the 2 and for stereo (left/right chooseability) you need the last "true".