2012-07-24 146 views
3

我試圖使用Direct3D11來執行一些圖像扭曲非常快,根據this previous question,但似乎無法讓所有的東西一起工作。DirectX - 渲染四個WicBitmapRenderTarget(SharpDX)

當我嘗試將DXGI表面讀入Direct2D位圖時,出現故障。

var renderSurface = renderTexture.QueryInterface<SharpDX.DXGI.Surface>(); 
var props = new BitmapProperties 
       { 
        PixelFormat = new SharpDX.Direct2D1.PixelFormat(
         Format.B8G8R8A8_UNorm, 
         AlphaMode.Premultiplied 
        ) 
       }; 

// This throws "No such interface supported" 
var direct2DBitmap = 
    new SharpDX.Direct2D1.Bitmap(_bitmapRenderTarget, renderSurface, props); 

我也試圖讀取直接使用Map法在表面,但在此之前我甚至嘗試用數據做任何事情,失敗:

var renderSurface = renderTexture.QueryInterface<SharpDX.DXGI.Surface>(); 
// This throws "The parameter is incorrect." 
renderSurface.Map(MapFlags.Read); 

更完整的代碼如下。此外,如果這裏有什麼與這項工作無關的話......我全都是耳朵。我不是一個真正的3D人,只是想解決一個沒有簡單的Direct2D解決方案的特定問題。

public void AddImage(BitmapSource bitmapSource, SharpDX.Vector2[] abcd) 
{ 
    Device device; 
    Texture2D renderTexture = null; 
    device = new Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport); 
    renderTexture = new Texture2D(device, new Texture2DDescription 
    { 
     Width = _size.Width, 
     Height = _size.Height, 
     Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, 
     MipLevels = 1, 
     ArraySize = 1, 
     SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), 
     BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, 
     Usage = ResourceUsage.Default, 
    }); 
    var renderView = new RenderTargetView(device, renderTexture); 

    // 
    // Load the input bitmap as a texture 
    // 
    var texture = CreateTexture2DFromBitmap(device, bitmapSource); 
    var textureView = new ShaderResourceView(device, texture); 
    var sampler = new SamplerState(device, new SamplerStateDescription() 
    { 
     Filter = Filter.MinMagMipLinear, 
     AddressU = TextureAddressMode.Wrap, 
     AddressV = TextureAddressMode.Wrap, 
     AddressW = TextureAddressMode.Wrap, 
     BorderColor = Color.Black, 
     ComparisonFunction = Comparison.Never, 
     MaximumAnisotropy = 16, 
     MipLodBias = 0, 
     MinimumLod = 0, 
     MaximumLod = 16, 
    }); 

    // 
    // Setup the scene 
    // These shaders are from the MiniCubeTexture sample for SharpDX 
    // 
    var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCubeTexture.fx", "VS", "vs_4_0"); 
    var vertexShader = new VertexShader(device, vertexShaderByteCode); 
    var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniCubeTexture.fx", "PS", "ps_4_0"); 
    var pixelShader = new PixelShader(device, pixelShaderByteCode); 

    var layout = new InputLayout(device, ShaderSignature.GetInputSignature(vertexShaderByteCode), new[] { 
     new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32A32_Float, 0, 0), 
    new InputElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float, 16, 0), 
    }); 

    var vertices = SharpDX.Direct3D11.Buffer.Create(device, BindFlags.VertexBuffer, new[] { 
    // 3D coordinates    UV Texture coordinates 
     abcd[0].X, abcd[0].Y, 0.0f, 1.0f,  0.0f, 1.0f, // Front 
     abcd[1].X, abcd[1].Y, 0.0f, 1.0f,  0.0f, 0.0f, 
     abcd[2].X, abcd[2].Y, 0.0f, 1.0f,  1.0f, 0.0f, 
     abcd[3].X, abcd[3].Y, 0.0f, 1.0f,  0.0f, 1.0f, 
    }); 

    var contantBuffer = new SharpDX.Direct3D11.Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); 

    var context = device.ImmediateContext; 
    context.InputAssembler.InputLayout = layout; 
    context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip; 
    context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() + Utilities.SizeOf<Vector2>(), 0)); 
    context.VertexShader.SetConstantBuffer(0, contantBuffer); 
    context.VertexShader.Set(vertexShader); 
    context.Rasterizer.SetViewports(new Viewport(0, 0, _size.Width, _size.Height, 0.0f, 1.0f)); 
    context.PixelShader.Set(pixelShader); 
    context.PixelShader.SetSampler(0, sampler); 
    context.PixelShader.SetShaderResource(0, textureView); 
    context.OutputMerger.SetTargets(renderView); 

    // 
    // Render 3D 
    //   
    context.ClearRenderTargetView(renderView, Colors.Transparent); 
    var worldViewProj = Matrix.Identity;// Matrix.Translation (_size.Width, _size.Height/2, 0) * Matrix.Scaling (_size.Width/2, _size.Height/2, 1); 
    context.UpdateSubresource(ref worldViewProj, contantBuffer); 
    context.Draw(4, 0); 

    // 
    // Composite 
    // 

    //Create a render target 

    var renderSurface = renderTexture.QueryInterface<SharpDX.DXGI.Surface>(); 
    var props = new BitmapProperties 
        { 
         PixelFormat = new SharpDX.Direct2D1.PixelFormat(Format.B8G8R8A8_UNorm,AlphaMode.Premultiplied) 
        }; 

    var direct2DBitmap = new SharpDX.Direct2D1.Bitmap(_bitmapRenderTarget, renderSurface, props); 

    _wicRenderTarget.BeginDraw(); 
    _wicRenderTarget.DrawBitmap(direct2DBitmap, 1.0f, SharpDX.Direct2D1.BitmapInterpolationMode.Linear); 
    _wicRenderTarget.EndDraw(); 

    direct2DBitmap.Dispose(); 
} 

