TL;DR: I don’t understand how the alpha channel works in shaders. How can I make my shader respect the alpha specified in my GUI?
Re-opening this topic because I was trying to update the project so that the palette swap shader maintained the alpha of the images.
Here is my setup. I have a GUI with a custom material and fragment program. In this GUI I have two nodes. One is the greyscale which is what was used in the video above to palette swap. The second node is a copy of the first, except I move it a bit, flip it horizontally, and set the alpha to 0.5.
Here’s what happens when you apply the shader I’ve already shared. You can see that the alpha channel gets overwritten to 1 (no surprise - the shader explicitly overwrites alpha to whatever is provided, in this case 1):
The shader code (simplified - I’ve removed color replacements 2 through 7 as they are basically identical).:
varying mediump vec2 var_texcoord0;
varying lowp vec4 var_color;
uniform lowp sampler2D texture_sampler;
vec4 color_1 = vec4(1, 1, 1, 1);
uniform lowp vec4 replace_1;
vec4 eps = vec4(0.009, 0.009, 0.009, 0.009);
void main()
{
lowp vec4 pixel = texture2D(texture_sampler, var_texcoord0.xy);
// color_1, replace_1
if (all(greaterThanEqual(pixel, vec4(color_1 - eps))) &&
all(lessThanEqual(pixel, vec4(color_1 + eps))))
pixel = vec4(replace_1);
gl_FragColor = pixel;
}
I tried modifying it to capture pixel’s original alpha value, then setting it back at the end. I’ve tried both “a” and “w” by the way, with no difference. It just doesn’t change the picture from the last one.
varying mediump vec2 var_texcoord0;
varying lowp vec4 var_color;
uniform lowp sampler2D texture_sampler;
vec4 color_1 = vec4(1, 1, 1, 1);
uniform lowp vec4 replace_1;
vec4 eps = vec4(0.009, 0.009, 0.009, 0.009);
void main()
{
lowp vec4 pixel = texture2D(texture_sampler, var_texcoord0.xy);
float alph = pixel.a;
// color_1, replace_1
if (all(greaterThanEqual(pixel, vec4(color_1 - eps))) &&
all(lessThanEqual(pixel, vec4(color_1 + eps))))
pixel = vec4(replace_1);
pixel.a = alph;
gl_FragColor = pixel;
}
My fragment program is a kind of hybrid of the default GUI and sprite fp’s, since I was modifing Pkeod’s original shader. I thought perhaps I’ve messed something up on the way, so I went back to basics. The default GUI fragment program:
varying mediump vec2 var_texcoord0;
varying lowp vec4 var_color;
uniform lowp sampler2D texture_sampler;
void main()
{
lowp vec4 tex = texture2D(texture_sampler, var_texcoord0.xy);
gl_FragColor = tex * var_color;
}
To test that I was changing the alpha channel, I added this line at the end:
gl_FragColor.a = 0.1;
You can see here that definitely does something to the alpha channel, but not the way I’d expect. The transparency is more pronounced on the darker shades, seemingly not at all on the whites (at least the fully opaque white):
To make it clearer, I added a red node underneath (also in the same GUI):
What’s going on?
How does alpha work in shaders?
How can I modify my shader so that it keeps the alpha set in GUI?