Rendered texture is transparent in DirectX11

Started by
7 comments, last by dave09cbank 8 years, 5 months ago

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.

Advertisement

I'm not sure I entirely understand what the problem is. Perhaps a screenshot would help?

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Hi ajmiles,

I have uploaded the image which identifies shows the issue.

Hope it will give you an idea about my problem.

[attachment=29375:Rendered_Texture.JPG]


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?

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.

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.

Sean Middleditch – Game Systems Engineer – Join my team!

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.

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.

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 .

This topic is closed to new replies.

Advertisement