OpenGL Stereo support (NVIDIA - ATI)

Hello all,

1-
I have written a OpenGL stereo renderer (using directshow) that must work
using dualview (or
similar in other GC).
The problem is that when I turn dualview on and setup OpenGL stereo mode on
both monitors, only the primary works, the second returns an openGL error
that it does not support stereo.
It actually should work, is there anybody there who has experience with
NVIDIA development ? I’m using the current Forceware drivers.
Does ATI supports it in their 256p Graphic card ?
I need dualview because one of the monitors must be in portrait mode due to
it’s vertical interlaced properties. It’s an auto stereo monitor that uses
lenticular lenses.

2-
The renderer receives a media sample from directshow. This sample is stored
in a texture and then it’s rendered using the back ight and left buffers.
I would like to optimize it, for example which glHint values would make
sense ? I disabled depth test also, what else can I disable ?
Currently I’m receiving side-by-side images. At the end I’ve pasted some
code showing how I’m rendering.

Does anybody could point me to a place where I can find info on OpenGL
optimizations (i.e. for NVIDIA).
Any help welcome.

TIA.

wpr.

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_captureWidth,
m_captureHeight, m_colorFormat, m_colorBitFormat, (void*)m_pImage);
glDrawBuffer(GL_BACK_LEFT);

glClear(GL_COLOR_BUFFER_BIT);// Clear Screen
glMatrixMode(GL_MODELVIEW);// Select The Modelview Matrix
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, m_videoTexture);

glBegin(GL_QUADS);
// video backplate
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(m_widthRelation, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(m_widthRelation, m_heightRelation);
glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, m_heightRelation);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();

