I'm trying to create a 3D environment using DirectX. Is there any kind of
tutorial out there for surface flipping 2 images, a left and a right image, that
would sync with my CRT vertical sync so that my shutter glasses would hide the
right image from the left eye and left image from the right eye?
So far, I've got my images flipping but I can't seem to make them sync with the
CRT vertical sync... I'm using IDirect3DDevice9::Present() to accomplish this.
Is there a way to configure the D3DPRESENT_PARAMETERS to auto-sync to the CRT?
If I understand this correctly, all I have to do is ensure that each CRT paint
(at 120Hz) paints alternating images as the shutter glasses sync with the CRT's
vertical sync automatically...
Here's what (I think) I know at this point...
My main message processing loop calls my rendering function which displays the
left or right picture on the screen via Present(). As the PresentationInterval
is INTERVAL_ONE, it should work... and does. But, my guess is, every so often,
my program get forced out of the CPU (WinAmp does this very reliably) and
therefore misses a vSync from the monitor, resulting in my left and right images
reversing and my eyes effectively crossing.
I was thinking about checking each successive call into my ShowSynchronizedFrame
against the Windows TickCount and estimating which image (left or right) I
should be displaying. Alternatively, if I could somehow get the number of vSyncs
that have elapsed, I could easily determine the proper image to display based on
oddness or evenness of this number...
I figure this is 3D Gaming 101 because if you can't get your display to stay in
sync, you get killed pretty fast by the guys you're trying to shoot. ;)
Unfortunately, I have little experience with DirectX.
Thanks,
Rob
...
// DirectX painting of backbuffers
void ShowSynchronizedFrame()
{
// flip front and back buffers - this displays new image data
if (g_pd3dDevice->Present(NULL, NULL, g_hWnd, NULL) != D3DERR_WASSTILLDRAWING)
{
// flip left/right surface
PaintLeftFrame = !PaintLeftFrame;
}
}
...
// configure Direct3D Present() parameters
d3dpp.BackBufferWidth = bmInfo->bmiHeader.biWidth;
d3dpp.BackBufferHeight = bmInfo->bmiHeader.biHeight;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = NULL;
d3dpp.Windowed = false;
d3dpp.EnableAutoDepthStencil = false;//true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = 120;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
...
// main event loop for page flipping window
do
{
// process all events
if (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE))
{
// standard message dispatch...
TranslateMessage(&uMsg);
DispatchMessage (&uMsg);
}
// display proper back buffer
ShowSynchronizedFrame();
}
while (uMsg.message != WM_QUIT);
It's been a while since I did the same thing you're trying. It goes
out of sync, I was told because, the scene isn't ready to be presented
yet, so the next scene drawn on the CRT is still the old scene, even
tho you got a VSync and the glasses flipped. You need more back
buffers ( 4?) Two for left and right completed scenes that get flipped
to the front and two for right and left in process that get rotated up
when there ready. But I never got there. So you need to investigate
swapping backbuffers and chains.
here is a VERY good web site:
http://www.stereo3d.com/3dhome.htm
I also have a P5 powerglove that tracks your hand in 3D space. I made
a real cool app where you can grab and move objects floating in front
of you.
I can dig up some code if you want.
Thanks for the post.... the funny thing is that all I'm doing at this
point is flipping 2 images, left and right, back and forth, no
rendering. I can't seem to keep the left image on the left eye
consistently. It works after the window stabalizes - after Windows gets
done rearranging all the desktop icons and other windows when my screen
resolution changes to 640x480. Then, left switches over to right after
10-20 seconds, probably because Windows is busy doing something else at
just the wrong time and I miss a vertical sync because my message loop
is not in the processor.
I've been experimenting with QueryPerformanceCounter() and getting very
precise measurements in between frame paints. (My paint function is
below.) I see ~11.7ms in between each paint call very consistently.
However, every once in a while I see a delay of ~24ms or ~32ms which
seems to be consistent with the crisscross of the left and right images.
All attempts to flip or not flip depending on the time in between paints
have not yielded the desired results. :(
Am I going about this wrong? Is there an easier way to do this? This is
gaming 101, right? Left stays on left, right stays on right, and we're
all happy shooting at each other in 3D! :D
...
// pointer to DirectX backbuffer
LPDIRECT3DSURFACE9 pBackBuffer;
// get pointer to first (and only) back buffer for background rendering
g_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
// paint left/right surface with first pair
if (PaintLeftFrame)
g_pd3dDevice->UpdateSurface(SurfaceLeft1, &BackBufferRect,
pBackBuffer, &BackBufferPoint);
else
g_pd3dDevice->UpdateSurface(SurfaceRight1, &BackBufferRect,
pBackBuffer, &BackBufferPoint);
// free resources
pBackBuffer->Release();
// flip front/back buffers - displays new image data
g_pd3dDevice->Present(NULL, NULL, g_hWnd, NULL);
at On Thu, 19 Jul 2007 06:38:21 -0400, "Robert G. Hoover"
THANKS!!! :D