5

I have currently the problem that a library creates a DX11 texture with BGRA pixel format. But the displaying library can only display RGBA correctly. (This means the colors are swapped in the rendered image)

After looking around I found a simple for-loop to solve the problem, but the performance is not very good and scales bad with higher resolutions. I'm new to DirectX and maybe I just missed a simple function to do the converting.

// Get the image data
unsigned char* pDest = view->image->getPixels();

// Prepare source texture
ID3D11Texture2D* pTexture = static_cast<ID3D11Texture2D*>( tex );

// Get context
ID3D11DeviceContext* pContext = NULL;
dxDevice11->GetImmediateContext(&pContext);

// Copy data, fast operation
pContext->CopySubresourceRegion(texStaging, 0, 0, 0, 0, tex, 0, nullptr);

// Create mapping 
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( texStaging, 0, D3D11_MAP_READ, 0, &mapped );

if ( FAILED( hr ) )
{
    return;
}

// Calculate size
const size_t size = _width * _height * 4;

// Access pixel data
unsigned char* pSrc = static_cast<unsigned char*>( mapped.pData );

// Offsets
int offsetSrc = 0;
int offsetDst = 0;
int rowOffset = mapped.RowPitch % _width;

// Loop through it, BRGA to RGBA conversation
for (int row = 0; row < _height; ++row)
{
    for (int col = 0; col < _width; ++col)
    {
        pDest[offsetDst] = pSrc[offsetSrc+2];
        pDest[offsetDst+1] = pSrc[offsetSrc+1];
        pDest[offsetDst+2] = pSrc[offsetSrc];
        pDest[offsetDst+3] = pSrc[offsetSrc+3];

        offsetSrc += 4;
        offsetDst += 4;
    }

    // Adjuste offset
    offsetSrc += rowOffset;
}

// Unmap texture
pContext->Unmap( texStaging, 0 );

Solution:

    Texture2D txDiffuse : register(t0);
SamplerState texSampler : register(s0);

struct VSScreenQuadOutput
{
float4 Position : SV_POSITION;
float2 TexCoords0 : TEXCOORD0;
};

float4 PSMain(VSScreenQuadOutput input) : SV_Target
{
return txDiffuse.Sample(texSampler, input.TexCoords0).rgba;
}
MAGYS
  • 181
  • 1
  • 14
  • What is the "displaying library" that you're using? Any half-decent DX11 rendering library should be able to handle both BGRA and RGBA formats correctly (along with BC1, BC7, etc.). – MooseBoys Jun 11 '14 at 05:07
  • It's a 3D engine and why ever some formats are not supported. Because of this I try to find a workaround. – MAGYS Jun 11 '14 at 07:33

1 Answers1

4

Obviously iterating over a texture on you CPU is not the most effective way. If you know that colors in a texture are always swapped like that and you don't want to modify the texture itself in your C++ code, the most straightforward way would be to do it in the pixel shader. When you sample the texture, simply swap colors there. You won't even notice any performance drop.

Elvithari
  • 834
  • 1
  • 8
  • 13
  • Hello! Thanks a lot for the help! Do you have a sample code? I got through my DX11 bible but found nothing. Too I can't find anything related to swapping colors with pixel shaders elsewhere. – MAGYS Jun 10 '14 at 20:44
  • Ok, I'll assume that you're using HLSL. In your pixel shader code you should have a place where you read a texture. I belive it will look more or less like that: "float4 finalColor=myTexture.Sample(colorSampler, uv);" so yo need to swap color in the finalColor vector. Just to something like: finalColor = float4(finalColor.g,finalColor.b,finalColor.r,finalColor.a); – Elvithari Jun 10 '14 at 20:52
  • Hello! I'm still reading tutorials for applying a pixel shader. I will post the result here once I'm able to understand the topic correctly. (There are not very much tutorials in the wild) – MAGYS Jun 16 '14 at 12:26