Hi! So I’ve been working on the following dithering shader
precision highp float;
varying vec2 vUv0;
uniform sampler2D uColorBuffer;
uniform vec2 uResolution;
const mat4x4 bayerMatrix4x4 = mat4x4(
0.0, 0.5, 0.125, 0.625,
0.75, 0.25, 0.875, 0.375,
0.1875, 0.6875, 0.0625, 0.5625,
0.9375, 0.4375, 0.8125, 0.3125
);
vec3 orderedDither(vec2 uv, float lum) {
vec3 color = vec3(0.0);
float threshold = 0.0;
int x = int(uv.x * uResolution.x) % 4;
int y = int(uv.y * uResolution.y) % 4;
threshold = bayerMatrix4x4[y][x];
if (lum < threshold) {
color = vec3(0.0);
} else {
color = vec3(1.0);
}
return color;
}
void main( ) {
vec4 color = texture2D(uColorBuffer, vUv0);
float lum = dot(vec3(0.2126, 0.7152, 0.0722), color.rgb);
color.rgb = orderedDither(vUv0, lum);
gl_FragColor = color;
}
But for some reason it renders the screen fully white. Any advice is welcome.
Looking at this, you are either rendering a black or white pixel irrespective of the original pixel color
Yes, that is the case. It seems the issue lies in sampling the threshold for pixel luminance.
vUv0
is in 0 … 1 range … you then multiply it by resolution. That should work.
but try to use gl_FragCoord.xy
instead, that is in pixel space already, so no need to multiply.
1 Like
Thank you, that worked perfectly.
1 Like
see the other dithering possibilities that we used in the engine:
export default /* glsl */`
uniform vec4 blueNoiseJitter;
#ifdef DITHER_BLUENOISE
uniform sampler2D blueNoiseTex32;
#endif
void opacityDither(float alpha, float id) {
#ifdef DITHER_BAYER8
float noise = bayer8(floor(mod(gl_FragCoord.xy + blueNoiseJitter.xy + id, 8.0))) / 64.0;
#else
#ifdef DITHER_BLUENOISE
vec2 uv = fract(gl_FragCoord.xy / 32.0 + blueNoiseJitter.xy + id);
float noise = texture2DLod(blueNoiseTex32, uv, 0.0).y;
#endif
This file has been truncated. show original
it also uses code from here
// procedural Bayer matrix, based on: https://www.shadertoy.com/view/Mlt3z8
export default /* glsl */`
// 2x2 bayer matrix [1 2][3 0], p in [0,1]
float bayer2(vec2 p) {
return mod(2.0 * p.y + p.x + 1.0, 4.0);
}
// 4x4 matrix, p - pixel coordinate
float bayer4(vec2 p) {
vec2 p1 = mod(p, 2.0);
vec2 p2 = floor(0.5 * mod(p, 4.0));
return 4.0 * bayer2(p1) + bayer2(p2);
}
// 8x8 matrix, p - pixel coordinate
float bayer8(vec2 p) {
vec2 p1 = mod(p, 2.0);
vec2 p2 = floor(0.5 * mod(p, 4.0));
vec2 p4 = floor(0.25 * mod(p, 8.0));
This file has been truncated. show original
1 Like