C# 在C中使用DirectX11和SlimDX的Nvidia 3d视频#

C# 在C中使用DirectX11和SlimDX的Nvidia 3d视频#,c#,nvidia,direct3d,directx-11,slimdx,C#,Nvidia,Direct3d,Directx 11,Slimdx,你好, 我正在尝试使用nvidia 3DVision和两个IP摄像头显示实时立体视频。我对DirectX完全陌生,但我尝试过在这个网站和其他网站上完成一些教程和其他问题。现在,我正在为左眼和右眼显示两个静态位图。一旦我的程序的这一部分开始工作,这些将被我相机中的位图所取代。 这个问题对我帮助很大,但我仍在努力让我的程序正常工作。我发现我的快门眼镜开始正常工作,但只显示右眼的图像,而左眼保持空白(除了鼠标光标) 以下是生成立体图像的代码: using System; using System.Co

你好, 我正在尝试使用nvidia 3DVision和两个IP摄像头显示实时立体视频。我对DirectX完全陌生,但我尝试过在这个网站和其他网站上完成一些教程和其他问题。现在,我正在为左眼和右眼显示两个静态位图。一旦我的程序的这一部分开始工作,这些将被我相机中的位图所取代。 这个问题对我帮助很大,但我仍在努力让我的程序正常工作。我发现我的快门眼镜开始正常工作,但只显示右眼的图像,而左眼保持空白(除了鼠标光标)

以下是生成立体图像的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

using SlimDX;
using SlimDX.Direct3D11;
using SlimDX.Windows;
using SlimDX.DXGI;

using Device = SlimDX.Direct3D11.Device;            // Make sure we use DX11
using Resource = SlimDX.Direct3D11.Resource;

namespace SlimDxTest2
{
static class Program
{
    private static Device device;               // DirectX11 Device
    private static int Count;                   // Just to make sure things are being updated

    // The NVSTEREO header. 
    static byte[] stereo_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

    [STAThread]
    static void Main()
    {

        Bitmap left_im = new Bitmap("Blue.png");        // Read in Bitmaps
        Bitmap right_im = new Bitmap("Red.png");

        // Device creation 
        var form = new RenderForm("Stereo test") { ClientSize = new Size(1920, 1080) };
        var desc = new SwapChainDescription()
        {
            BufferCount = 1,
            ModeDescription = new ModeDescription(1920, 1080, new Rational(120, 1), Format.R8G8B8A8_UNorm),
            IsWindowed = false, //true,
            OutputHandle = form.Handle,
            SampleDescription = new SampleDescription(1, 0),
            SwapEffect = SwapEffect.Discard,
            Usage = Usage.RenderTargetOutput
        };

        SwapChain swapChain;
        Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.Debug, desc, out device, out swapChain);

        RenderTargetView renderTarget;          // create a view of our render target, which is the backbuffer of the swap chain we just created
        using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
            renderTarget = new RenderTargetView(device, resource);

        var context = device.ImmediateContext;                  // set up a viewport
        var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height);
        context.OutputMerger.SetTargets(renderTarget);
        context.Rasterizer.SetViewports(viewport);

