Rendered texture is transparent in DirectX 11

2019-08-27 21:34发布

问题:

I am rendering H264 video frames from an IP camera which are decoded into BGRA32 pixel format via DirectX 11 and SharpDx in WPF via D3DImage control.

After lot of research and looking at various samples and examples I have managed to get it finally got it to render H264 frames with DirectX 11

My current setup involves setting setting up vertex shader and pixel shader as below:

var device = this.Device;
var context = device.ImmediateContext;

// Compile Vertex and Pixel shaders
vertexShaderByteCode = ShaderBytecode.CompileFromFile("TriangleShader.fx", "VSMain", "vs_5_0", ShaderFlags.Debug, EffectFlags.None);
vertexShader = new VertexShader(device, vertexShaderByteCode);
pixelShaderByteCode = ShaderBytecode.CompileFromFile("TriangleShader.fx", "PSMain", "ps_5_0", ShaderFlags.Debug, EffectFlags.None);
pixelShader = new PixelShader(device, pixelShaderByteCode);

// Layout from VertexShader input signature
// An input layout is the layout of the data containing the location and properties of a vertex. It would be a format of data that you can modify and set according
layout = new InputLayout(device, ShaderSignature.GetInputSignature(vertexShaderByteCode), new[] {
          new InputElement("SV_Position", 0, Format.R32G32B32A32_Float, 0, 0),
          new InputElement("COLOR", 0, Format.R32G32_Float, 16, 0),
          new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0),
        });

// Write vertex data to a datastream
var stream = new DataStream(Utilities.SizeOf<Vertex>() * 6, true, true);

int iWidth = (int)this.ActualWidth;
int iHeight = (int)this.ActualHeight;

float top = iWidth / 2;
float bottom = iHeight / 2;

stream.WriteRange(new[]
                             {
   new Vertex(
               new Vector4(-top, bottom, 0.5f, 0.0f), // position top-center
               new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color top-center (r,g,b,alpha)
               new Vector2(0f,0f)),
    new Vertex(
               new Vector4(top, bottom, 0.5f, 0.0f), // position top-right
               new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color top-right (r,g,b,alpha)
               new Vector2(iWidth,iHeight)),
    new Vertex(
               new Vector4(-top, -bottom, 0.5f, 0.0f), // position bottom-left
               new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color bottom-left (r,g,b,alpha)
               new Vector2(iWidth,iHeight)),
    new Vertex( 
                new Vector4(-top, -bottom, 0.5f, 0.0f), // position bottom-right
                new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color bottom-left (r,g,b,alpha)
                new Vector2(iWidth,0f)),
        new Vertex(
                new Vector4(top, -bottom, 0.5f, 0.0f), // position bottom-right
                new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color bottom-right (r,g,b,alpha)
                new Vector2(iWidth,iHeight)),
        new Vertex(
                new Vector4(top, bottom, 0.5f, 0.0f), // position top-right
                new Color4(0.0f, 0.0f, 0.0f, 0.0f), // color top-right (r,g,b,alpha)
                new Vector2(0f, iHeight)),
        });

        stream.Position = 0;

        // Instantiate Vertex buiffer from vertex data
        // 
        vertices = new SharpDX.Direct3D11.Buffer(device, stream, new BufferDescription()
        {
            BindFlags = BindFlags.VertexBuffer,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.None,
            SizeInBytes = Utilities.SizeOf<Vertex>() * 6,
            Usage = ResourceUsage.Default,
            StructureByteStride = 0
        });
        stream.Dispose();

        // Prepare All the stages
        context.InputAssembler.InputLayout = (layout);
        context.InputAssembler.PrimitiveTopology = (PrimitiveTopology.TriangleStrip);
        context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vertex>(), 0));
        context.VertexShader.Set(vertexShader);
        context.PixelShader.Set(pixelShader);
        context.OutputMerger.SetTargets(m_RenderTargetView);

When ever i receive a new frame then I update the RenderTexture by mapping the resource as below:

device.ImmediateContext.ClearRenderTargetView(this.m_RenderTargetView, Color4.Black);

        Texture2DDescription colordesc = new Texture2DDescription
        {
            BindFlags = BindFlags.ShaderResource,
            Format = m_PixelFormat,
            Width = iWidth,
            Height = iHeight,
            MipLevels = 1,
            SampleDescription = new SampleDescription(1, 0),
            Usage = ResourceUsage.Dynamic,
            OptionFlags = ResourceOptionFlags.None,
            CpuAccessFlags = CpuAccessFlags.Write,
            ArraySize = 1
        };

        Texture2D newFrameTexture = new Texture2D(this.Device, colordesc);

        DataStream dtStream = null;
        DataBox dBox = Device.ImmediateContext.MapSubresource(newFrameTexture, 0, MapMode.WriteDiscard, 0, out dtStream);
        if (dtStream != null)
        {
            int iRowPitch = dBox.RowPitch;

            for (int iHeightIndex = 0; iHeightIndex < iHeight; iHeightIndex++)
            {
                //Copy the image bytes to Texture
                // we write row strides multiplies by bytes per pixel
                // as our case is bgra32 which is 4 bytes 
                dtStream.Position = iHeightIndex * iRowPitch;
                Marshal.Copy(decodedData, iHeightIndex * iWidth * 4, new IntPtr(dtStream.DataPointer.ToInt64() + iHeightIndex * iRowPitch), iWidth * 4);
            }
        }

        Device.ImmediateContext.UnmapSubresource(newFrameTexture, 0);

        Texture2D srcTexture = m_RenderTargetView.ResourceAs<Texture2D>();
        Device.ImmediateContext.CopySubresourceRegion(newFrameTexture, 0, null, this.RenderTarget, 0);

        Device.ImmediateContext.Draw(6, 0);
        Device.ImmediateContext.Flush();
        this.D3DSurface.InvalidateD3DImage();

        Disposer.SafeDispose(ref newFrameTexture);

My Effects/HLSL file:

Texture2D ShaderTexture : register(t0);
SamplerState Sampler : register(s0);

cbuffer PerObject: register(b0)
{
    float4x4 WorldViewProj;
};
struct VertexShaderInput
{
    float4 Position : SV_Position;
    float4 Color : COLOR;
    float2 TextureUV : TEXCOORD0;
};
struct VertexShaderOutput
{
    float4 Position : SV_Position;
    float4 Color : COLOR;
    float2 TextureUV : TEXCOORD0;
};

VertexShaderOutput VSMain(VertexShaderInput input)
{
    VertexShaderOutput output = (VertexShaderOutput)0;

output.Position = mul(input.Position, WorldViewProj);
output.Color = mul(input.Color, WorldViewProj);
output.TextureUV = input.TextureUV;

return output;
}

float4 PSMain(VertexShaderOutput input) : SV_Target
{
    return ShaderTexture.Sample(Sampler, input.TextureUV).rgb;
}

Images are rendered correctly but it seem they are opaque if the background color of the parent color is anything other than black.

Now i can't seem to figure out what exactly is going on here which is rendering my texture as transparent.

I have also tried to render when the parent grid control has its background as a picture of a koala as shown below:

Any help in this matter would be much appreciated.