par-term 0.37.1

Cross-platform GPU-accelerated terminal emulator with inline graphics support (Sixel, iTerm2, Kitty)
/*! par-term shader metadata
name: dither
author: null
description: Ordered dithering effect using 4x4 Bayer matrix
version: 1.0.0
defaults:
  animation_speed: 0.5
  brightness: null
  full_content: true
  channel0: ''
  channel1: null
  channel2: null
  channel3: null
  cubemap: ''
  cubemap_enabled: false
  use_background_as_channel0: null
  uniforms:
    iColorMode: 0
    iDitherLevels: 4
    iDitherStrength: 1.0
    iPatternScale: 1
    iThresholdWeight: 1.0
*/

// Ordered dithering effect
// Original by moni-dz (https://github.com/moni-dz)
// CC BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/)

// Standard 4x4 Bayer matrix (normalized to 0-1 range)
// Values: 0,8,2,10 / 12,4,14,6 / 3,11,1,9 / 15,7,13,5
const mat4 bayerMatrix = 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
);

// control int min=2 max=16 step=1 label="Color Levels"
uniform int iDitherLevels;
// control slider min=0 max=1 step=0.01 label="Dither Strength"
uniform float iDitherStrength;
// control int min=1 max=8 step=1 label="Pattern Scale"
uniform int iPatternScale;
// control slider min=0 max=2 step=0.01 label="Threshold Weight"
uniform float iThresholdWeight;
// control select options="color,mono,amber,green" label="Color Mode"
uniform int iColorMode;

vec3 applyColorMode(vec3 color) {
    if (iColorMode == 1) {
        float luma = dot(color, vec3(0.2126, 0.7152, 0.0722));
        return vec3(luma);
    }
    if (iColorMode == 2) {
        float luma = dot(color, vec3(0.2126, 0.7152, 0.0722));
        return luma * vec3(1.0, 0.62, 0.22);
    }
    if (iColorMode == 3) {
        float luma = dot(color, vec3(0.2126, 0.7152, 0.0722));
        return luma * vec3(0.34, 1.0, 0.42);
    }
    return color;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord / iResolution.xy;
    vec3 color = applyColorMode(texture(iChannel4, uv).rgb);

    // Get threshold from Bayer matrix
    float patternScale = float(max(iPatternScale, 1));
    int x = int(floor(fragCoord.x / patternScale)) & 3;
    int y = int(floor(fragCoord.y / patternScale)) & 3;
    float threshold = (bayerMatrix[y][x] - 0.5) * iThresholdWeight + 0.5;

    // Apply ordered dithering
    float levels = float(max(iDitherLevels, 2));
    vec3 dithered = floor(color * levels + threshold) / levels;
    vec3 mixedColor = mix(color, dithered, clamp(iDitherStrength, 0.0, 1.0));

    fragColor = vec4(mixedColor, 1.0);
}