I've literally just today entered the wonderful world of pixel shaders, with the wish of making a specific palette shader for a game I'm working on.
I'm planning on making the game with the a slightly altered NES palette, and I've looked at some other Palette shaders to see how it would be done (and to see how HLSL generally worked).
The game would run at a very low resolution (similar resolution to the NES, albeit with a different aspect ratio), and I'd then scale it up after everything else in the shader.
Every single tile and sprite will already be fixed to this NES palette, therefore I don't need this shader to make other colors into the nearest colors in the palette.
I'm not going to use any form of half-transparency or ink effects (only pixels that are pure pink, or 255, 0, 255 in RGB, will be fully transparent)
I wanted the shader to find which index the color (of the current pixel) has in the palette, where the pixel's color (index) then would be shifted in the palette by a given offset value (primarily in the Y dimension)
This would allow me to make everything 1 level (or more) darker or lighter, I'd then save an X offset for something like a constant shifting rainbow effect if that was needed, either that or lock the entire X dimension to a single column of colors, so everything could be in greyscale (or even GameBoy-like green colors).
I've written an experimental shader that should be able to do the Y Offset part (that would also make sure that any colors above or below the palette-spectrum would reset to the limits).
sampler2D img; // Input screen (per pixel)
sampler2D Palette: register(s1); // Palette
float Xoffset; // X offset value, currently unused
float Yoffset; // Y offset value
int Mode; // Greyscale, rainbow, GameBoy, etc. Currently unused
float4 ps_main(in float2 In : TEXCOORD0) : COLOR0
{
float4 Out = tex2D(img, In);
float2 PaletteCoord;
PaletteCoord.xy = (0,0);
for(float PaletteIndex; tex2D(img, In).rgb != tex2D(Palette, PaletteCoord).rgb; PaletteIndex++)
{
PaletteCoord.x = PaletteIndex % 16;
PaletteCoord.y = Floor(PaletteIndex / 16);
}
//PaletteCoord.x += Xoffset;
if((PaletteCoord.y + Yoffset) > 3)
{
PaletteCoord.y = 3;
}
else if((PaletteCoord.y + Yoffset) < 0)
{
PaletteCoord.y = 0;
}
else
{
PaletteCoord.y += Yoffset;
}
Out.rgb = tex2D(Palette, PaletteCoord).rgb;
return Out;
}
technique tech_main
{
pass P0
{
PixelShader = compile ps_2_0 ps_main();
}
}
Display More
This doesn't work for some reason. Later on I then learned that it wasn't very efficient to use for-loops in shader-code (I should've predicted it, having to compare a color to 64 other colors for every pixel on the screen, 60 times a second, that's gotta be rough).
My problem is that I can't see any other way to find out what color has what index in the palette, that is without making a 64-layered if-nest that compares the input to each color in the palette (which I think would almost be worse than a for-loop).
I need a way to find the index in the palette of the colors from the input, from there I'm pretty sure I'd know how to manipulate the index numbers to make the outputs get their neighbor-colors in the palette and such.