glDrawBuffer(GL_BACK_RIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);// Select The Modelview Matrix
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, m_videoTexture);
glBegin(GL_QUADS);
// video backplate
glTexCoord2f(m_widthRelation, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(2m_widthRelation, 0.0f); glVertex3f( 1.0f, -1.0f,
0.0f);
glTexCoord2f(2
m_widthRelation, m_heightRelation);
glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(m_widthRelation, m_heightRelation);
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
SwapBuffers(m_hdc);

from NV drivers for X11. Hope, under Win32 is the same.

4 - TwinView clone mode stereo. On video cards that support TwinView, the left eye is displayed on the first display, and the right eye is displayed on the second display. This is normally used in conjuction with special projectors to produce 2 polarized images which are then viewed with polarized glasses. To use this stereo mode, you must also configure TwinView in clone mode with the same resolution, panning offset, and panning domains on each display.

Stereo is only available on Quadro cards, and is not supported in TwinView (with the exception of TwinView clone mode stereo, option #4 above).

Who would build a monitor which has the lenses in portrait mode? The effective horizontal resolution would be even worse.

If it’s an autostereo monitor, you don’t need a stereo pixelformat but can render your image twice with a suitable stencil pattern which is aligned to the screen’s pixel grid.
Fastest way to draw that striped pattern into the stencil buffer is with polygon stipple and glRect. A drawpixels to the stencil buffer would work too, but is much slower.
Remember that you need to align the pattern to the screen pixels on each window move and need to repair it in case your window had been occluded or moved offscreen.

I don’t get the point of rendering the pattern fast. You just render it once in the stencil buffer and never clear the stencil buffer after that. Then you just have to change the stencil function to render when stencil == 0 for left eye and when stencil == 1 for right eye, for instance.

[This message has been edited by vincoof (edited 11-27-2003).]

The pixel ownership changes when you have any window overlapping your OpenGL window. If you don’t repaint the stencil on expose events you’ll see corruption, because the other application might have cleared the stencil at that frambuffer position.
It’s wrong by design to think pixels which are underneath another window are still valid on an expose event. This includes ALL pixel planes for front, back, depth, stencil, …
If you do so, you’re relying on implementation dependent behaviour and your app wouldn’t work correctly on a lot of implementations (all workstation class boards I can think of).

Sure, then catch events like move / resize / repaint and then redraw your stencil buffer only at that time.

Hello,

Relic, very good explanation, actually I’m already trying to use the stencil buffer, but I’m starting with OpenGL and I don’t know how to make the alignment.

Currently I receive the images in side by side, then I put in the texture, and use the back left and right to render it because we have a OpenGL wrapper that adjusts it to the screen (interlace and rotate).

Where can I find info on how to do it with the stencil or this other faster method. Is there a way to write the images directly interlaced. Using nvidia render to texture or something !? Well thanks a lot for the help.

Well, now I will explain why the monitor uses the portrait mode. This is because of the lenticular lenses. They are special contructed so that the crosstalking is smaller than 2% (I think the ones out there are currently 15%). This makes this monitor have a much better 3D effect. Believe me, I already saw the others.
Ah, the lenticular woudn’t work in landscape because it would diffuse the light because of how the Pixel is drawn.
More info: http://www.actkern.info/eHome/eProdukte/e3DDisplay/e3ddisplay.html

Cheers.

>>Believe me, I already saw the others.<<

Me too.
You work for that company?

A straightforward implementation would need two stipple patterns, the even one contains all 0x55 bytes, the odd one all 0xAA.
To decide which to take you need to calculate the desktop position of the window’s first column:

point.x = 0;
point.y = 0;
ClientToScreen(hwnd, &point);
nScreenOffset = point.x;

To fill the stencil you use this:

// Draw vertical stripes into the stencil buffer to partition the left and right buffer.

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, (double) nWidth, 0.0, (double) nHeight, -1.0, 1.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
// You may need to disable other fragment operations.
glClear(GL_STENCIL_BUFFER_BIT);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, ~0);
glEnable(GL_STENCIL_TEST);

// If the first client pixel is on an even screen pixel, use the even pattern.
if ((nScreenOffset & 1) == 0)
{
glPolygonStipple(patternEven);
}
else
{
glPolygonStipple(patternOdd);
}
glEnable(GL_POLYGON_STIPPLE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

glRecti(0, 0, nWidth, nHeight);

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_POLYGON_STIPPLE);
glEnable(GL_LIGHTING);

To draw your two stereo images do this

// Update stencil here with above calls if necessary!

glDrawBuffer(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Select back “left” buffer.
// The left image lies in the 0-stripes.
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 0, ~0);
glEnable(GL_STENCIL_TEST);

// Draw left eye image here

// Select back “right” buffer
glStencilFunc(GL_NOTEQUAL, 0, ~0);

// Draw right eye image here.

All code pieces ripped from 4 year old code and not changed since. Should work instantly.

Hello Relic,

Yes, I work fr this company.

So, yesterday I could manage to make it work, I used GL_LINES to create the pattern.

Now I tried your way. It works also, but I can’t see improvements. Which one would be the fastest theoretically ?

Does the GL_UNPACK_ALIGNMENT interfere in the speed ? I’m currently using the default( I think is 4).

I wrote a small function to print the fps and I’m getting 20 for an avi video.

The only bad thing is that when I turn DualView in order to rotate the 3D monitor, the fps drop to 10 It doesn’t matter if I use stereo buffers or stencil. Looks like there is no hw accel.

I think I will have to rotate the image my self, is there a fast way to do it? Would be cool if I could rotate the window… well I have to do some research.

Thanks a lot

wpr.

OOps

I will rotate using the texture coordinates.

wpr.

GL_LINES is dangerous, you need to be very careful with the pixel positions. The stipple pattern is much easier, pixel aligned and should be faster, well probably no difference, it touches the same pixels.

GL_UNPACK_ALIGNMENT with respect to what operation? Yes, 4 is the default, but that doesn’t matter as long as it fits to your image width.

You can only be download or fillrate bound, as you just render two quads.
First bets are on the download rate.

Check out the pixel data range extension in that case (http://oss.sgi.com/projects/ogl-sample/registry/NV/pixel_data_range.txt)

Always check your pixelformat and glGetString in case you think you lost hardware acceleration.

Those vertical interlace monitors are not good for 2D desktop work so I expect your’re running fullscreen.
Rotating an image you have downloaded as a texture by multiples of 90 degrees is mondo easy, just change your texture coordinates at the quads’ vertices.
Mouse interaction could get weird if the display is rotated, but the mouse positions aren’t.

Isn’t polygon stipple reputedly free? If it is, there should be no need to use the stencil buffer so long as you’re only using polygons to render in stereo.
Seems likely that it’s faster than the stencil test.

Good point, that would be possible here.
But it wouldn’t work for a general 3D stereo app because polygon stipple is applied to filled primitives only, the stencil test works for any fragment.

Originally posted by Relic:
But it wouldn’t work for a general 3D stereo app because polygon stipple is applied to filled primitives only

Yeah, that was my poorly explained “only using polygons to render in stereo”.

No offense meant, I noticed that after I hit submit and was too lazy to correct it.
Let’s keep it as hint for others stumbling across polygon stipple wonders.