0

A game uses software rendering to draw a full-screen paletted (8-bit) image in memory.

What's the fastest way to put that image on the screen, using Direct3D?

Currently I convert the paletted image to RGB in software, then put it on a D3DUSAGE_DYNAMIC texture (which is locked with D3DLOCK_DISCARD).

Is there a faster way? E.g. using shaders to perform palettization?

Related questions:

Community
  • 1
  • 1
Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114

2 Answers2

4

Create a D3DFMT_L8 texture containing the paletted image, and an 256x1 D3DFMT_X8R8G8B8 image containing the palette.

HLSL shader code:

uniform sampler2D image;
uniform sampler1D palette;

float4 main(in float2 coord:TEXCOORD) : COLOR
{
    return tex1D(palette, tex2D(image, coord).r * (255./256) + (0.5/256));
}

Note that the luminance (palette index) is adjusted with a multiply-add operation. This is necessary, as palette index 255 is considered as white (maximum luminance), which becomes 1.0f when represented as a float. Reading the palette texture at that coordinate causes it to wrap around (as only the fractionary part is used) and read the first palette entry instead.

Compile it with:

fxc /Tps_2_0 PaletteShader.hlsl /FhPaletteShader.h

Use it like this:

// ... create and populate texture and paletteTexture objects ...
d3dDevice->CreatePixelShader((DWORD*)g_ps20_main, &shader)
// ...
d3dDevice->SetTexture(1, paletteTexture);
d3dDevice->SetPixelShader(shader);
// ... draw texture to screen as textured quad as usual ...
Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114
1

You could write a simple pixel shader to handle the palettization. Create an L8 dynamic texture and copy your paletteized image to it and create a palette lookup texture (or an array of colors in constant memory). Then just render a fullscreen quad with the palettized image set as a texture and a pixel shader that performs the palette lookup from the lookup texture or constant buffer.

That said, performing the palette conversion on the CPU shouldn't be very expensive on a modern CPU. Are you sure that is your performance bottleneck?

mattnewport
  • 13,728
  • 2
  • 35
  • 39
  • Yes, I'm sure. CPU usage increases dramatically in 32-bit DirectDraw vs. 8-bit paletted DirectDraw. I'm looking into shaders right now, thanks (trying to figure out how to bind the palette texture to the sampler uniform variable). – Vladimir Panteleev Oct 30 '12 at 21:36
  • Since the palette is only 256 entries and you don't need to take advantage of texture blending or anything you could just use a constant buffer for your palette entries which would be a bit simpler on the shader / binding side than using a texture (assuming D3D11). – mattnewport Oct 30 '12 at 21:59
  • I just noticed that you're using D3D9, you should still be able to use constants for the palette lookup I think but there are restrictions on indexed constant look ups in pixel shaders in D3D9 as I remember so a palette texture is probably the way to go. – mattnewport Oct 30 '12 at 22:06
  • Thanks, figured everything out (see my answer below). – Vladimir Panteleev Oct 30 '12 at 23:51