Skip to content

Instantly share code, notes, and snippets.

@zfedoran
Created February 8, 2025 17:46
Show Gist options
  • Save zfedoran/4e8c2c172f3a8f381e2a92acdc894002 to your computer and use it in GitHub Desktop.
Save zfedoran/4e8c2c172f3a8f381e2a92acdc894002 to your computer and use it in GitHub Desktop.
ghostty glow effect
// A set of sample offsets (x, y) and corresponding weights
const vec3[24] samples = vec3[](
vec3( 0.16937617, 0.98555148, 1.0),
vec3(-1.33307083, 0.47214633, 0.70710678),
vec3(-0.84643949, -1.51113871, 0.57735027),
vec3( 1.55415568, -1.25880901, 0.5),
vec3( 1.68136438, 1.47411459, 0.44721360),
vec3(-1.27951577, 2.08874110, 0.40824829),
vec3(-2.45758475, -0.97993734, 0.37796447),
vec3( 0.58746414, -2.76674644, 0.35355339),
vec3( 2.99771570, 0.11704940, 0.33333333),
vec3( 0.41360842, 3.13511213, 0.31622777),
vec3(-3.16714993, 0.98445990, 0.30151134),
vec3(-1.57367138, -3.08602631, 0.28867513),
vec3( 2.88820265, -2.15830616, 0.27735010),
vec3( 2.71507790, 2.57455860, 0.26726124),
vec3(-2.15040700, 3.22114106, 0.25819889),
vec3(-3.65488588, -1.62536433, 0.25),
vec3( 1.01307760, -3.99670787, 0.24253563),
vec3( 4.22972367, 0.33081361, 0.23570226),
vec3( 0.40107790, 4.34040741, 0.22941573),
vec3(-4.31912457, 1.15981160, 0.22360680),
vec3(-1.92090448, -4.16054395, 0.21821789),
vec3( 3.86391223, -2.65898144, 0.21320072),
vec3( 3.34862284, 3.43318002, 0.20851441),
vec3(-2.87697336, 3.96522689, 0.20412415)
);
// Colors we want to detect
const vec3 targetColors[4] = vec3[](
vec3(0.956, 0.933, 0.894), // #f4eee4
vec3(0.212, 0.976, 0.965), // #36f9f6
vec3(1.0, 1.0, 1.0 ), // #ffffff
vec3(0.600, 0.271, 1.000) // #9945ff
);
// Tint colors for bloom
const vec3 bloomColors[4] = vec3[](
vec3(0.953, 0.624, 0.02), // #f39f05
vec3(0.533, 0.122, 0.988), // #881ffc
vec3(0.011, 0.933, 0.976), // #03edf9
vec3(0.533, 0.122, 0.988) // #881ffc
);
// Per-color bloom strength
const float bloomStrength[4] = float[](
0.20, // yellow-white
0.15, // cyan
0.10, // white
0.15 // purple
);
// Distance threshold to treat two colors as a match
const float threshold = 0.1;
// Return index of the closest matching color if within threshold, otherwise -1
int getMatchingColorIndex(vec3 color) {
int bestIndex = -1;
float bestDist = 9999.0;
for (int i = 0; i < 4; i++) {
float d = distance(color, targetColors[i]);
if (d < bestDist) {
bestDist = d;
bestIndex = i;
}
}
return (bestDist < threshold) ? bestIndex : -1;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord.xy / iResolution.xy;
vec4 color = texture(iChannel0, uv);
// Step size for sampling around the pixel
//vec2 step = vec2(1.414) / iResolution.xy;
vec2 step = vec2(1.0) / iResolution.xy;
// Accumulate bloom
for (int i = 0; i < 24; i++) {
vec3 s = samples[i];
vec4 c = texture(iChannel0, uv + s.xy * step);
// Check if this neighbor matches one of the target colors
int idx = getMatchingColorIndex(c.rgb);
if (idx != -1) {
// Add bloom tint
float w = s.z;
color += vec4(bloomColors[idx], 0.0) * (bloomStrength[idx] * w);
}
}
// Clamp final color
fragColor = clamp(color, 0.0, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment