Lookup table using pixel shader

Started by
4 comments, last by Alex F 16 years, 1 month ago
Is it possible to write pixel shader which converts texture image using Lookup table? Pseudo-code is: unsigned char LUT[256]; for each pixel in image pixel = LUT[pixel]; Image is 8 bpp monochrome. Inside of pixel shader it looks like ARGB image with equal R,G and B components. Is it possible to write such shader, load LUT to it programmatically, and execute it?
Advertisement
Yes. The easiest option is to put the LUT in another texture. Make sure you use point sampling for both textures and it should be straight forward to do.
Here's an HLSL shader I wrote for 8-bit paletted images. The textures are stored in monochrome L8 format. The palette texture is 256x1 in size.

float4x4 WorldViewProj	: WORLDVIEWPROJ;Texture ColorTexture;sampler ColorTextureSampler = sampler_state { texture = <ColorTexture> ; magfilter = NONE; minfilter = NONE; mipfilter = NONE; AddressU = wrap; AddressV = wrap; };Texture PaletteTexture;sampler PaletteTextureSampler = sampler_state { texture = <PaletteTexture> ; magfilter = NONE; minfilter = NONE; mipfilter = NONE; AddressU = wrap; AddressV = wrap; };struct a2v{	float4 Position   	: POSITION0;	float2 TexCoords  	: TEXCOORD0;};struct v2p{	float4 Position		: POSITION0;	float2 TexCoords   	: TEXCOORD0;};struct p2f{    float4 Color 		: COLOR0;};void vs( in a2v IN, out v2p OUT ){	OUT.Position = mul( IN.Position, WorldViewProj );	OUT.TexCoords = IN.TexCoords;}void ps( in v2p IN, out p2f OUT ){	float4 TextureColor = tex2D( ColorTextureSampler, IN.TexCoords );	OUT.Color = tex1D( PaletteTextureSampler, TextureColor.r );}technique PaletteTechnique{    pass p0    {        vertexshader = compile vs_1_1 vs();	pixelshader = compile ps_1_4 ps();    }}
One thing to watch out for doing a pixel shader based palettized texture like this is that texture filtering won't work correctly. You'll either need to live with texture filtering turned off (as in Scet's example) or implement the filtering manually yourself in the shader. You will also have to write custom code to generate your mipmap chain as standard mipmapping won't work correclty either.

The reason that filtering and mipmapping don't work with palettized textures is that the lerp of two palette indices doesn't generally equate to the index of the lerp of the two colours, unless your palette happens to be a linear ramp.

Game Programming Blog: www.mattnewport.com/blog

Thank you very much, two textures and function ps( in v2p IN, out p2f OUT ) did the trick.
Hello. I found interesting bug in this code: pixel with value 255 is always mapped to 0. All other pixel values are OK. After playing some time with shader text I found the version which works correctly:

void ps( in v2p IN, out p2f OUT )
{
float4 TextureColor = tex2D( ColorTextureSampler, IN.TexCoords );
float f = TextureColor.r;

if ( f == 1.0 )
{
f = 0.999;
}

OUT.Color = tex1D( PaletteTextureSampler, f );
}

It looks like avoiding 1.0 value solved the problem. Maybe there is more elegant solution? Thank you.

This topic is closed to new replies.

Advertisement