Simple palette shader giving me all white or all black.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
gradualgames
Prole
Posts: 9
Joined: Thu Feb 21, 2019 2:55 am

Simple palette shader giving me all white or all black.

Post by gradualgames »

My goal is to write a shader which, given any pixel on the screen, uses the red component of the color as an index into a 256 pixel wide, 1 pixel tall texture as a palette lookup table. I want to simulate a 256 color palettized screen mode from the old days, in other words.

I was able to get a very very similar shader working on LibGDX some months back. This being my very second shader ever, I'm not sure what could be wrong.

I have verified my palette texture is filled with the colors I want to use as a lookup.

I have verified that the current rendering canvas, without the shader applied, is monochrome red (all shades of 0 to 1 in the red component. as you can see from the shader code, this is used to look up the color to replace with).

Yet, the pixels are all white, or all black.

I'm thinking there must be something with the underlying opengl system that I do not understand that is affecting the behavior of the shader. For example, I do not understand why I have to do a setColor(1, 1, 1) right before my last setCanvas() in order to see the colors as I drew them (without the shader applied).

Code: Select all

uniform sampler2D u_paletteTexture;

vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords)
{
    vec4 pixelColor = texture2D(texture, texture_coords);

    float paletteIndex = pixelColor.r;

    vec2 paletteTextureCoords = vec2(paletteIndex, 0);
    vec3 outputPixelColor = texture2D(u_paletteTexture, paletteTextureCoords).rgb;
    return vec4(outputPixelColor,pixelColor.a);
}
gradualgames
Prole
Posts: 9
Joined: Thu Feb 21, 2019 2:55 am

Re: Simple palette shader giving me all white or all black.

Post by gradualgames »

I've already found a solution to my issue; however I have no idea why it fixed it, and would still be interested in learning why. I found this example in the docs:

Code: Select all

vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords)
{
    vec4 texturecolor = Texel(texture, texture_coords);
    return texturecolor * color;
}
I added * color to my return expression in my own shader:

Code: Select all

uniform sampler2D u_paletteTexture;

vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords)
{
    vec4 pixelColor = texture2D(texture, texture_coords);

    float paletteIndex = pixelColor.r;

    vec2 paletteTextureCoords = vec2(paletteIndex, 0);
    vec3 outputPixelColor = texture2D(u_paletteTexture, paletteTextureCoords).rgb;
    return vec4(outputPixelColor,1.0) * color;
}
And now it works exactly as I would expect. What is mysterious to me is that the shader I based this on was working in a LibGDX project some months back, so why did I need to use * color on Love2D?
User avatar
zorg
Party member
Posts: 3465
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Simple palette shader giving me all white or all black.

Post by zorg »

Hi and welcome to the forums;

For one, the default drawing color should indeed be (1,1,1,1) that is, fully opaque white, which, with the default blend mode, it should basically not tint whatever you're drawing to the screen or into a canvas.

Now, if you did change the color previously at any point, you need to reset the color before drawing a canvas, because that too would be tinted with the default shader as it gets rendered to whatever the currently active frame buffer is (another canvas or the screen), and of course, this doesn't only apply in this situation; alternatively, there's a parametric version of love.graphics.push, with 'all' as its parameter, which not only pushes the transform state onto a stack, but a bunch of other stuff as well, including the color.

As for the shader issue itself, i see you also changed pixelcolor.a to 1.0; i'm not really well versed in shaders but maybe that was the issue? I mean, if you don't want to tint, then multiplying (r,g,b,1) with (1,1,1,1) should just be (r,g,b,1) unless i'm mistaken.

Also, this wiki page has further information about what löve also supports in shaders: Shader_Variables and this is also helpful: love.graphics.newShader since it has tons of examples if you scroll down.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
delweinew
Prole
Posts: 1
Joined: Fri Sep 27, 2019 10:06 am

Re: Simple palette shader giving me all white or all black.

Post by delweinew »

This particular technique is for pixelart, if you deal with high-res images the shader would need to be more complicated. You might try to convert the colors to the HSB format, and then shift the hue for colors within certain hue range, then back to RGB. It'd be quite more taxing, but that's one of the solutions that come to my head.
gradualgames
Prole
Posts: 9
Joined: Thu Feb 21, 2019 2:55 am

Re: Simple palette shader giving me all white or all black.

Post by gradualgames »

So I resuscitated my project the last few weeks. I thought I had had this issue fixed, but the syntax of the shader wasn't the last remaining issue as on some machines, I was still getting all black. On other machines, I was getting odd colorization.

So with my palette shader above, I generate a 256x1 size texture to contain the 256 colors of the palette. The actual images I'm rendering all fill the red component with the palette index/255 so it can be used to look up the color in the palette texture.

I didn't realize last year when I first developed this that plotting points in Love2D treats the x and y coordinates as the mid point of the point. The wiki (https://love2d.org/wiki/love.graphics.points) says:

The pixel grid is actually offset to the center of each pixel. So to get clean pixels drawn use 0.5 + integer increments.

Once I added .5 to the x and y coordinate when plotting the original palette texture, my shader suddenly began working on all the laptops I was seeing problems with.

Just thought I'd add that to this thread in the off chance it helps anybody.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 4 guests