Godot Version
v4.7.2.stable.official [ed1daf0bf]
Question
I’m not sure if I’ll ever need this in any of my projects, but I decided to do a little challenge or whatever and make a shader that would dither a gradient texture. So far, here’s what I have:
This black-hole-looking mess is the gradient texture, and as you can see, it clearly doesn’t align with screen/texture pixels, I assume it’s because I’m using FRAGCOORD but I haven’t figured out how to do it any other way yet. How do I determine where a pixel is relative to the texture, not the screen?
Another problem is that the dithering isn’t properly pixelated, it’s just circular bands that end wherever they happen to.
The code so far:
shader_type canvas_item;
uniform int mode: hint_enum("Linear", "Radial") = 1;
uniform int bayer_size: hint_enum("2x2", "4x4", "8x8") = 2;
const int bayer2[4] = {
0, 2,
3, 1
};
const int bayer4[16] = {
0, 8, 2, 10,
12, 4, 14, 6,
3, 11, 1, 9,
15, 7, 13, 5
};
const int bayer8[64] = {
0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21
};
float get_bayer2(vec2 coord, float alpha) {
int x = int(mod(coord.x, 2.0));
int y = int(mod(coord.y, 2.0));
int index = y * 2 + x;
float limit = (float(bayer2[index]) + 1.5) / 6.0;
return alpha < limit ? 0.0 : 1.0;
}
float get_bayer4(vec2 coord) {
int x = int(mod(coord.x, 4.0));
int y = int(mod(coord.y, 4.0));
int index = y * 4 + x;
return (float(bayer4[index]) + 1.0) / 16.0;
}
float get_bayer8(vec2 coord) {
int x = int(mod(coord.x, 8.0));
int y = int(mod(coord.y, 8.0));
int index = y * 8 + x;
return (float(bayer8[index]) + 1.0) / 64.0;
}
void fragment() {
// these are supposed to work with linear/radial mode
// but I'd rather just get the dithering to work first
vec4 color1;
vec4 color2;
if (mode == 0) {
color1 = texture(TEXTURE, vec2(0.0));
color2 = texture(TEXTURE, vec2(1.0));
} else {
color1 = texture(TEXTURE, vec2(0.5));
color2 = texture(TEXTURE, vec2(0.0));
}
COLOR = (COLOR * get_bayer2(FRAGCOORD.xy / 4.0, COLOR.a));
if (COLOR.a < 0.25){
COLOR = vec4(COLOR.rgb, 0.0);
} else {
COLOR = vec4(COLOR.rgb, 1.0);
}
}



