40 lines
1.1 KiB
GLSL
Executable File
40 lines
1.1 KiB
GLSL
Executable File
#version 300 es
|
|
// Posterization Shader - OPTIMIZED
|
|
// Fixes: Proper rounding, optional dithering to reduce banding
|
|
|
|
precision highp float;
|
|
|
|
in vec2 v_texcoord;
|
|
uniform sampler2D tex;
|
|
out vec4 fragColor;
|
|
|
|
// --- CONFIGURATION ---
|
|
const float COLOR_LEVELS = 4.0;
|
|
// Enable dithering to reduce visible banding
|
|
const bool DITHER = true;
|
|
|
|
// Simple dither pattern
|
|
float dither(vec2 pos) {
|
|
// 4x4 Bayer matrix approximation
|
|
vec2 p = fract(pos * 0.5);
|
|
float d = fract(dot(p, vec2(0.75, 0.5)));
|
|
return (d - 0.5) / COLOR_LEVELS;
|
|
}
|
|
|
|
void main() {
|
|
vec4 color = texture(tex, v_texcoord);
|
|
|
|
vec3 posterized;
|
|
if (DITHER) {
|
|
// Add dither noise before quantization
|
|
float ditherValue = dither(gl_FragCoord.xy);
|
|
posterized = floor((color.rgb + ditherValue) * COLOR_LEVELS + 0.5) / COLOR_LEVELS;
|
|
} else {
|
|
// FIXED: Use round() behavior instead of floor() for better color accuracy
|
|
posterized = floor(color.rgb * COLOR_LEVELS + 0.5) / COLOR_LEVELS;
|
|
}
|
|
|
|
posterized = clamp(posterized, 0.0, 1.0);
|
|
fragColor = vec4(posterized, color.a);
|
|
}
|