Skip to content

Instantly share code, notes, and snippets.

@AKST
Last active December 8, 2025 06:27
Show Gist options
  • Select an option

  • Save AKST/f0edd31f4775ef7a7c8a190b281a05a1 to your computer and use it in GitHub Desktop.

Select an option

Save AKST/f0edd31f4775ef7a7c8a190b281a05a1 to your computer and use it in GitHub Desktop.
some shader toy stuff
const float DITHER_SCALE = 8.0;
const vec3 LUM_VECTOR = vec3(0.299, 0.587, 0.114);
const mat4 BAYER_MATRIX = mat4(
0.0/16.0, 8.0/16.0, 2.0/16.0, 10.0/16.0,
12.0/16.0, 4.0/16.0, 14.0/16.0, 6.0/16.0,
3.0/16.0, 11.0/16.0, 1.0/16.0, 9.0/16.0,
15.0/16.0, 7.0/16.0, 13.0/16.0, 5.0/16.0
);
vec2 square_coord(vec2 frag_coord) {
return floor(frag_coord / DITHER_SCALE) * DITHER_SCALE + DITHER_SCALE * 0.5;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = square_coord(fragCoord) / iResolution.xy;
vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
ivec2 pixelPos = ivec2(fragCoord / DITHER_SCALE) % 4;
float threshold = BAYER_MATRIX[pixelPos.x][pixelPos.y];
float dithered = step(threshold, dot(col, LUM_VECTOR));
fragColor = vec4(vec3(dithered), 1.0);
}
const float DITHER_SCALE = 4.0;
const vec3 LUM_VECTOR = vec3(0.299, 0.587, 0.114);
const mat4 BAYER_MATRIX = mat4(
0.0/16.0, 8.0/16.0, 2.0/16.0, 10.0/16.0,
12.0/16.0, 4.0/16.0, 14.0/16.0, 6.0/16.0,
3.0/16.0, 11.0/16.0, 1.0/16.0, 9.0/16.0,
15.0/16.0, 7.0/16.0, 13.0/16.0, 5.0/16.0
);
vec2 square_coord(vec2 frag_coord) {
return floor(frag_coord / DITHER_SCALE) * DITHER_SCALE + DITHER_SCALE * 0.5;
}
/**
* This is based on this guys tweet, with some changes.
*
* https://x.com/XorDev/status/1995634971030196401
*/
vec3 colour_fn(vec2 coord, float time) {
vec2 p = coord * 6.0 / iResolution.y;
for (float i = 1.0; i <= 32.0; i++) {
p += sin(p.yx * i + i * i + time * i + iResolution.xy) / i;
}
vec4 fragColor = tanh(0.2 / tan(p.y + vec4(0.0, 0.1, 0.3, 0.0)));
return (fragColor * fragColor * fragColor * fragColor).xyz;
}
const vec3 DARK_BLUE = vec3(0.0, 0.0, 0.2);
const vec3 CYAN = vec3(0.0, 0.2, 0.8);
const vec3 YELLOW = vec3(1.0, 0.9, 0.0);
const vec3 WHITE = vec3(1.0, 1.0, 1.0);
vec3 gradient_map(float t) {
if (t < 0.33) {
return mix(DARK_BLUE, CYAN, t / 0.33);
} else if (t < 0.66) {
return mix(CYAN, YELLOW, (t - 0.33) / 0.33);
} else {
return mix(YELLOW, WHITE, (t - 0.66) / 0.34);
}
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
float wave = sin(fragCoord.y * 0.02 + iTime / 16.0) * 0.5 + 0.5;
vec2 coord_dist = vec2(
fragCoord.x + 300.0 * wave,
fragCoord.y
);
vec3 col = colour_fn(square_coord(coord_dist), 1.0 * iTime);
float lum = dot(col, LUM_VECTOR);
vec3 mapped_col = gradient_map(lum);
ivec2 pixelPos = ivec2(fragCoord / DITHER_SCALE) % 4;
float threshold = BAYER_MATRIX[pixelPos.x][pixelPos.y];
vec3 dithered = step(threshold, mapped_col);
fragColor = vec4(vec3(dithered), 1.0);
}
const float DITHER_SCALE = 4.0;
const vec3 LUM_VECTOR = vec3(0.299, 0.587, 0.114);
const mat4 BAYER_MATRIX = mat4(
0.0/16.0, 8.0/16.0, 2.0/16.0, 10.0/16.0,
12.0/16.0, 4.0/16.0, 14.0/16.0, 6.0/16.0,
3.0/16.0, 11.0/16.0, 1.0/16.0, 9.0/16.0,
15.0/16.0, 7.0/16.0, 13.0/16.0, 5.0/16.0
);
vec2 square_coord(vec2 frag_coord) {
return floor(frag_coord / DITHER_SCALE) * DITHER_SCALE + DITHER_SCALE * 0.5;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = square_coord(fragCoord) / iResolution.xy;
vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
ivec2 pixelPos = ivec2(fragCoord / DITHER_SCALE) % 4;
float threshold = BAYER_MATRIX[pixelPos.x][pixelPos.y];
float dithered = step(threshold, dot(col, LUM_VECTOR));
float g = 0.3 + 0.7 * dithered;
float b = 1.0 - 0.5 * dithered;
fragColor = vec4(1.0, g, b, 1.0);
}
/**
* This is my first attempt at dithering, I just adapted the default shader
*/
const float DITHER_SCALE = 4.0;
const float RGB_LEVEL = 8.0;
const vec3 LUM_VECTOR = vec3(0.299, 0.587, 0.114);
const mat4 BAYER_MATRIX = mat4(
0.0/16.0, 8.0/16.0, 2.0/16.0, 10.0/16.0,
12.0/16.0, 4.0/16.0, 14.0/16.0, 6.0/16.0,
3.0/16.0, 11.0/16.0, 1.0/16.0, 9.0/16.0,
15.0/16.0, 7.0/16.0, 13.0/16.0, 5.0/16.0
);
void mainImage(out vec4 fragColor, in vec2 fragCoord ) {
vec2 uv = fragCoord/iResolution.xy;
vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
ivec2 pixelPos = ivec2(fragCoord / DITHER_SCALE) % 4;
float threshold = BAYER_MATRIX[pixelPos.x][pixelPos.y];
float dithered = step(threshold, dot(col, LUM_VECTOR));
col = floor(col * RGB_LEVEL + threshold) / RGB_LEVEL;
fragColor = vec4(col / vec3(dithered), 1.0);
}
const float DITHER_SCALE = 4.0;
const float TARGET_FPS = 30.0;
const float SCANLINE_FPS = 60.0;
const vec3 LUM_VECTOR = vec3(0.299, 0.587, 0.114);
const mat4 BAYER_MATRIX = mat4(
0.0/16.0, 8.0/16.0, 2.0/16.0, 10.0/16.0,
12.0/16.0, 4.0/16.0, 14.0/16.0, 6.0/16.0,
3.0/16.0, 11.0/16.0, 1.0/16.0, 9.0/16.0,
15.0/16.0, 7.0/16.0, 13.0/16.0, 5.0/16.0
);
vec2 square_coord(vec2 frag_coord) {
return floor(frag_coord / DITHER_SCALE) * DITHER_SCALE + DITHER_SCALE * 0.5;
}
/**
* This is based on this guys tweet, with some changes.
*
* https://x.com/XorDev/status/1995634971030196401
*/
vec3 colour_fn(vec2 coord, float time) {
vec2 p = coord * 6.0 / iResolution.y;
for (float i = 1.0; i <= 32.0; i++) {
p += sin(p.yx * i + i * i + time * i + iResolution.xy) / i;
}
vec4 fragColor = tanh(0.2 / tan(p.y + vec4(0.0, 0.1, 0.3, 0.0)));
return (fragColor * fragColor).xyz;
}
const vec3 DARK_BLUE = vec3(0.0, 0.0, 0.2);
const vec3 CYAN = vec3(0.0, 0.2, 0.8);
const vec3 YELLOW = vec3(1.0, 0.9, 0.0);
const vec3 WHITE = vec3(1.0, 1.0, 1.0);
vec3 gradient_map(float t) {
if (t < 0.33) {
return mix(DARK_BLUE, CYAN, t / 0.33);
} else if (t < 0.66) {
return mix(CYAN, YELLOW, (t - 0.33) / 0.33);
} else {
return mix(YELLOW, WHITE, (t - 0.66) / 0.34);
}
}
vec3 render_cell(vec2 coord, float time) {
float wave = sin(coord.y * 0.02 + time / 16.0) * 0.5 + 0.5;
vec2 coord_dist = vec2(coord.x + 200.0 * wave, coord.y);
vec3 col_base = colour_fn(square_coord(coord_dist), 2.0 * time);
ivec2 pixelPos = ivec2(coord / DITHER_SCALE) % 4;
float threshold = BAYER_MATRIX[pixelPos.x][pixelPos.y];
float lum = dot(col_base, LUM_VECTOR);
vec3 mapped_col = gradient_map(lum);
return step(threshold, mapped_col);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
float quantized_time = floor(iTime * TARGET_FPS) / TARGET_FPS;
float scanline_time = floor(iTime * SCANLINE_FPS) / SCANLINE_FPS;
float is_even_frame = mod(floor(scanline_time * SCANLINE_FPS), 2.0);
float a = mod(fragCoord.y, DITHER_SCALE);
float b = DITHER_SCALE / 2.0;
float refresh = mix(step(a, b), step(b, a), is_even_frame);
if (refresh == 1.0) {
vec3 cell_base = render_cell(fragCoord, quantized_time);
fragColor = vec4(mix(cell_base, vec3(1.0), 0.1), 1.0);
} else {
float last_frame = (floor(iTime * TARGET_FPS) - 1.0) / TARGET_FPS;
vec3 cell_base = render_cell(fragCoord, last_frame) * 0.5;
vec2 coord_u = fragCoord - vec2(0.0, DITHER_SCALE);
vec2 coord_b = fragCoord + vec2(0.0, DITHER_SCALE);
vec3 col_u = render_cell(coord_u, quantized_time) * 0.5;
vec3 col_b = render_cell(coord_b, quantized_time) * 0.5;
vec3 col_bleed = mix(col_u, col_b, 0.5);
fragColor = vec4(mix(col_bleed, cell_base, 0.5), 1.0);
}
}
const float DITHER_SCALE = 3.0;
const vec3 LUM_VECTOR = vec3(0.299, 0.587, 0.114);
const mat4 BAYER_MATRIX = mat4(
0.0/16.0, 8.0/16.0, 2.0/16.0, 10.0/16.0,
12.0/16.0, 4.0/16.0, 14.0/16.0, 6.0/16.0,
3.0/16.0, 11.0/16.0, 1.0/16.0, 9.0/16.0,
15.0/16.0, 7.0/16.0, 13.0/16.0, 5.0/16.0
);
vec2 square_coord(vec2 frag_coord) {
return floor(frag_coord / DITHER_SCALE) * DITHER_SCALE + DITHER_SCALE * 0.5;
}
/**
* This is basically this guys tweet
*
* https://x.com/XorDev/status/1995634971030196401
*/
vec3 colour_fn(vec2 coord) {
vec2 p = coord * 6.0 / iResolution.y;
for (float i = 1.0; i <= 10.0; i++) {
p += sin(p.yx * i + i * i + iTime * i + iResolution.xy) / i;
}
vec4 fragColor = tanh(0.2 / tan(p.y + vec4(0.0, 0.1, 0.3, 0.0)));
return (fragColor * fragColor).xyz;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec3 col = colour_fn(square_coord(fragCoord));
ivec2 pixelPos = ivec2(fragCoord / DITHER_SCALE) % 4;
float threshold = BAYER_MATRIX[pixelPos.x][pixelPos.y];
float dithered = step(threshold, dot(col, LUM_VECTOR));
fragColor = vec4(vec3(dithered), 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment