如何用C#单独控制立体帧? (NVIDIA 3D 快门眼镜)
我正在尝试制作一个非常简单的应用程序,它可以在每只眼睛上显示不同的图像。我有华硕 VG236H 显示器和 NVIDIA 3D Vision 套件、立体 3D 快门眼镜。我正在使用 C#、.NET Framework 2.0、DirectX 9(托管 Direct X)和 Visual Studio 2008。我一直在到处搜索示例和教程,实际上找到了一些示例和教程,并基于这些示例和教程我创建了程序,但是由于某种原因我无法让它工作。
在寻找如何为每只眼睛显示不同图像的示例时,许多人不断参考 GDC 09 上的 NVIDIA 演示(著名的 GDC09-3DVision-The_In_and_Out.pdf 文档)和第 37-40 页。我的代码主要是基于该示例构建的:
- 我在表面(_imageLeft 和 _imageRight)上加载两个纹理(Red.png 和 Blue.png),在函数 LoadSurfaces()
- Set3D() 函数中将这两个图像并排放置-一侧到一个更大的图像,其大小为 2x 屏幕宽度和屏幕高度 + 1 (_imageBuf)。
- Set3D() 函数继续在最后一行附加立体声签名。
- OnPaint() 函数获取后台缓冲区 (_backBuf) 并将组合图像 (_imageBuf) 的内容复制到其中。
当我运行该程序时,快门眼镜开始工作,但我只能在屏幕上看到并排的两个图像。有人可以帮忙告诉我我做错了什么吗?我相信解决这个问题也可能对其他人有帮助,因为似乎还没有一个简单的例子如何使用 C# 来做到这一点。
以下是我的代码的战术部分。完整的项目可以在这里下载:http://koti.mbnet.fi/jjantti2/NVStereoTest.rar
public void InitializeDevice()
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = false;
presentParams.BackBufferFormat = Format.A8R8G8B8;
presentParams.BackBufferWidth = _size.Width;
presentParams.BackBufferHeight = _size.Height;
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.PresentationInterval = PresentInterval.One;
_device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
}
public void LoadSurfaces()
{
_imageBuf = _device.CreateOffscreenPlainSurface(_size.Width * 2, _size.Height + 1, Format.A8R8G8B8, Pool.Default);
_imageLeft = Surface.FromBitmap(_device, (Bitmap)Bitmap.FromFile("Blue.png"), Pool.Default);
_imageRight = Surface.FromBitmap(_device, (Bitmap)Bitmap.FromFile("Red.png"), Pool.Default);
}
private void Set3D()
{
Rectangle destRect = new Rectangle(0, 0, _size.Width, _size.Height);
_device.StretchRectangle(_imageLeft, _size, _imageBuf, destRect, TextureFilter.None);
destRect.X = _size.Width;
_device.StretchRectangle(_imageRight, _size, _imageBuf, destRect, TextureFilter.None);
GraphicsStream gStream = _imageBuf.LockRectangle(LockFlags.None);
byte[] data = new byte[] {0x44, 0x33, 0x56, 0x4e, //NVSTEREO_IMAGE_SIGNATURE = 0x4433564e
0x00, 0x00, 0x0F, 0x00, //Screen width * 2 = 1920*2 = 3840 = 0x00000F00;
0x00, 0x00, 0x04, 0x38, //Screen height = 1080 = 0x00000438;
0x00, 0x00, 0x00, 0x20, //dwBPP = 32 = 0x00000020;
0x00, 0x00, 0x00, 0x02}; //dwFlags = SIH_SCALE_TO_FIT = 0x00000002;
gStream.Seek(_size.Width * 2 * _size.Height * 4, System.IO.SeekOrigin.Begin); //last row
gStream.Write(data, 0, data.Length);
gStream.Close();
_imageBuf.UnlockRectangle();
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
_device.BeginScene();
// Get the Backbuffer then Stretch the Surface on it.
_backBuf = _device.GetBackBuffer(0, 0, BackBufferType.Mono);
_device.StretchRectangle(_imageBuf, new Rectangle(0, 0, _size.Width * 2, _size.Height + 1), _backBuf, new Rectangle(0, 0, _size.Width, _size.Height), TextureFilter.None);
_backBuf.ReleaseGraphics();
_device.EndScene();
_device.Present();
this.Invalidate();
}
I’m trying to make a very simple application which would display different images on each eye. I have Asus VG236H monitor and NVIDIA 3D Vision kit, the stereo 3D shutter glasses. The I’m using C#, .NET Framework 2.0, DirectX 9 (Managed Direct X) and Visual Studio 2008. I have been searching high and low for examples and tutorials, have actually found a couple and based those I have created the program but for some reason I can’t get it working.
When looking for examples how to display different images for each eye, many people keep referring to the NVIDIA presentation at GDC 09 (the famous GDC09-3DVision-The_In_and_Out.pdf document) and the pages 37-40. My code is mainly constructed based on that example:
- I'm loading two textures (Red.png and Blue.png) on surface (_imageLeft and _imageRight), in function LoadSurfaces()
- Set3D() function puts those two images side-by-side to one bigger image which has the size of 2x Screen width and Screen height + 1 (_imageBuf).
- Set3D() function continues by appending the stereo signature on the last row.
- OnPaint()-function takes the back buffer (_backBuf) and copies the content of the combined image (_imageBuf) to it.
When I run the program, shutter glasses start working, but I only see the two images side-by-side on the screen. Could someone help out and tell me what am I doing wrong? I believe that solving this problem might also help others as there does not yet seem to be a simple example how to do this with C#.
Below are the tactical parts of my code. Complete project can be downloaded here: http://koti.mbnet.fi/jjantti2/NVStereoTest.rar
public void InitializeDevice()
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = false;
presentParams.BackBufferFormat = Format.A8R8G8B8;
presentParams.BackBufferWidth = _size.Width;
presentParams.BackBufferHeight = _size.Height;
presentParams.BackBufferCount = 1;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.PresentationInterval = PresentInterval.One;
_device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
}
public void LoadSurfaces()
{
_imageBuf = _device.CreateOffscreenPlainSurface(_size.Width * 2, _size.Height + 1, Format.A8R8G8B8, Pool.Default);
_imageLeft = Surface.FromBitmap(_device, (Bitmap)Bitmap.FromFile("Blue.png"), Pool.Default);
_imageRight = Surface.FromBitmap(_device, (Bitmap)Bitmap.FromFile("Red.png"), Pool.Default);
}
private void Set3D()
{
Rectangle destRect = new Rectangle(0, 0, _size.Width, _size.Height);
_device.StretchRectangle(_imageLeft, _size, _imageBuf, destRect, TextureFilter.None);
destRect.X = _size.Width;
_device.StretchRectangle(_imageRight, _size, _imageBuf, destRect, TextureFilter.None);
GraphicsStream gStream = _imageBuf.LockRectangle(LockFlags.None);
byte[] data = new byte[] {0x44, 0x33, 0x56, 0x4e, //NVSTEREO_IMAGE_SIGNATURE = 0x4433564e
0x00, 0x00, 0x0F, 0x00, //Screen width * 2 = 1920*2 = 3840 = 0x00000F00;
0x00, 0x00, 0x04, 0x38, //Screen height = 1080 = 0x00000438;
0x00, 0x00, 0x00, 0x20, //dwBPP = 32 = 0x00000020;
0x00, 0x00, 0x00, 0x02}; //dwFlags = SIH_SCALE_TO_FIT = 0x00000002;
gStream.Seek(_size.Width * 2 * _size.Height * 4, System.IO.SeekOrigin.Begin); //last row
gStream.Write(data, 0, data.Length);
gStream.Close();
_imageBuf.UnlockRectangle();
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
_device.BeginScene();
// Get the Backbuffer then Stretch the Surface on it.
_backBuf = _device.GetBackBuffer(0, 0, BackBufferType.Mono);
_device.StretchRectangle(_imageBuf, new Rectangle(0, 0, _size.Width * 2, _size.Height + 1), _backBuf, new Rectangle(0, 0, _size.Width, _size.Height), TextureFilter.None);
_backBuf.ReleaseGraphics();
_device.EndScene();
_device.Present();
this.Invalidate();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的一个朋友发现了这个问题。立体声签名中的字节顺序相反。以下是正确的顺序:
此更改后代码可以完美运行。对于其他尝试同样事情的人来说,该代码甚至可以作为一个很好的教程。 :)
A friend of mine found the problem. The bytes in the stereo signature were in reversed order. Here is the correct order:
The code works perfectly after this change. This code might even serve as a good tutorial for someone else attempting the same thing. :)