private static SharpDX.Direct3D11.Texture2D CreateTexture2DFromBitmap(SharpDX.Direct3D11.Device device, SharpDX.WIC.BitmapSource bitmapSource) 
{ 
    // Allocate DataStream to receive the WIC image pixels 
    int stride = bitmapSource.Size.Width * 4; 
    using (var buffer = new SharpDX.DataStream(bitmapSource.Size.Height * stride, true, true)) 
    { 
     // Copy the content of the WIC to the buffer 
     bitmapSource.CopyPixels(stride, buffer); 
     return new SharpDX.Direct3D11.Texture2D(device, new SharpDX.Direct3D11.Texture2DDescription() 
     { 
      Width = bitmapSource.Size.Width, 
      Height = bitmapSource.Size.Height, 
      ArraySize = 1, 
      BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource, 
      Usage = SharpDX.Direct3D11.ResourceUsage.Immutable, 
      CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None, 
      Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm, 
      MipLevels = 1, 
      OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None, 
      SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), 
     }, new SharpDX.DataRectangle(buffer.DataPointer, stride)); 
    } 
} 

回答

4

你應該能夠使用CreateSharedBitmap創建ID2D1Bitmap並在Direct2D中的場景使用。從SharpDX sources開始,看起來好像有多個重載的Bitmap構造函數調用CreateSharedBitmap。

另外通過DXGI here查看Direct2D和Direct3D之間的互操作文檔。

編輯:經過一番搜索,it looks like我上面提出的方法是not supported on Windows 7(僅適用於Windows 8)。

解決方法是here,但。

+0

謝謝。它看起來像我調用的構造函數是一個調用CreateSharedBitmap的構造函數,所以其他事情必須進行。 – roufamatic 2012-07-24 19:43:15

+0

請參閱我上面編輯的答案。 :) – Ani 2012-07-24 19:59:53

+0

阿格。與DX一起工作所需的大量咒語讓我驚歎不已。 – roufamatic 2012-07-24 20:17:58