如何用C#单独控制立体帧?(英伟达3D快门眼镜)

本文关键字:3D 快门 眼镜 单独 何用 控制 | 更新日期: 2023-09-27 17:56:05

我正在尝试制作一个非常简单的应用程序,它将在每只眼睛上显示不同的图像。我有华硕VG236H显示器和NVIDIA 3D Vision套件,立体3D快门眼镜。我正在使用C#,.NET Framework 2.0,DirectX 9(Managed Direct X)和Visual Studio 2008。我一直在上下搜索示例和教程,实际上已经找到了几个并基于我创建了该程序的那些,但由于某种原因我无法让它工作。

在寻找如何为每只眼睛显示不同图像的示例时,许多人不断参考 GDC 09(著名的 GDC09-3DVision-The_In_and_Out.pdf 文档)和 37-40 页的 NVIDIA 演示。我的代码主要是基于该示例构建的:

  1. 我在函数 LoadSurfaces() 中在表面(_imageLeft 和 _imageRight)上加载两个纹理(红色.png和蓝色.png
  2. Set3D() 函数将这两个图像并排放置到一个较大的图像上,该图像的大小为 2x 屏幕宽度和屏幕高度 + 1 (_imageBuf)。
  3. Set3D() 函数通过在最后一行附加立体签名来继续。
  4. 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();
    }

如何用C#单独控制立体帧?(英伟达3D快门眼镜)

我的一个朋友发现了这个问题。立体声签名中的字节顺序相反。这是正确的顺序:

byte[] data = new byte[] {0x4e, 0x56, 0x33, 0x44,   //NVSTEREO_IMAGE_SIGNATURE         = 0x4433564e;
0x00, 0x0F, 0x00, 0x00,   //Screen width * 2 = 1920*2 = 3840 = 0x00000F00;
0x38, 0x04, 0x00, 0x00,   //Screen height = 1080             = 0x00000438;
0x20, 0x00, 0x00, 0x00,   //dwBPP = 32                       = 0x00000020;
0x02, 0x00, 0x00, 0x00};  //dwFlags = SIH_SCALE_TO_FIT       = 0x00000002;

此更改后,代码运行良好。这段代码甚至可以作为其他人尝试同样事情的好教程。:)