2012-06-30 23 views
13

Ngày tốt, Tôi đang cố gắng hiển thị video stereo thời gian thực bằng cách sử dụng nVidia 3DVision và hai camera IP. Tôi hoàn toàn mới với DirectX, nhưng đã cố gắng làm việc thông qua một số hướng dẫn và các câu hỏi khác về điều này và các trang web khác. Hiện tại, tôi đang hiển thị hai bitmap tĩnh cho mắt trái và phải. Chúng sẽ được thay thế bằng bitmap từ máy ảnh của tôi khi tôi đã nhận được phần này của chương trình làm việc. Câu hỏi này NV_STEREO_IMAGE_SIGNATURE and DirectX 10/11 (nVidia 3D Vision) đã giúp tôi khá nhiều, nhưng tôi vẫn đang đấu tranh để làm cho chương trình của tôi hoạt động như mong muốn. Những gì tôi thấy là kính cửa trập của tôi bắt đầu hoạt động như mong muốn, nhưng chỉ hình ảnh cho mắt phải được hiển thị, trong khi mắt trái vẫn trống (trừ con trỏ chuột).Nvidia 3d Video sử dụng DirectX11 và SlimDX trong C#

Đây là mã của tôi để tạo ra những hình ảnh âm thanh stereo:

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; 
    } 

} 

}

Tôi đã thử phương pháp khác nhau sao chép Texture2D của hình ảnh stereo bao gồm chữ ký (3840x1081) cho backbuffer, nhưng không ai của các phương pháp tôi đã thử hiển thị cả hai hình ảnh ... Bất kỳ trợ giúp hoặc nhận xét nào sẽ được đánh giá cao, Ryan

+0

Tôi đã thử quay lại Direct3D 9 (để tôi có thể sử dụng stretchrect), nhưng bây giờ tôi gặp sự cố khi chạy chương trình ở chế độ toàn màn hình. Ngay sau khi tôi đặt presentparams.Windowed = false, chương trình bị treo khi tôi tạo swapchain của mình. Tôi nhận được lỗi sau: D3DERR_INVALIDCALL (-2005530516). Nếu nó giúp gì cả, tôi đang sử dụng máy tính xách tay Dell XPS17 với bộ phát 3D tích hợp ... –

+0

Ok, vì vậy tôi đã quản lý để làm cho nó hoạt động bằng cách sử dụng SlimDX và Direct3D 9. Tôi chỉ tạo một thiết bị bằng cách sử dụng presentparams của tôi, và không tạo ra một swapchain (mà gây ra chương trình của tôi sụp đổ khi cố gắng để khởi động ở chế độ toàn màn hình). Tôi nghĩ rằng một swapchain được yêu cầu khi tạo một thiết bị, nhưng có vẻ như không. Để bây giờ, tôi sẽ dính vào Direct3D 9 và nhận phần còn lại của chương trình của tôi làm việc (kết nối hai máy ảnh và nhận được tất cả mọi thứ đồng bộ, vv). Nó vẫn sẽ được tốt đẹp để có được nó làm việc trong Direct3D11, nhưng điều đó sẽ phải chờ đợi. –

+0

Trong vòng lặp chính bạn có ResourceRegion Bottom = 1080 và Right = 1920 không nên có quyền = 1920 * 2? –

Trả lời

0

Thử tạo backbufer có chiều rộng = 1920 và không 3840. kéo giãn từng hình ảnh thành một nửa chiều rộng và đặt chúng cạnh nhau.

+0

Cảm ơn lời khuyên. Như tôi đã đề cập trong các ý kiến ​​ở trên, tôi đã làm việc với D3D 9. Backbuffer của tôi được thiết lập với width = 1920, nhưng vấn đề tôi có là không có hàm tương đương với StretchRectangle() trong D3D 10 và 11. Làm thế nào để bạn kéo dài hình ảnh rộng 3840 pixel xuống đến độ rộng 1920 pixel, không có StretchRectangle()? Tôi đã thử bằng cách sử dụng CopySubResourceRegion(), nhưng chỉ kích thước nguồn có thể được xác định và tôi không làm cho nó hoạt động ... –

0

Tôi nhớ đã thấy chính xác câu hỏi này khi tìm kiếm cách đây vài ngày trên diễn đàn Nvidia Developer. Thật không may các diễn đàn là xuống do một cuộc tấn công của hacker gần đây. Tôi nhớ rằng các OP trên thread đó đã có thể làm cho nó làm việc với DX11 và Slimdx bằng cách sử dụng hack chữ ký. Bạn không sử dụng phương thức stretchRectangle, nó giống như createResuroseRegion() hoặc không chính xác mà tôi không thể nhớ được. Nó có thể là những phương thức CopyResource() hoặc CopySubresourceRegion() được tìm thấy trong luồng tương tự này trên stack overflow. Copy Texture to Texture

0

Bạn cũng có thể kết xuất hình ảnh liên tục hoặc ít nhất một vài lần không? Tôi đã làm điều tương tự trong DX9 và đã phải nói với DX để render 3 khung hình trước khi trình điều khiển nhận ra nó là tầm nhìn 3D. Kính của bạn có bật không? Là backbuffer = của bạn (chiều rộng * 2), (Chiều cao + 1) và được bạn viết backbuffer như vậy:

_________________________ 
|   |   |  
| img1  |  img2 | 
|   |   | 
-------------------------- 
|_______signature________| where this last row = 1 pix tall 
+0

Xin chào. Có, tôi đang hiển thị liên tục. Như tôi đã đề cập trong các ý kiến ​​của tôi ở trên tôi đã nhận nó làm việc với DX9. Bây giờ tôi cũng có hai camera chạy và nó hoạt động rất tốt. Bộ đệm trung gian tôi làm việc giống như bạn mô tả ở trên, nhưng backbuffer mà tôi viết bằng cách sử dụng StretchRectangle() chỉ là 1920x1080, và không gấp đôi chiều rộng và chiều cao + 1. Tôi nghĩ rằng trình điều khiển nvidia phát hiện nó ngay lập tức, nhưng phải mất một lúc cho máy phát hồng ngoại bật và kính bắt đầu hoạt động. Tôi sẽ không làm phiền thêm ở giai đoạn này để thử làm cho nó hoạt động trong DX11. –

1

Nếu sử dụng DirectX11.1 là một lựa chọn, có một cách dễ dàng hơn nhiều để cho phép các tính năng nổi , mà không cần phải dựa vào thuật sĩ byte của nVidia. Về cơ bản, bạn tạo một SwapChan1 thay vì SwapChain thông thường, sau đó nó đơn giản như thiết lập Stereo thành True.

Hãy xem post Tôi đã thực hiện, nó cho bạn thấy cách tạo một Hoán đổi âm thanh nổi. Mã này là một porting đến C# của mẫu stereo của MS. Sau đó, bạn sẽ có hai mục tiêu render và nó đơn giản hơn nhiều. Trước khi render bạn phải:

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] 
} 

nơi ITarget là một giao diện cho một lớp học cung cấp quyền truy cập vào các backbuffer, rendertargets vv Vậy đó, DirectX sẽ chăm sóc tất cả mọi thứ. Hi vọng điêu nay co ich.

Các vấn đề liên quan