        // prevent DXGI handling of alt+enter, which doesn't work properly with Winforms
        using (var factory = swapChain.GetParent<Factory>())
            factory.SetWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);

        form.KeyDown += (o, e) =>                   // handle alt+enter ourselves
        {
            if (e.Alt && e.KeyCode == Keys.Enter)
                swapChain.IsFullScreen = !swapChain.IsFullScreen;
        };

        form.KeyDown += (o, e) =>                   // Alt + X -> Exit Program
        {
            if (e.Alt && e.KeyCode == Keys.X)
            {
                form.Close();
            }
        };

        context.ClearRenderTargetView(renderTarget, Color.Green);       // Fill Screen with specified colour

        Texture2DDescription stereoDesc = new Texture2DDescription()
        {
            ArraySize = 1,
            Width = 3840,
            Height = 1081,
            BindFlags = BindFlags.None,
            CpuAccessFlags = CpuAccessFlags.Write,
            Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm,
            OptionFlags = ResourceOptionFlags.None,
            Usage = ResourceUsage.Staging,
            MipLevels = 1,
            SampleDescription = new SampleDescription(1, 0)
        };

        // Main Loop 
        MessagePump.Run(form, () =>
        {
            Texture2D texture_stereo =  Make3D(left_im, right_im);      // Create Texture from two bitmaps in memory
            ResourceRegion stereoSrcBox = new ResourceRegion { Front = 0, Back = 1, Top = 0, Bottom = 1080, Left = 0, Right = 1920 };
            context.CopySubresourceRegion(texture_stereo, 0, stereoSrcBox, renderTarget.Resource, 0, 0, 0, 0);
            texture_stereo.Dispose();

            swapChain.Present(0, PresentFlags.None);
        });

        // Dispose resources 

        swapChain.IsFullScreen = false;     // Required before swapchain dispose
        device.Dispose();
        swapChain.Dispose();
        renderTarget.Dispose();

    }



    static Texture2D Make3D(Bitmap leftBmp, Bitmap rightBmp)
    {
        var context = device.ImmediateContext;
        Bitmap left2 = leftBmp.Clone(new RectangleF(0, 0, leftBmp.Width, leftBmp.Height), PixelFormat.Format32bppArgb);     // Change bmp to 32bit ARGB
        Bitmap right2 = rightBmp.Clone(new RectangleF(0, 0, rightBmp.Width, rightBmp.Height), PixelFormat.Format32bppArgb);

        // Show FrameCount on screen: (To test)
        Graphics left_graph = Graphics.FromImage(left2);
        left_graph.DrawString("Frame: " + Count.ToString(), new System.Drawing.Font("Arial", 16), Brushes.Black, new PointF(100, 100));
        left_graph.Dispose();

        Graphics right_graph = Graphics.FromImage(right2);
        right_graph.DrawString("Frame: " + Count.ToString(), new System.Drawing.Font("Arial", 16), Brushes.Black, new PointF(200, 200));
        right_graph.Dispose();
        Count++;

        Texture2DDescription desc2d = new Texture2DDescription()
        {
            ArraySize = 1,
            Width = 1920,
            Height = 1080,
            BindFlags = BindFlags.None,
            CpuAccessFlags = CpuAccessFlags.Write,
            Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm,
            OptionFlags = ResourceOptionFlags.None,
            Usage = ResourceUsage.Staging,
            MipLevels = 1,
            SampleDescription = new SampleDescription(1, 0)
        };

        Texture2D leftText2 = new Texture2D(device, desc2d);        // Texture2D for each bmp
        Texture2D rightText2 = new Texture2D(device, desc2d);

        Rectangle rect = new Rectangle(0, 0, left2.Width, left2.Height);
        BitmapData leftData = left2.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        IntPtr left_ptr = leftData.Scan0;
        int left_num_bytes = Math.Abs(leftData.Stride) * leftData.Height;
        byte[] left_bytes = new byte[left_num_bytes];
        byte[] left_bytes2 = new byte[left_num_bytes];

        System.Runtime.InteropServices.Marshal.Copy(left_ptr, left_bytes, 0, left_num_bytes);       // Get Byte array from bitmap
        left2.UnlockBits(leftData);
        DataBox box1 = context.MapSubresource(leftText2, 0, MapMode.Write, SlimDX.Direct3D11.MapFlags.None);
        box1.Data.Write(left_bytes, 0, left_bytes.Length);
        context.UnmapSubresource(leftText2, 0);

        BitmapData rightData = right2.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        IntPtr right_ptr = rightData.Scan0;
        int right_num_bytes = Math.Abs(rightData.Stride) * rightData.Height;
        byte[] right_bytes = new byte[right_num_bytes];

        System.Runtime.InteropServices.Marshal.Copy(right_ptr, right_bytes, 0, right_num_bytes);       // Get Byte array from bitmap
        right2.UnlockBits(rightData);
        DataBox box2 = context.MapSubresource(rightText2, 0, MapMode.Write, SlimDX.Direct3D11.MapFlags.None);
        box2.Data.Write(right_bytes, 0, right_bytes.Length);
        context.UnmapSubresource(rightText2, 0);

        Texture2DDescription stereoDesc = new Texture2DDescription()
        {
            ArraySize = 1,
            Width = 3840,
            Height = 1081,
            BindFlags = BindFlags.None,
            CpuAccessFlags = CpuAccessFlags.Write,
            Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm,
            OptionFlags = ResourceOptionFlags.None,
            Usage = ResourceUsage.Staging,
            MipLevels = 1,
            SampleDescription = new SampleDescription(1, 0)
        };
        Texture2D stereoTexture = new Texture2D(device, stereoDesc);    // Texture2D to contain stereo images and Nvidia 3DVision Signature

        // Identify the source texture region to copy (all of it) 
        ResourceRegion stereoSrcBox = new ResourceRegion { Front = 0, Back = 1, Top = 0, Bottom = 1080, Left = 0, Right = 1920 };

        // Copy it to the stereo texture 
        context.CopySubresourceRegion(leftText2, 0, stereoSrcBox, stereoTexture, 0, 0, 0, 0);
        context.CopySubresourceRegion(rightText2, 0, stereoSrcBox, stereoTexture, 0, 1920, 0, 0);   // Offset by 1920 pixels

        // Open the staging texture for reading and go to last row
        DataBox box = context.MapSubresource(stereoTexture, 0, MapMode.Write, SlimDX.Direct3D11.MapFlags.None);
        box.Data.Seek(stereoTexture.Description.Width * (stereoTexture.Description.Height - 1) * 4, System.IO.SeekOrigin.Begin);
        box.Data.Write(stereo_data, 0, stereo_data.Length);            // Write the NVSTEREO header 
        context.UnmapSubresource(stereoTexture, 0);

        left2.Dispose();
        leftText2.Dispose();
        right2.Dispose();
        rightText2.Dispose();
        return stereoTexture;
    } 

}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Windows.Forms;
使用系统图;
使用系统、绘图、成像;
使用System.IO;
使用SlimDX;
使用SlimDX.Direct3D11;
使用SlimDX.Windows;
使用SlimDX.DXGI;
使用Device=SlimDX.Direct3D11.Device;//确保我们使用DX11
使用Resource=SlimDX.Direct3D11.Resource;
命名空间slimdxt2
{
静态类程序
{
专用静态设备设备;//DirectX11设备
private static int Count;//只是为了确保正在更新内容
//立体声标题。
静态字节[]立体声图像数据=新字节[]{0x4e,0x56,0x33,0x44,//NVSTEREO图像签名=0x4433564e;
0x00,0x0F,0x00,0x00,//屏幕宽度*2=1920*2=3840=0x00000F00;
0x38,0x04,0x00,0x00,//屏幕高度=1080=0x00000438;
0x20,0x00,0x00,0x00,//dwBPP=32=0x00000020;
0x02,0x00,0x00,0x00};//dwFlags=SIH\u SCALE\u TO\u FIT=0x00000002
[状态线程]
静态void Main()
{
位图left_im=新位图(“Blue.png”);//读入位图
位图右\u im=新位图(“Red.png”);
//设备创建
var form=newrenderform(“立体测试”){ClientSize=new Size(19201080)};
var desc=新SwapChainDescription()
{
BufferCount=1,
ModeDescription=新的ModeDescription(19201080,新的Rational(120,1),格式为.R8G8B8A8_UNorm),
IsWindowed=false,//true,
outputhHandle=form.Handle,
SampleDescription=新的SampleDescription(1,0),
SwapEffect=SwapEffect.丢弃,
用法=用法.RenderTargetOutput
};
SwapChain SwapChain;
Device.CreateWithSwapChain(DriverType.Hardware,DeviceCreationFlags.Debug,desc,out Device,out swapChain);
RenderTargetView renderTarget;//创建渲染目标的视图,它是我们刚刚创建的交换链的backbuffer
使用(var resource=resource.FromSwapChain(swapChain,0))
renderTarget=新的RenderTargetView(设备、资源);
var context=device.ImmediateContext;//设置视口
var viewport=新视口(0.0f,0.0f,form.ClientSize.Width,form.ClientSize.Height);
context.outputMerge.SetTargets(renderTarget);
context.Rasterizer.SetViewports(viewport);
//防止DXGI处理alt+enter,这在Winforms中无法正常工作
使用(var factory=swapChain.GetParent())
SetWindowAssociation(form.Handle,WindowAssociationFlags.IgnoreAll);
form.KeyDown+=(o,e)=>//handle alt+输入我们自己
{
if(e.Alt&&e.KeyCode==Keys.Enter)
swapChain.IsFullScreen=!swapChain.IsFullScreen;
};
form.KeyDown+=(o,e)=>//Alt+X->退出程序
{
if(e.Alt&&e.KeyCode==Keys.X)
{
form.Close();
}
};
context.ClearRenderTargetView(renderTarget,Color.Green);//用指定的颜色填充屏幕
Texture2DDescription stereoDesc=新的Texture2DDescription()
{
ArraySize=1,
宽度=3840,
高度=1081,
BindFlags=BindFlags.None,
CpuAccessFlags=CpuAccessFlags.Write,
Format=SlimDX.DXGI.Format.R8G8B8A8_UNorm,
OptionFlags=ResourceOptionFlags.None,
用法=ResourceUsage.Staging,
MIP级别=1,
SampleDescription=新的SampleDescription(1,0)
};
//主回路
MessagePump.Run(表单,()=>
{
Texture2D texture_stereo=Make3D(左\u im,右\u im);//从内存中的两个位图创建纹理
ResourceRegion立体rcbox=new ResourceRegion{Front=0,Back=1,Top=0,Bottom=1080,Left=0,Right=1920};
CopySubresourceRegion(纹理\立体,0,立体框,renderTarget.Resource,0,0,0);
纹理_立体声处理();
swapChain.Present(0,PresentFlags.None);
});
//配置资源
swapChain.IsFullScreen=false;//在处理swapChain之前需要
device.Dispose();
swapChain.Dispose();
renderTarget.Dispose();
}
静态纹理2D Make3D(位图leftBmp、位图rightBmp)
{
var context=device.ImmediateContext;
位图left2=leftBmp.Clone(新矩形f(0,0,leftBmp.Width,leftBmp.Height),PixelFormat.Format32bppArgb);//将bmp更改为32位ARGB
位图right2=righbmp.Clone(新矩形f(0,0,righbmp.Width,righbmp.Height),PixelFormat.Format32bppArgb);
//在屏幕上显示帧数:(要测试)
Graphics left_graph=Graphics.FromImage(left2);
左\u图形.抽绳(“帧:+Count.ToString(),新建
_________________________
|           |            |      
|  img1     |     img2   |
|           |            |
--------------------------
|_______signature________| where this last row = 1 pix tall
void RenderEye(bool rightEye, ITarget target)
{
    RenderTargetView currentTarget = rightEye ? target.RenderTargetViewRight : target.RenderTargetView;
    context.OutputMerger.SetTargets(target.DepthStencilView, currentTarget);
    [clean color/depth]
    [render scene]
    [repeat for each eye]
}