NV_STEREO_IMAGE_SIGNATURE and DirectX 10/11 (nVidia 3D Visio

本文关键字:nVidia 3D Visio DirectX IMAGE STEREO SIGNATURE and NV | 更新日期: 2023-09-27 18:08:08

我试图使用SlimDX和DirectX10或11来控制nVidia 3D Vision Kit上的立体化过程。由于这个问题,我已经能够使它在DirectX 9中工作。然而,由于一些缺失的方法,我一直无法使它在DirectX 10或11下工作。

算法是这样的:

  1. 渲染左眼图像
  2. 渲染右眼图像
  3. 创建一个能够包含它们的纹理加上一个额外的行(所以纹理大小将是2 *宽度,高度+ 1)
  4. 写入NV_STEREO_IMAGE_SIGNATURE值
  5. 在屏幕上渲染这个纹理
我的测试代码跳过了前两个步骤,因为我已经有了一个立体纹理。这是一个以前的。jps文件,特别是那些包含在nvidia 3D套件附带的示例图片之一。步骤5使用全屏四边形和着色器通过正交投影矩阵将立体纹理渲染到其上。我看到的DX9示例代码不需要这个,只是调用StretchRect(…)方法将纹理复制回backbuffer。所以也许是这个原因导致了它不起作用?在DX10中是否有类似的方法来完成此操作?我认为渲染到反缓冲理论上会是相同的复制(或StretchRecting)纹理到它,但也许它不是?下面是我的代码(slimdx):Stereoization过程
static Texture2D Make3D(Texture2D stereoTexture)
{
// stereoTexture contains a stereo image with the left eye image on the left half 
// and the right eye image on the right half
// this staging texture will have an extra row to contain the stereo signature
Texture2DDescription stagingDesc = 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 staging = new Texture2D(device, stagingDesc);
// 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 = 3840 };
// Copy it to the staging texture
device.CopySubresourceRegion(stereoTexture, 0, stereoSrcBox, staging, 0, 0, 0, 0);
// Open the staging texture for reading
DataRectangle box = staging.Map(0, MapMode.Write, SlimDX.Direct3D10.MapFlags.None);
// Go to the last row
box.Data.Seek(stereoTexture.Description.Width * stereoTexture.Description.Height * 4, System.IO.SeekOrigin.Begin);
// Write the NVSTEREO header
box.Data.Write(data, 0, data.Length);
staging.Unmap(0);
// Create the final stereoized texture
Texture2DDescription finalDesc = new Texture2DDescription()
{
    ArraySize = 1,
    Width = 3840,
    Height = 1081,
    BindFlags = BindFlags.ShaderResource,
    CpuAccessFlags = CpuAccessFlags.Write,
    Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm,
    OptionFlags = ResourceOptionFlags.None,
    Usage = ResourceUsage.Dynamic,
    MipLevels = 1,
    SampleDescription = new SampleDescription(1, 0)
};
// Copy the staging texture on a new texture to be used as a shader resource
Texture2D final = new Texture2D(device, finalDesc);
device.CopyResource(staging, final);
staging.Dispose();
return final;
}

NV_STEREO_IMAGE_SIGNATURE数据
// The NVSTEREO header.
    static 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
主要

private static Device device;
[STAThread]
static void Main()
{
// 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 = true,
                   OutputHandle = form.Handle,
                   SampleDescription = new SampleDescription(1, 0),
                   SwapEffect = SwapEffect.Discard,
                   Usage = Usage.RenderTargetOutput
               };
SwapChain swapChain;
Device.CreateWithSwapChain(null, DriverType.Hardware, DeviceCreationFlags.Debug, desc, out device, out swapChain);
//Stops Alt+enter from causing fullscreen skrewiness.
Factory factory = swapChain.GetParent<Factory>();
factory.SetWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);
Texture2D backBuffer = Resource.FromSwapChain<Texture2D>(swapChain, 0);
RenderTargetView renderView = new RenderTargetView(device, backBuffer);
ImageLoadInformation info = new ImageLoadInformation()
                                {
                                    BindFlags = BindFlags.None,
                                    CpuAccessFlags = CpuAccessFlags.Read,
                                    FilterFlags = FilterFlags.None,
                                    Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm,
                                    MipFilterFlags = FilterFlags.None,
                                    OptionFlags = ResourceOptionFlags.None,
                                    Usage = ResourceUsage.Staging,
                                    MipLevels = 1
                                };
