Sign in to follow this  
dave09cbank

Rendered texture is transparent in DirectX11

Recommended Posts

dave09cbank    231

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.

Please note I am a newbie to Direct X.
 

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:

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.

Any help in this matter would be much appreciated.

Edited by dave09cbank

Share this post


Link to post
Share on other sites
Styves    1792

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

 

First thing I'd look at is this. You're returning a float3 (.rgb) but the return type for your PSMain function is float4. Is that actually compiling?

Edited by Styves

Share this post


Link to post
Share on other sites
dave09cbank    231

thanks for the reply. Styves.

That was a humble mistake on my part as it shouldnt have

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

as identified by yourself.
 

but rather it should be
 

float4 PSMain(VertexShaderOutput input) : SV_Target

{
    return ShaderTexture.Sample(Sampler, input.TextureUV);
}

I think i had posted an older version of the HLSL file by-mistake.
 

With the mentioned HLSL file code above, ouput is still the same as shown in the picture in the post above.

Edited by dave09cbank

Share this post


Link to post
Share on other sites
SeanMiddleditch    17565
This is why the fine folks at Microsoft invented graphics debuggers. You can use the one built into VS to step through your program and investigate exactly why a pixel in the output is a particular color.

My random guess is that you've just set up the wrong blend state for what you're trying to do. If you have an opaque movie you're rendering, disable blending. If you need to keep it on for some reason, make sure your blend equation is what you expect (it'll _usually_ be SrcAlpha*(1-SrcAlpha) but it sounds like you might have it set to something using DstAlpha) and that your alpha channels are what you expect (if you have an opaque image, your alpha channel should be 1.0). You can inspect all this easily in your graphics debugger.

Share this post


Link to post
Share on other sites
dave09cbank    231

Thanks Sean for the reply.

i am still trying to get myself familiar with the graphics debugger.

However, i am not setting the blend state at all manually but will check things again specially via graphics debuggers.

Share this post


Link to post
Share on other sites
dave09cbank    231

Now as recommended by Sean to try the graphics debugger in Visual Studio, which doesn't seem to be working for me.
Reason being
1. the capture of frame doesn't finish
2. i do not see any option to select the frame analysis window or pixel history or any other options that usually are select-able for graphics debugging.

I am using VS2015 Enterprise, on windows 7.

Any help in regards would be great in order to progress further and debug my original issue stated at the top.

Thanks.

Share this post


Link to post
Share on other sites
dave09cbank    231

I have finally figured it out. the pixel data received contains alpha channel value to be zero hence it is transparent.  

I have overcame this by updating the alpha channel value to 255.

This has been done either in the pixel shader or within my decoder.

hope this helps some one else.

Thanks .

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this