// Make texture 3D
Texture2D sourceTexture = Texture2D.FromFile(device, "medusa.jpg", info);
Texture2D stereoizedTexture = Make3D(sourceTexture);
ShaderResourceView srv = new ShaderResourceView(device, stereoizedTexture);
// Create a quad that fills the whole screen
ushort[] idx;
TexturedVertex[] quad = CreateTexturedQuad(Vector3.Zero, 1920, 1080, out idx);
// fill vertex and index buffers
DataStream stream = new DataStream(4*24, true, true);
stream.WriteRange(quad);
stream.Position = 0;
Buffer vertices = new SlimDX.Direct3D10.Buffer(device, stream, new BufferDescription()
                                                                   {
                                                                       BindFlags = BindFlags.VertexBuffer,
                                                                       CpuAccessFlags = CpuAccessFlags.None,
                                                                       OptionFlags = ResourceOptionFlags.None,
                                                                       SizeInBytes = 4*24,
                                                                       Usage = ResourceUsage.Default
                                                                   });
stream.Close();
stream = new DataStream(6*sizeof (ushort), true, true);
stream.WriteRange(idx);
stream.Position = 0;
Buffer indices = new SlimDX.Direct3D10.Buffer(device, stream, new BufferDescription()
                                                                  {
                                                                      BindFlags = BindFlags.IndexBuffer,
                                                                      CpuAccessFlags = CpuAccessFlags.None,
                                                                      OptionFlags = ResourceOptionFlags.None,
                                                                      SizeInBytes = 6*sizeof (ushort),
                                                                      Usage = ResourceUsage.Default
                                                                  });
// Create world view (ortho) projection matrices
QuaternionCam qCam = new QuaternionCam();
// Load effect from file. It is a basic effect that renders a full screen quad through 
// an ortho projectio=n matrix
Effect effect = Effect.FromFile(device, "Texture.fx", "fx_4_0", ShaderFlags.Debug, EffectFlags.None);
EffectTechnique technique = effect.GetTechniqueByIndex(0);
EffectPass pass = technique.GetPassByIndex(0);
InputLayout layout = new InputLayout(device, pass.Description.Signature, new[]
                                                                             {
                                                                                 new InputElement("POSITION", 0,
                                                                                                  Format.
                                                                                                      R32G32B32A32_Float,
                                                                                                  0, 0),
                                                                                 new InputElement("TEXCOORD", 0,
                                                                                                  Format.
                                                                                                      R32G32_Float,
                                                                                                  16, 0)
                                                                             });
effect.GetVariableByName("mWorld").AsMatrix().SetMatrix(
    Matrix.Translation(Layout.OrthographicTransform(Vector2.Zero, 90, new Size(1920, 1080))));
effect.GetVariableByName("mView").AsMatrix().SetMatrix(qCam.View);
effect.GetVariableByName("mProjection").AsMatrix().SetMatrix(qCam.OrthoProjection);
effect.GetVariableByName("tDiffuse").AsResource().SetResource(srv);
// Set RT and Viewports
device.OutputMerger.SetTargets(renderView);
device.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
// Create solid rasterizer state
RasterizerStateDescription rDesc = new RasterizerStateDescription()
                                       {
                                           CullMode = CullMode.None,
                                           IsDepthClipEnabled = true,
                                           FillMode = FillMode.Solid,
                                           IsAntialiasedLineEnabled = true,
                                           IsFrontCounterclockwise = true,
                                           IsMultisampleEnabled = true
                                       };
RasterizerState rState = RasterizerState.FromDescription(device, rDesc);
device.Rasterizer.State = rState;
// Main Loop
MessagePump.Run(form, () =>
    {
        device.ClearRenderTargetView(renderView, Color.Cyan);
        device.InputAssembler.SetInputLayout(layout);
        device.InputAssembler.SetPrimitiveTopology(PrimitiveTopology.TriangleList);
        device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, 24, 0));
        device.InputAssembler.SetIndexBuffer(indices, Format.R16_UInt, 0);
        for (int i = 0; i < technique.Description.PassCount; ++i)
        {
            // Render the full screen quad
            pass.Apply();
            device.DrawIndexed(6, 0, 0);
        }
        swapChain.Present(0, PresentFlags.None);
    });
// Dispose resources
vertices.Dispose();
layout.Dispose();
effect.Dispose();
renderView.Dispose();
backBuffer.Dispose();
device.Dispose();
swapChain.Dispose();
rState.Dispose();
stereoizedTexture.Dispose();
sourceTexture.Dispose();
indices.Dispose();
srv.Dispose();
}[/code]

提前感谢!

NV_STEREO_IMAGE_SIGNATURE and DirectX 10/11 (nVidia 3D Visio

我最终设法修复了它。关键在于使用CopySubResourceRegion方法将立体纹理返回到backbuffer,指定其尺寸(例如:1920 x 1080而不是3840 x 1081)。