mirror of
https://github.com/mr0xb/dotfiles_chezmoi.git
synced 2026-08-28 03:44:57 -04:00
initial commit
This commit is contained in:
commit
f1374f54c4
46 changed files with 4121 additions and 0 deletions
96
dot_config/ghostty/shaders/bling99_gold.glsl
Normal file
96
dot_config/ghostty/shaders/bling99_gold.glsl
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#define PI 3.141592653589793
|
||||
|
||||
float hash12(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float diamondSparkle(vec2 uv, float density, float threshold, float speed) {
|
||||
vec2 g = uv * vec2(density, density * 0.55);
|
||||
vec2 id = floor(g);
|
||||
vec2 f = fract(g) - 0.5;
|
||||
|
||||
float n = hash12(id);
|
||||
float gate = step(threshold, n);
|
||||
float twinkle = pow(max(0.0, sin(iTime * speed + n * 6.2831853)), 36.0);
|
||||
|
||||
float diaD = abs(f.x) + abs(f.y);
|
||||
float diamond = 1.0 - smoothstep(0.00, 0.10, diaD);
|
||||
|
||||
float vertical = (1.0 - smoothstep(0.00, 0.012, abs(f.x))) *
|
||||
(1.0 - smoothstep(0.00, 0.38, abs(f.y)));
|
||||
float horizontal = (1.0 - smoothstep(0.00, 0.012, abs(f.y))) *
|
||||
(1.0 - smoothstep(0.00, 0.38, abs(f.x)));
|
||||
|
||||
return gate * twinkle * (diamond + 0.40 * (vertical + horizontal));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec2 px = 1.0 / iResolution.xy;
|
||||
|
||||
// Tiny VHS-ish horizontal wobble.
|
||||
float wobble = sin(uv.y * 82.0 + iTime * 2.1) * 0.0008
|
||||
+ sin(uv.y * 11.0 - iTime * 0.35) * 0.0012;
|
||||
|
||||
vec2 uvR = clamp(uv + vec2(wobble + px.x * 1.25, 0.0), vec2(0.001), vec2(0.999));
|
||||
vec2 uvG = clamp(uv + vec2(wobble, 0.0), vec2(0.001), vec2(0.999));
|
||||
vec2 uvB = clamp(uv + vec2(wobble - px.x * 1.25, 0.0), vec2(0.001), vec2(0.999));
|
||||
|
||||
vec4 base = texture(iChannel0, uvG);
|
||||
vec3 src = vec3(
|
||||
texture(iChannel0, uvR).r,
|
||||
base.g,
|
||||
texture(iChannel0, uvB).b
|
||||
);
|
||||
|
||||
float lum = dot(src, vec3(0.299, 0.587, 0.114));
|
||||
float ink = smoothstep(0.03, 0.22, lum);
|
||||
float text = smoothstep(0.20, 0.78, lum);
|
||||
|
||||
// Cash-money palette: velvet black, dark leather brown, hot gold, pale diamond gold.
|
||||
vec3 velvet = vec3(0.014, 0.008, 0.003);
|
||||
vec3 brown = vec3(0.085, 0.044, 0.012);
|
||||
vec3 gold = vec3(1.00, 0.66, 0.13);
|
||||
vec3 paleGold = vec3(1.00, 0.90, 0.55);
|
||||
|
||||
vec3 bg = mix(
|
||||
velvet,
|
||||
brown,
|
||||
uv.y + 0.20 * sin(uv.x * 3.0 + iTime * 0.10)
|
||||
);
|
||||
|
||||
vec3 goldText = mix(gold * 0.75, paleGold, pow(lum, 0.75));
|
||||
vec3 col = mix(bg, mix(src, goldText + src * 0.50, 0.48), ink);
|
||||
|
||||
// Jewelry-store light sweep / chrome-grille reflection.
|
||||
float sweepA = pow(max(0.0, sin((uv.x * 1.8 + uv.y * 0.75) * PI * 2.0 - iTime * 0.60)), 22.0);
|
||||
float sweepB = pow(max(0.0, sin((uv.x * -1.1 + uv.y * 1.25) * PI * 2.0 + iTime * 0.42)), 30.0);
|
||||
col += (sweepA * 0.16 + sweepB * 0.11) * vec3(1.0, 0.83, 0.42) * (0.35 + text);
|
||||
|
||||
// Thin old-video scan shimmer, subtle enough to keep text readable.
|
||||
float scan = 0.965 + 0.035 * sin(fragCoord.y * PI);
|
||||
float vhs = 0.98 + 0.02 * hash12(vec2(floor(uv.y * 360.0), floor(iTime * 24.0)));
|
||||
col *= scan * vhs;
|
||||
|
||||
// Random diamond/star hits.
|
||||
float spark = diamondSparkle(uv, 74.0, 0.978, 4.5);
|
||||
spark += 0.55 * diamondSparkle(uv + vec2(0.17, -0.11), 43.0, 0.970, 3.2);
|
||||
col += spark * vec3(1.0, 0.88, 0.48) * (0.85 + 0.65 * text);
|
||||
|
||||
// Camera-flash blobs in the corners.
|
||||
vec2 aspect = vec2(iResolution.x / iResolution.y, 1.0);
|
||||
float flashL = 1.0 - smoothstep(0.00, 0.28, length((uv - vec2(0.14, 0.82)) * aspect));
|
||||
float flashR = 1.0 - smoothstep(0.00, 0.34, length((uv - vec2(0.88, 0.18)) * aspect));
|
||||
col += (flashL * 0.10 + flashR * 0.07) * vec3(1.0, 0.72, 0.22);
|
||||
|
||||
// Music-video edge falloff.
|
||||
float vig = 1.0 - smoothstep(0.20, 0.82, distance(uv, vec2(0.5)));
|
||||
col *= 0.80 + 0.20 * vig;
|
||||
|
||||
// Legibility save: blend some original terminal text back in.
|
||||
col = mix(col, src, 0.18 * text);
|
||||
|
||||
fragColor = vec4(clamp(col, 0.0, 1.0), base.a);
|
||||
}
|
||||
52
dot_config/ghostty/shaders/bloom.glsl
Normal file
52
dot_config/ghostty/shaders/bloom.glsl
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// source: https://gist.github.com/qwerasd205/c3da6c610c8ffe17d6d2d3cc7068f17f
|
||||
// credits: https://github.com/qwerasd205
|
||||
// Golden spiral samples, [x, y, weight] weight is inverse of distance.
|
||||
const vec3[24] samples = {
|
||||
vec3(0.1693761725038636, 0.9855514761735895, 1),
|
||||
vec3(-1.333070830962943, 0.4721463328627773, 0.7071067811865475),
|
||||
vec3(-0.8464394909806497, -1.51113870578065, 0.5773502691896258),
|
||||
vec3(1.554155680728463, -1.2588090085709776, 0.5),
|
||||
vec3(1.681364377589461, 1.4741145918052656, 0.4472135954999579),
|
||||
vec3(-1.2795157692199817, 2.088741103228784, 0.4082482904638631),
|
||||
vec3(-2.4575847530631187, -0.9799373355024756, 0.3779644730092272),
|
||||
vec3(0.5874641440200847, -2.7667464429345077, 0.35355339059327373),
|
||||
vec3(2.997715703369726, 0.11704939884745152, 0.3333333333333333),
|
||||
vec3(0.41360842451688395, 3.1351121305574803, 0.31622776601683794),
|
||||
vec3(-3.167149933769243, 0.9844599011770256, 0.30151134457776363),
|
||||
vec3(-1.5736713846521535, -3.0860263079123245, 0.2886751345948129),
|
||||
vec3(2.888202648340422, -2.1583061557896213, 0.2773500981126146),
|
||||
vec3(2.7150778983300325, 2.5745586041105715, 0.2672612419124244),
|
||||
vec3(-2.1504069972377464, 3.2211410627650165, 0.2581988897471611),
|
||||
vec3(-3.6548858794907493, -1.6253643308191343, 0.25),
|
||||
vec3(1.0130775986052671, -3.9967078676335834, 0.24253562503633297),
|
||||
vec3(4.229723673607257, 0.33081361055181563, 0.23570226039551587),
|
||||
vec3(0.40107790291173834, 4.340407413572593, 0.22941573387056174),
|
||||
vec3(-4.319124570236028, 1.159811599693438, 0.22360679774997896),
|
||||
vec3(-1.9209044802827355, -4.160543952132907, 0.2182178902359924),
|
||||
vec3(3.8639122286635708, -2.6589814382925123, 0.21320071635561041),
|
||||
vec3(3.3486228404946234, 3.4331800232609, 0.20851441405707477),
|
||||
vec3(-2.8769733643574344, 3.9652268864187157, 0.20412414523193154)
|
||||
};
|
||||
|
||||
float lum(vec4 c) {
|
||||
return 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
vec4 color = texture(iChannel0, uv);
|
||||
|
||||
vec2 step = vec2(1.414) / iResolution.xy;
|
||||
|
||||
for (int i = 0; i < 24; i++) {
|
||||
vec3 s = samples[i];
|
||||
vec4 c = texture(iChannel0, uv + s.xy * step);
|
||||
float l = lum(c);
|
||||
if (l > 0.2) {
|
||||
color += l * s.z * c * 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
fragColor = color;
|
||||
}
|
||||
43
dot_config/ghostty/shaders/cash_money_frame.glsl
Normal file
43
dot_config/ghostty/shaders/cash_money_frame.glsl
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#define PI 3.141592653589793
|
||||
|
||||
float diamondAt(vec2 uv, vec2 c, float r) {
|
||||
vec2 q = (uv - c) * vec2(iResolution.x / iResolution.y, 1.0);
|
||||
return 1.0 - smoothstep(r * 0.20, r, abs(q.x) + abs(q.y));
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec4 base = texture(iChannel0, uv);
|
||||
vec3 col = base.rgb;
|
||||
|
||||
float edgeD = min(min(uv.x, 1.0 - uv.x), min(uv.y, 1.0 - uv.y));
|
||||
float frame = 1.0 - smoothstep(0.0, 0.055, edgeD);
|
||||
|
||||
float chrome = pow(
|
||||
0.5 + 0.5 * sin((uv.x * 5.0 + uv.y * 3.0) * PI * 2.0 - iTime * 2.0),
|
||||
3.0
|
||||
);
|
||||
|
||||
float bead = pow(
|
||||
0.5 + 0.5 * sin((uv.x + uv.y) * 120.0 + iTime * 1.7),
|
||||
14.0
|
||||
);
|
||||
|
||||
vec3 darkGold = vec3(0.23, 0.11, 0.02);
|
||||
vec3 hotGold = vec3(1.00, 0.82, 0.30);
|
||||
vec3 frameColor = mix(darkGold, hotGold, chrome);
|
||||
|
||||
col = mix(col, col + frameColor * (0.20 + 0.35 * bead), frame * 0.55);
|
||||
|
||||
// Big fake diamonds in the corners.
|
||||
float corners = 0.0;
|
||||
corners += diamondAt(uv, vec2(0.035, 0.045), 0.040);
|
||||
corners += diamondAt(uv, vec2(0.965, 0.045), 0.040);
|
||||
corners += diamondAt(uv, vec2(0.035, 0.955), 0.040);
|
||||
corners += diamondAt(uv, vec2(0.965, 0.955), 0.040);
|
||||
|
||||
float twinkle = 0.75 + 0.25 * sin(iTime * 5.0);
|
||||
col += corners * vec3(1.0, 0.90, 0.55) * twinkle * 0.80;
|
||||
|
||||
fragColor = vec4(clamp(col, 0.0, 1.0), base.a);
|
||||
}
|
||||
114
dot_config/ghostty/shaders/cubes.glsl
Normal file
114
dot_config/ghostty/shaders/cubes.glsl
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
// credits: https://github.com/rymdlego
|
||||
|
||||
const float speed = 0.2;
|
||||
const float cube_size = 1.0;
|
||||
const float cube_brightness = 1.0;
|
||||
const float cube_rotation_speed = 2.8;
|
||||
const float camera_rotation_speed = 0.1;
|
||||
|
||||
|
||||
|
||||
mat3 rotationMatrix(vec3 m,float a) {
|
||||
m = normalize(m);
|
||||
float c = cos(a),s=sin(a);
|
||||
return mat3(c+(1.-c)*m.x*m.x,
|
||||
(1.-c)*m.x*m.y-s*m.z,
|
||||
(1.-c)*m.x*m.z+s*m.y,
|
||||
(1.-c)*m.x*m.y+s*m.z,
|
||||
c+(1.-c)*m.y*m.y,
|
||||
(1.-c)*m.y*m.z-s*m.x,
|
||||
(1.-c)*m.x*m.z-s*m.y,
|
||||
(1.-c)*m.y*m.z+s*m.x,
|
||||
c+(1.-c)*m.z*m.z);
|
||||
}
|
||||
|
||||
float sphere(vec3 pos, float radius)
|
||||
{
|
||||
return length(pos) - radius;
|
||||
}
|
||||
|
||||
float box(vec3 pos, vec3 size)
|
||||
{
|
||||
float t = iTime;
|
||||
pos = pos * 0.9 * rotationMatrix(vec3(sin(t/4.0*speed)*10.,cos(t/4.0*speed)*12.,2.7), t*2.4/4.0*speed*cube_rotation_speed);
|
||||
return length(max(abs(pos) - size, 0.0));
|
||||
}
|
||||
|
||||
|
||||
float distfunc(vec3 pos)
|
||||
{
|
||||
float t = iTime;
|
||||
|
||||
float size = 0.45 + 0.25*abs(16.0*sin(t*speed/4.0));
|
||||
// float size = 2.3 + 1.8*tan((t-5.4)*6.549);
|
||||
size = cube_size * 0.16 * clamp(size, 2.0, 4.0);
|
||||
|
||||
//pos = pos * rotationMatrix(vec3(0.,-3.,0.7), 3.3 * mod(t/30.0, 4.0));
|
||||
vec3 q = mod(pos, 5.0) - 2.5;
|
||||
float obj1 = box(q, vec3(size));
|
||||
return obj1;
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
float t = iTime;
|
||||
vec2 screenPos = -1.0 + 2.0 * fragCoord.xy / iResolution.xy;
|
||||
screenPos.x *= iResolution.x / iResolution.y;
|
||||
vec3 cameraOrigin = vec3(t*1.0*speed, 0.0, 0.0);
|
||||
// vec3 cameraOrigin = vec3(t*1.8*speed, 3.0+t*0.02*speed, 0.0);
|
||||
vec3 cameraTarget = vec3(t*100., 0.0, 0.0);
|
||||
cameraTarget = vec3(t*20.0,0.0,0.0) * rotationMatrix(vec3(0.0,0.0,1.0), t*speed*camera_rotation_speed);
|
||||
|
||||
vec3 upDirection = vec3(0.5, 1.0, 0.6);
|
||||
|
||||
vec3 cameraDir = normalize(cameraTarget - cameraOrigin);
|
||||
vec3 cameraRight = normalize(cross(upDirection, cameraOrigin));
|
||||
vec3 cameraUp = cross(cameraDir, cameraRight);
|
||||
|
||||
vec3 rayDir = normalize(cameraRight * screenPos.x + cameraUp * screenPos.y + cameraDir);
|
||||
|
||||
const int MAX_ITER = 64;
|
||||
const float MAX_DIST = 48.0;
|
||||
const float EPSILON = 0.001;
|
||||
|
||||
float totalDist = 0.0;
|
||||
vec3 pos = cameraOrigin;
|
||||
float dist = EPSILON;
|
||||
|
||||
for (int i = 0; i < MAX_ITER; i++)
|
||||
{
|
||||
if (dist < EPSILON || totalDist > MAX_DIST)
|
||||
break;
|
||||
dist = distfunc(pos);
|
||||
totalDist += dist;
|
||||
pos += dist*rayDir;
|
||||
}
|
||||
|
||||
vec4 cubes;
|
||||
|
||||
if (dist < EPSILON)
|
||||
{
|
||||
// Lighting Code
|
||||
vec2 eps = vec2(0.0, EPSILON);
|
||||
vec3 normal = normalize(vec3(
|
||||
distfunc(pos + eps.yxx) - distfunc(pos - eps.yxx),
|
||||
distfunc(pos + eps.xyx) - distfunc(pos - eps.xyx),
|
||||
distfunc(pos + eps.xxy) - distfunc(pos - eps.xxy)));
|
||||
float diffuse = max(0., dot(-rayDir, normal));
|
||||
float specular = pow(diffuse, 32.0);
|
||||
vec3 color = vec3(diffuse + specular);
|
||||
vec3 cubeColor = vec3(abs(screenPos),0.5+0.5*sin(t*2.0))*0.8;
|
||||
cubeColor = mix(cubeColor.rgb, vec3(0.0,0.0,0.0), 1.0);
|
||||
color += cubeColor;
|
||||
cubes = vec4(color, 1.0) * vec4(1.0 - (totalDist/MAX_DIST));
|
||||
cubes = vec4(cubes.rgb*0.02*cube_brightness, 0.1);
|
||||
}
|
||||
else {
|
||||
cubes = vec4(0.0);
|
||||
}
|
||||
|
||||
vec2 uv = fragCoord/iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
vec3 blendedColor = terminalColor.rgb + cubes.rgb;
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
221
dot_config/ghostty/shaders/cursor_sweep.glsl
Normal file
221
dot_config/ghostty/shaders/cursor_sweep.glsl
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
// sRGB -> Linear conversion (needed because Ghostty passes sRGB values but the shader pipeline operates in linear color space)
|
||||
vec3 sRGBToLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), c));
|
||||
}
|
||||
|
||||
// --- CONFIGURATION ---
|
||||
vec4 TRAIL_COLOR = vec4(sRGBToLinear(iCurrentCursorColor.rgb), iCurrentCursorColor.a); // for custom color: vec4(0.2, 0.6, 1.0, 0.5); (wrap in sRGBToLinear for correct brightness)
|
||||
const float DURATION = 0.2; // in seconds
|
||||
const float TRAIL_LENGTH = 0.5;
|
||||
const float BLUR = 2.0; // blur size in pixels (for antialiasing)
|
||||
|
||||
// --- CONSTANTS for easing functions ---
|
||||
const float PI = 3.14159265359;
|
||||
const float C1_BACK = 1.70158;
|
||||
const float C2_BACK = C1_BACK * 1.525;
|
||||
const float C3_BACK = C1_BACK + 1.0;
|
||||
const float C4_ELASTIC = (2.0 * PI) / 3.0;
|
||||
const float C5_ELASTIC = (2.0 * PI) / 4.5;
|
||||
const float SPRING_STIFFNESS = 9.0;
|
||||
const float SPRING_DAMPING = 0.9;
|
||||
|
||||
// --- EASING FUNCTIONS ---
|
||||
|
||||
// // Linear
|
||||
// float ease(float x) {
|
||||
// return x;
|
||||
// }
|
||||
|
||||
// // EaseOutQuad
|
||||
// float ease(float x) {
|
||||
// return 1.0 - (1.0 - x) * (1.0 - x);
|
||||
// }
|
||||
|
||||
// EaseOutCubic
|
||||
float ease(float x) {
|
||||
return 1.0 - pow(1.0 - x, 3.0);
|
||||
}
|
||||
|
||||
// // EaseOutQuart
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 4.0);
|
||||
// }
|
||||
|
||||
// // EaseOutQuint
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 5.0);
|
||||
// }
|
||||
|
||||
// EaseOutSine
|
||||
// float ease(float x) {
|
||||
// return sin((x * PI) / 2.0);
|
||||
// }
|
||||
|
||||
// // EaseOutExpo
|
||||
// float ease(float x) {
|
||||
// return x == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * x);
|
||||
// }
|
||||
|
||||
// // EaseOutCirc
|
||||
// float ease(float x) {
|
||||
// return sqrt(1.0 - pow(x - 1.0, 2.0));
|
||||
// }
|
||||
|
||||
// // EaseOutBack
|
||||
// float ease(float x) {
|
||||
// return 1.0 + C3_BACK * pow(x - 1.0, 3.0) + C1_BACK * pow(x - 1.0, 2.0);
|
||||
// }
|
||||
|
||||
// // EaseOutElastic
|
||||
// float ease(float x) {
|
||||
// return x == 0.0 ? 0.0
|
||||
// : x == 1.0 ? 1.0
|
||||
// : pow(2.0, -10.0 * x) * sin((x * 10.0 - 0.75) * C4_ELASTIC) + 1.0;
|
||||
// }
|
||||
|
||||
// Parametric Spring
|
||||
// float ease(float x) {
|
||||
// x = clamp(x, 0.0, 1.0);
|
||||
// float decay = exp(-SPRING_DAMPING * SPRING_STIFFNESS * x);
|
||||
// float freq = sqrt(SPRING_STIFFNESS * (1.0 - SPRING_DAMPING * SPRING_DAMPING));
|
||||
// float osc = cos(freq * 6.283185 * x) + (SPRING_DAMPING * sqrt(SPRING_STIFFNESS) / freq) * sin(freq * 6.283185 * x);
|
||||
// return 1.0 - decay * osc;
|
||||
// }
|
||||
|
||||
float getSdfRectangle(in vec2 point, in vec2 center, in vec2 halfSize)
|
||||
{
|
||||
vec2 d = abs(point - center) - halfSize;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
// Based on Inigo Quilez's 2D distance functions article: https://iquilezles.org/articles/distfunctions2d/
|
||||
// Potencially optimized by eliminating conditionals and loops to enhance performance and reduce branching
|
||||
|
||||
float seg(in vec2 p, in vec2 a, in vec2 b, inout float s, float d) {
|
||||
vec2 e = b - a;
|
||||
vec2 w = p - a;
|
||||
vec2 proj = a + e * clamp(dot(w, e) / dot(e, e), 0.0, 1.0);
|
||||
float segd = dot(p - proj, p - proj);
|
||||
d = min(d, segd);
|
||||
|
||||
float c0 = step(0.0, p.y - a.y);
|
||||
float c1 = 1.0 - step(0.0, p.y - b.y);
|
||||
float c2 = 1.0 - step(0.0, e.x * w.y - e.y * w.x);
|
||||
float allCond = c0 * c1 * c2;
|
||||
float noneCond = (1.0 - c0) * (1.0 - c1) * (1.0 - c2);
|
||||
float flip = mix(1.0, -1.0, step(0.5, allCond + noneCond));
|
||||
s *= flip;
|
||||
return d;
|
||||
}
|
||||
|
||||
float getSdfParallelogram(in vec2 p, in vec2 v0, in vec2 v1, in vec2 v2, in vec2 v3) {
|
||||
float s = 1.0;
|
||||
float d = dot(p - v0, p - v0);
|
||||
|
||||
d = seg(p, v0, v3, s, d);
|
||||
d = seg(p, v1, v0, s, d);
|
||||
d = seg(p, v2, v1, s, d);
|
||||
d = seg(p, v3, v2, s, d);
|
||||
|
||||
return s * sqrt(d);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 value, float isPosition) {
|
||||
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
||||
}
|
||||
|
||||
float antialising(float distance) {
|
||||
return 1. - smoothstep(0., normalize(vec2(BLUR, BLUR), 0.).x, distance);
|
||||
}
|
||||
|
||||
float getTopVertexFlag(vec2 a, vec2 b) {
|
||||
float condition1 = step(b.x, a.x) * step(a.y, b.y); // a.x < b.x && a.y > b.y
|
||||
float condition2 = step(a.x, b.x) * step(b.y, a.y); // a.x > b.x && a.y < b.y
|
||||
|
||||
// if neither condition is met, return 1 (else case)
|
||||
return 1.0 - max(condition1, condition2);
|
||||
}
|
||||
|
||||
vec2 getRectangleCenter(vec4 rectangle) {
|
||||
return vec2(rectangle.x + (rectangle.z / 2.), rectangle.y - (rectangle.w / 2.));
|
||||
}
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
||||
#if !defined(WEB)
|
||||
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
||||
#endif
|
||||
|
||||
// normalization & setup(-1, 1 coords)
|
||||
vec2 vu = normalize(fragCoord, 1.);
|
||||
vec2 offsetFactor = vec2(-.5, 0.5);
|
||||
|
||||
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
||||
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
||||
|
||||
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
||||
vec2 centerCP = previousCursor.xy - (previousCursor.zw * offsetFactor);
|
||||
|
||||
float sdfCurrentCursor = getSdfRectangle(vu, centerCC, currentCursor.zw * 0.5);
|
||||
|
||||
float lineLength = distance(centerCC, centerCP);
|
||||
|
||||
vec4 newColor = vec4(fragColor);
|
||||
|
||||
float minDist = currentCursor.w * 1.5;
|
||||
float progress = clamp((iTime - iTimeCursorChange) / DURATION, 0.0, 1.0);
|
||||
if (lineLength > minDist) {
|
||||
// --- Animation Logic ---
|
||||
float shrinkFactor = ease(progress);
|
||||
|
||||
// detect straight moves
|
||||
vec2 delta = abs(centerCC - centerCP);
|
||||
float threshold = 0.001;
|
||||
float isHorizontal = step(delta.y, threshold);
|
||||
float isVertical = step(delta.x, threshold);
|
||||
float isStraightMove = max(isHorizontal, isVertical);
|
||||
|
||||
// -- Making parallelogram sdf (diagonal moves) ---
|
||||
float topVertexFlag = getTopVertexFlag(currentCursor.xy, previousCursor.xy);
|
||||
float bottomVertexFlag = 1.0 - topVertexFlag;
|
||||
vec2 v0 = vec2(currentCursor.x + currentCursor.z * topVertexFlag, currentCursor.y - currentCursor.w);
|
||||
vec2 v1 = vec2(currentCursor.x + currentCursor.z * bottomVertexFlag, currentCursor.y);
|
||||
vec2 v2_full = vec2(previousCursor.x + currentCursor.z * bottomVertexFlag, previousCursor.y);
|
||||
vec2 v3_full = vec2(previousCursor.x + currentCursor.z * topVertexFlag, previousCursor.y - previousCursor.w);
|
||||
|
||||
vec2 v2_start = mix(v1, v2_full, TRAIL_LENGTH);
|
||||
vec2 v3_start = mix(v0, v3_full, TRAIL_LENGTH);
|
||||
vec2 v2_anim = mix(v2_start, v1, shrinkFactor);
|
||||
vec2 v3_anim = mix(v3_start, v0, shrinkFactor);
|
||||
|
||||
float sdfTrail_diag = getSdfParallelogram(vu, v0, v1, v2_anim, v3_anim);
|
||||
|
||||
// --- Making rectangle sdf (straight moves) ---
|
||||
vec2 min_center = min(centerCP, centerCC);
|
||||
vec2 max_center = max(centerCP, centerCC);
|
||||
|
||||
vec2 bBoxSize_full = (max_center - min_center) + currentCursor.zw;
|
||||
vec2 bBoxCenter_full = (min_center + max_center) * 0.5;
|
||||
|
||||
vec2 bBoxSize_start = mix(currentCursor.zw, bBoxSize_full, TRAIL_LENGTH);
|
||||
vec2 bBoxCenter_start = mix(centerCC, bBoxCenter_full, TRAIL_LENGTH);
|
||||
|
||||
vec2 animSize = mix(bBoxSize_start, currentCursor.zw, shrinkFactor);
|
||||
vec2 animCenter = mix(bBoxCenter_start, centerCC, shrinkFactor);
|
||||
|
||||
float sdfTrail_rect = getSdfRectangle(vu, animCenter, animSize * 0.5);
|
||||
|
||||
// -- Selecting and drawing the trail sdf --
|
||||
float sdfTrail = mix(sdfTrail_diag, sdfTrail_rect, isStraightMove);
|
||||
|
||||
vec4 trail = TRAIL_COLOR;
|
||||
float trailAlpha = antialising(sdfTrail);
|
||||
newColor = mix(newColor, trail, trailAlpha);
|
||||
|
||||
// Punch hole
|
||||
newColor = mix(newColor, fragColor, step(sdfCurrentCursor, 0.));
|
||||
}
|
||||
|
||||
|
||||
fragColor = newColor;
|
||||
}
|
||||
239
dot_config/ghostty/shaders/cursor_tail.glsl
Normal file
239
dot_config/ghostty/shaders/cursor_tail.glsl
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
// sRGB -> Linear conversion (needed because Ghostty passes sRGB values but the shader pipeline operates in linear color space)
|
||||
vec3 sRGBToLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), c));
|
||||
}
|
||||
|
||||
// --- CONFIGURATION ---
|
||||
vec4 TRAIL_COLOR = vec4(sRGBToLinear(iCurrentCursorColor.rgb), iCurrentCursorColor.a); // for custom color: vec4(0.2, 0.6, 1.0, 0.5); (wrap in sRGBToLinear for correct brightness)
|
||||
const float DURATION = 0.09; // in seconds
|
||||
const float MAX_TRAIL_LENGTH = 0.2;
|
||||
const float THRESHOLD_MIN_DISTANCE = 1.5; // min distance to show trail (units of cursor width)
|
||||
const float BLUR = 2.0; // blur size in pixels (for antialiasing)
|
||||
|
||||
// --- CONSTANTS for easing functions ---
|
||||
const float PI = 3.14159265359;
|
||||
const float C1_BACK = 1.70158;
|
||||
const float C2_BACK = C1_BACK * 1.525;
|
||||
const float C3_BACK = C1_BACK + 1.0;
|
||||
const float C4_ELASTIC = (2.0 * PI) / 3.0;
|
||||
const float C5_ELASTIC = (2.0 * PI) / 4.5;
|
||||
const float SPRING_STIFFNESS = 9.0;
|
||||
const float SPRING_DAMPING = 0.9;
|
||||
|
||||
// --- EASING FUNCTIONS ---
|
||||
|
||||
// // Linear
|
||||
// float ease(float x) {
|
||||
// return x;
|
||||
// }
|
||||
|
||||
// // EaseOutQuad
|
||||
// float ease(float x) {
|
||||
// return 1.0 - (1.0 - x) * (1.0 - x);
|
||||
// }
|
||||
|
||||
// // EaseOutCubic
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 3.0);
|
||||
// }
|
||||
|
||||
|
||||
// // EaseOutQuart
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 4.0);
|
||||
// }
|
||||
|
||||
// // EaseOutQuint
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 5.0);
|
||||
// }
|
||||
|
||||
// // EaseOutSine
|
||||
// float ease(float x) {
|
||||
// return sin((x * PI) / 2.0);
|
||||
// }
|
||||
|
||||
// // EaseOutExpo
|
||||
// float ease(float x) {
|
||||
// return x == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * x);
|
||||
// }
|
||||
|
||||
// EaseOutCirc
|
||||
float ease(float x) {
|
||||
return sqrt(1.0 - pow(x - 1.0, 2.0));
|
||||
}
|
||||
|
||||
// // EaseOutBack
|
||||
// float ease(float x) {
|
||||
// return 1.0 + C3_BACK * pow(x - 1.0, 3.0) + C1_BACK * pow(x - 1.0, 2.0);
|
||||
// }
|
||||
|
||||
// // EaseOutElastic
|
||||
// float ease(float x) {
|
||||
// return x == 0.0 ? 0.0
|
||||
// : x == 1.0 ? 1.0
|
||||
// : pow(2.0, -10.0 * x) * sin((x * 10.0 - 0.75) * C4_ELASTIC) + 1.0;
|
||||
// }
|
||||
|
||||
// Parametric Spring
|
||||
// float ease(float x) {
|
||||
// x = clamp(x, 0.0, 1.0);
|
||||
// float decay = exp(-SPRING_DAMPING * SPRING_STIFFNESS * x);
|
||||
// float freq = sqrt(SPRING_STIFFNESS * (1.0 - SPRING_DAMPING * SPRING_DAMPING));
|
||||
// float osc = cos(freq * 6.283185 * x) + (SPRING_DAMPING * sqrt(SPRING_STIFFNESS) / freq) * sin(freq * 6.283185 * x);
|
||||
// return 1.0 - decay * osc;
|
||||
// }
|
||||
|
||||
float getSdfRectangle(in vec2 p, in vec2 xy, in vec2 b)
|
||||
{
|
||||
vec2 d = abs(p - xy) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
// Based on Inigo Quilez's 2D distance functions article: https://iquilezles.org/articles/distfunctions2d/
|
||||
// Potencially optimized by eliminating conditionals and loops to enhance performance and reduce branching
|
||||
|
||||
float seg(in vec2 p, in vec2 a, in vec2 b, inout float s, float d) {
|
||||
vec2 e = b - a;
|
||||
vec2 w = p - a;
|
||||
vec2 proj = a + e * clamp(dot(w, e) / dot(e, e), 0.0, 1.0);
|
||||
float segd = dot(p - proj, p - proj);
|
||||
d = min(d, segd);
|
||||
|
||||
float c0 = step(0.0, p.y - a.y);
|
||||
float c1 = 1.0 - step(0.0, p.y - b.y);
|
||||
float c2 = 1.0 - step(0.0, e.x * w.y - e.y * w.x);
|
||||
float allCond = c0 * c1 * c2;
|
||||
float noneCond = (1.0 - c0) * (1.0 - c1) * (1.0 - c2);
|
||||
float flip = mix(1.0, -1.0, step(0.5, allCond + noneCond));
|
||||
s *= flip;
|
||||
return d;
|
||||
}
|
||||
|
||||
float getSdfParallelogram(in vec2 p, in vec2 v0, in vec2 v1, in vec2 v2, in vec2 v3) {
|
||||
float s = 1.0;
|
||||
float d = dot(p - v0, p - v0);
|
||||
|
||||
d = seg(p, v0, v3, s, d);
|
||||
d = seg(p, v1, v0, s, d);
|
||||
d = seg(p, v2, v1, s, d);
|
||||
d = seg(p, v3, v2, s, d);
|
||||
|
||||
return s * sqrt(d);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 value, float isPosition) {
|
||||
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
||||
}
|
||||
|
||||
float antialising(float distance) {
|
||||
return 1. - smoothstep(0., normalize(vec2(BLUR, BLUR), 0.).x, distance);
|
||||
}
|
||||
|
||||
float determineIfTopRightIsLeading(vec2 a, vec2 b) {
|
||||
float condition1 = step(b.x, a.x) * step(a.y, b.y); // a.x < b.x && a.y > b.y
|
||||
float condition2 = step(a.x, b.x) * step(b.y, a.y); // a.x > b.x && a.y < b.y
|
||||
|
||||
// if neither condition is met, return 1 (else case)
|
||||
return 1.0 - max(condition1, condition2);
|
||||
}
|
||||
|
||||
vec2 getRectangleCenter(vec4 rectangle) {
|
||||
return vec2(rectangle.x + (rectangle.z / 2.), rectangle.y - (rectangle.w / 2.));
|
||||
}
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
||||
#if !defined(WEB)
|
||||
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
||||
#endif
|
||||
|
||||
// normalization & setup(-1, 1 coords)
|
||||
vec2 vu = normalize(fragCoord, 1.);
|
||||
vec2 offsetFactor = vec2(-.5, 0.5);
|
||||
|
||||
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
||||
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
||||
|
||||
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
||||
vec2 centerCP = previousCursor.xy - (previousCursor.zw * offsetFactor);
|
||||
|
||||
vec2 delta = centerCP - centerCC;
|
||||
float lineLength = length(delta);
|
||||
|
||||
float sdfCurrentCursor = getSdfRectangle(vu, centerCC, currentCursor.zw * 0.5);
|
||||
|
||||
vec4 newColor = vec4(fragColor);
|
||||
|
||||
float minDist = currentCursor.w * THRESHOLD_MIN_DISTANCE;
|
||||
float progress = clamp((iTime - iTimeCursorChange) / DURATION, 0.0, 1.0);
|
||||
if (lineLength > minDist) {
|
||||
// ANIMATION logic
|
||||
|
||||
float head_eased = 0.0;
|
||||
float tail_eased = 0.0;
|
||||
|
||||
float tail_delay_factor = MAX_TRAIL_LENGTH / lineLength;
|
||||
|
||||
float isLongMove = step(MAX_TRAIL_LENGTH, lineLength);
|
||||
|
||||
float head_eased_short = ease(progress);
|
||||
float tail_eased_short = ease(smoothstep(tail_delay_factor, 1.0, progress));
|
||||
float head_eased_long = 1.0;
|
||||
float tail_eased_long = ease(progress);
|
||||
|
||||
head_eased = mix(head_eased_long, head_eased_short, isLongMove);
|
||||
tail_eased = mix(tail_eased_long, tail_eased_short, isLongMove);
|
||||
|
||||
// detect straight moves
|
||||
vec2 delta_abs = abs(centerCC - centerCP);
|
||||
float threshold = 0.001;
|
||||
float isHorizontal = step(delta_abs.y, threshold);
|
||||
float isVertical = step(delta_abs.x, threshold);
|
||||
float isStraightMove = max(isHorizontal, isVertical);
|
||||
|
||||
// -- Making the parallelogram sdf (diagonal move) --
|
||||
|
||||
// animate the TOP-LEFT corners
|
||||
vec2 head_pos_tl = mix(previousCursor.xy, currentCursor.xy, head_eased);
|
||||
vec2 tail_pos_tl = mix(previousCursor.xy, currentCursor.xy, tail_eased);
|
||||
|
||||
float isTopRightLeading = determineIfTopRightIsLeading(currentCursor.xy, previousCursor.xy);
|
||||
float isBottomLeftLeading = 1.0 - isTopRightLeading;
|
||||
|
||||
// v0, v1 : "front" of the trail (head)
|
||||
vec2 v0 = vec2(head_pos_tl.x + currentCursor.z * isTopRightLeading, head_pos_tl.y - currentCursor.w);
|
||||
vec2 v1 = vec2(head_pos_tl.x + currentCursor.z * isBottomLeftLeading, head_pos_tl.y);
|
||||
|
||||
// v2, v3: "back" of the trail (tail)
|
||||
vec2 v2 = vec2(tail_pos_tl.x + currentCursor.z * isBottomLeftLeading, tail_pos_tl.y);
|
||||
vec2 v3 = vec2(tail_pos_tl.x + currentCursor.z * isTopRightLeading, tail_pos_tl.y - previousCursor.w);
|
||||
|
||||
float sdfTrail_diag = getSdfParallelogram(vu, v0, v1, v2, v3);
|
||||
|
||||
// -- Making the rectangle sdf (straight move) --
|
||||
|
||||
vec2 head_center = mix(centerCP, centerCC, head_eased);
|
||||
vec2 tail_center = mix(centerCP, centerCC, tail_eased);
|
||||
|
||||
vec2 min_center = min(head_center, tail_center);
|
||||
vec2 max_center = max(head_center, tail_center);
|
||||
|
||||
vec2 box_size = (max_center - min_center) + currentCursor.zw;
|
||||
vec2 box_center = (min_center + max_center) * 0.5;
|
||||
|
||||
float sdfTrail_rect = getSdfRectangle(vu, box_center, box_size * 0.5);
|
||||
|
||||
// -- FINAL SELECTING AND DRAWING --
|
||||
float sdfTrail = mix(sdfTrail_diag, sdfTrail_rect, isStraightMove);
|
||||
|
||||
vec4 trail = TRAIL_COLOR;
|
||||
float trailAlpha = antialising(sdfTrail);
|
||||
newColor = mix(newColor, trail, trailAlpha);
|
||||
|
||||
// punch hole
|
||||
newColor = mix(newColor, fragColor, step(sdfCurrentCursor, 0.));
|
||||
}
|
||||
|
||||
fragColor = newColor;
|
||||
}
|
||||
308
dot_config/ghostty/shaders/cursor_warp.glsl
Normal file
308
dot_config/ghostty/shaders/cursor_warp.glsl
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
// sRGB -> Linear conversion (needed because Ghostty passes sRGB values but the shader pipeline operates in linear color space)
|
||||
vec3 sRGBToLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), c));
|
||||
}
|
||||
|
||||
// --- CONFIGURATION ---
|
||||
vec4 TRAIL_COLOR = vec4(sRGBToLinear(iCurrentCursorColor.rgb), iCurrentCursorColor.a); // for custom color: vec4(0.2, 0.6, 1.0, 0.5); (wrap in sRGBToLinear for correct brightness)
|
||||
const float DURATION = 0.2; // total animation time
|
||||
const float TRAIL_SIZE = 0.8; // 0.0 = all corners move together. 1.0 = max smear (leading corners jump instantly)
|
||||
const float THRESHOLD_MIN_DISTANCE = 1.5; // min distance to show trail (units of cursor height)
|
||||
const float BLUR = 1.0; // blur size in pixels (for antialiasing)
|
||||
const float TRAIL_THICKNESS = 1.0; // 1.0 = full cursor height, 0.0 = zero height, >1.0 = funky aah
|
||||
const float TRAIL_THICKNESS_X = 0.9;
|
||||
|
||||
const float FADE_ENABLED = 0.0; // 1.0 to enable fade gradient along the trail, 0.0 to disable
|
||||
const float FADE_EXPONENT = 5.0; // exponent for fade gradient along the trail
|
||||
|
||||
// --- CONSTANTS for easing functions ---
|
||||
const float PI = 3.14159265359;
|
||||
const float C1_BACK = 1.70158;
|
||||
const float C2_BACK = C1_BACK * 1.525;
|
||||
const float C3_BACK = C1_BACK + 1.0;
|
||||
const float C4_ELASTIC = (2.0 * PI) / 3.0;
|
||||
const float C5_ELASTIC = (2.0 * PI) / 4.5;
|
||||
const float SPRING_STIFFNESS = 9.0;
|
||||
const float SPRING_DAMPING = 0.9;
|
||||
|
||||
// --- EASING FUNCTIONS ---
|
||||
|
||||
// // Linear
|
||||
// float ease(float x) {
|
||||
// return x;
|
||||
// }
|
||||
|
||||
// // EaseOutQuad
|
||||
// float ease(float x) {
|
||||
// return 1.0 - (1.0 - x) * (1.0 - x);
|
||||
// }
|
||||
|
||||
// // EaseOutCubic
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 3.0);
|
||||
// }
|
||||
|
||||
// // EaseOutQuart
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 4.0);
|
||||
// }
|
||||
|
||||
// // EaseOutQuint
|
||||
// float ease(float x) {
|
||||
// return 1.0 - pow(1.0 - x, 5.0);
|
||||
// }
|
||||
|
||||
// // EaseOutSine
|
||||
// float ease(float x) {
|
||||
// return sin((x * PI) / 2.0);
|
||||
// }
|
||||
|
||||
// // EaseOutExpo
|
||||
// float ease(float x) {
|
||||
// return x == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * x);
|
||||
// }
|
||||
|
||||
// EaseOutCirc
|
||||
float ease(float x) {
|
||||
return sqrt(1.0 - pow(x - 1.0, 2.0));
|
||||
}
|
||||
|
||||
// // EaseOutBack
|
||||
// float ease(float x) {
|
||||
// return 1.0 + C3_BACK * pow(x - 1.0, 3.0) + C1_BACK * pow(x - 1.0, 2.0);
|
||||
// }
|
||||
|
||||
// // EaseOutElastic
|
||||
// float ease(float x) {
|
||||
// return x == 0.0 ? 0.0
|
||||
// : x == 1.0 ? 1.0
|
||||
// : pow(2.0, -10.0 * x) * sin((x * 10.0 - 0.75) * C4_ELASTIC) + 1.0;
|
||||
// }
|
||||
|
||||
// // Parametric Spring
|
||||
// float ease(float x) {
|
||||
// x = clamp(x, 0.0, 1.0);
|
||||
// float decay = exp(-SPRING_DAMPING * SPRING_STIFFNESS * x);
|
||||
// float freq = sqrt(SPRING_STIFFNESS * (1.0 - SPRING_DAMPING * SPRING_DAMPING));
|
||||
// float osc = cos(freq * 6.283185 * x) + (SPRING_DAMPING * sqrt(SPRING_STIFFNESS) / freq) * sin(freq * 6.283185 * x);
|
||||
// return 1.0 - decay * osc;
|
||||
// }
|
||||
|
||||
float getSdfRectangle(in vec2 p, in vec2 xy, in vec2 b)
|
||||
{
|
||||
vec2 d = abs(p - xy) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
// Based on Inigo Quilez's 2D distance functions article: https://iquilezles.org/articles/distfunctions2d/
|
||||
// Potencially optimized by eliminating conditionals and loops to enhance performance and reduce branching
|
||||
float seg(in vec2 p, in vec2 a, in vec2 b, inout float s, float d) {
|
||||
vec2 e = b - a;
|
||||
vec2 w = p - a;
|
||||
vec2 proj = a + e * clamp(dot(w, e) / dot(e, e), 0.0, 1.0);
|
||||
float segd = dot(p - proj, p - proj);
|
||||
d = min(d, segd);
|
||||
|
||||
float c0 = step(0.0, p.y - a.y);
|
||||
float c1 = 1.0 - step(0.0, p.y - b.y);
|
||||
float c2 = 1.0 - step(0.0, e.x * w.y - e.y * w.x);
|
||||
float allCond = c0 * c1 * c2;
|
||||
float noneCond = (1.0 - c0) * (1.0 - c1) * (1.0 - c2);
|
||||
float flip = mix(1.0, -1.0, step(0.5, allCond + noneCond));
|
||||
s *= flip;
|
||||
return d;
|
||||
}
|
||||
|
||||
float getSdfConvexQuad(in vec2 p, in vec2 v1, in vec2 v2, in vec2 v3, in vec2 v4) {
|
||||
float s = 1.0;
|
||||
float d = dot(p - v1, p - v1);
|
||||
|
||||
d = seg(p, v1, v2, s, d);
|
||||
d = seg(p, v2, v3, s, d);
|
||||
d = seg(p, v3, v4, s, d);
|
||||
d = seg(p, v4, v1, s, d);
|
||||
|
||||
return s * sqrt(d);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 value, float isPosition) {
|
||||
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
||||
}
|
||||
|
||||
float antialising(float distance, float blurAmount) {
|
||||
return 1. - smoothstep(0., normalize(vec2(blurAmount, blurAmount), 0.).x, distance);
|
||||
}
|
||||
|
||||
// Determines animation duration based on a corner's alignment with the move direction(dot product)
|
||||
// dot_val will be in [-2, 2]
|
||||
// > 0.5 (1 or 2) = Leading
|
||||
// > -0.5 (0) = Side
|
||||
// <= -0.5 (-1 or -2) = Trailing
|
||||
float getDurationFromDot(float dot_val, float DURATION_LEAD, float DURATION_SIDE, float DURATION_TRAIL) {
|
||||
float isLead = step(0.5, dot_val);
|
||||
float isSide = step(-0.5, dot_val) * (1.0 - isLead);
|
||||
|
||||
// Start with trailing duration
|
||||
float duration = mix(DURATION_TRAIL, DURATION_SIDE, isSide);
|
||||
// Mix in leading duration
|
||||
duration = mix(duration, DURATION_LEAD, isLead);
|
||||
return duration;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
||||
#if !defined(WEB)
|
||||
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
||||
#endif
|
||||
|
||||
// normalization & setup(-1, 1 coords)
|
||||
vec2 vu = normalize(fragCoord, 1.);
|
||||
vec2 offsetFactor = vec2(-.5, 0.5);
|
||||
|
||||
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
||||
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
||||
|
||||
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
||||
vec2 halfSizeCC = currentCursor.zw * 0.5;
|
||||
vec2 centerCP = previousCursor.xy - (previousCursor.zw * offsetFactor);
|
||||
vec2 halfSizeCP = previousCursor.zw * 0.5;
|
||||
|
||||
float sdfCurrentCursor = getSdfRectangle(vu, centerCC, halfSizeCC);
|
||||
|
||||
float lineLength = distance(centerCC, centerCP);
|
||||
float minDist = currentCursor.w * THRESHOLD_MIN_DISTANCE;
|
||||
|
||||
vec4 newColor = vec4(fragColor);
|
||||
|
||||
float baseProgress = iTime - iTimeCursorChange;
|
||||
|
||||
if (lineLength > minDist && baseProgress < DURATION - 0.001) {
|
||||
// defining corners of cursors
|
||||
|
||||
// Y (Height) with TRAIL_THICKNESS
|
||||
float cc_half_height = currentCursor.w * 0.5;
|
||||
float cc_center_y = currentCursor.y - cc_half_height;
|
||||
float cc_new_half_height = cc_half_height * TRAIL_THICKNESS;
|
||||
float cc_new_top_y = cc_center_y + cc_new_half_height;
|
||||
float cc_new_bottom_y = cc_center_y - cc_new_half_height;
|
||||
|
||||
// X (Width) with TRAIL_THICKNESS
|
||||
float cc_half_width = currentCursor.z * 0.5;
|
||||
float cc_center_x = currentCursor.x + cc_half_width;
|
||||
float cc_new_half_width = cc_half_width * TRAIL_THICKNESS_X;
|
||||
float cc_new_left_x = cc_center_x - cc_new_half_width;
|
||||
float cc_new_right_x = cc_center_x + cc_new_half_width;
|
||||
|
||||
vec2 cc_tl = vec2(cc_new_left_x, cc_new_top_y);
|
||||
vec2 cc_tr = vec2(cc_new_right_x, cc_new_top_y);
|
||||
vec2 cc_bl = vec2(cc_new_left_x, cc_new_bottom_y);
|
||||
vec2 cc_br = vec2(cc_new_right_x, cc_new_bottom_y);
|
||||
|
||||
// same thing for previous cursor
|
||||
float cp_half_height = previousCursor.w * 0.5;
|
||||
float cp_center_y = previousCursor.y - cp_half_height;
|
||||
float cp_new_half_height = cp_half_height * TRAIL_THICKNESS;
|
||||
float cp_new_top_y = cp_center_y + cp_new_half_height;
|
||||
float cp_new_bottom_y = cp_center_y - cp_new_half_height;
|
||||
|
||||
float cp_half_width = previousCursor.z * 0.5;
|
||||
float cp_center_x = previousCursor.x + cp_half_width;
|
||||
float cp_new_half_width = cp_half_width * TRAIL_THICKNESS_X;
|
||||
float cp_new_left_x = cp_center_x - cp_new_half_width;
|
||||
float cp_new_right_x = cp_center_x + cp_new_half_width;
|
||||
|
||||
vec2 cp_tl = vec2(cp_new_left_x, cp_new_top_y);
|
||||
vec2 cp_tr = vec2(cp_new_right_x, cp_new_top_y);
|
||||
vec2 cp_bl = vec2(cp_new_left_x, cp_new_bottom_y);
|
||||
vec2 cp_br = vec2(cp_new_right_x, cp_new_bottom_y);
|
||||
|
||||
// calculating durations for every corner
|
||||
const float DURATION_TRAIL = DURATION;
|
||||
const float DURATION_LEAD = DURATION * (1.0 - TRAIL_SIZE);
|
||||
const float DURATION_SIDE = (DURATION_LEAD + DURATION_TRAIL) / 2.0;
|
||||
|
||||
vec2 moveVec = centerCC - centerCP;
|
||||
vec2 s = sign(moveVec);
|
||||
|
||||
// dot products for each corner, determining alignment with movement direction
|
||||
float dot_tl = dot(vec2(-1., 1.), s);
|
||||
float dot_tr = dot(vec2( 1., 1.), s);
|
||||
float dot_bl = dot(vec2(-1.,-1.), s);
|
||||
float dot_br = dot(vec2( 1.,-1.), s);
|
||||
|
||||
// assign durations based on dot products
|
||||
float dur_tl = getDurationFromDot(dot_tl, DURATION_LEAD, DURATION_SIDE, DURATION_TRAIL);
|
||||
float dur_tr = getDurationFromDot(dot_tr, DURATION_LEAD, DURATION_SIDE, DURATION_TRAIL);
|
||||
float dur_bl = getDurationFromDot(dot_bl, DURATION_LEAD, DURATION_SIDE, DURATION_TRAIL);
|
||||
float dur_br = getDurationFromDot(dot_br, DURATION_LEAD, DURATION_SIDE, DURATION_TRAIL);
|
||||
|
||||
// check direction of horizontal movement
|
||||
float isMovingRight = step(0.5, s.x);
|
||||
float isMovingLeft = step(0.5, -s.x);
|
||||
|
||||
// calculate vertical-rail durations
|
||||
float dot_right_edge = (dot_tr + dot_br) * 0.5;
|
||||
float dur_right_rail = getDurationFromDot(dot_right_edge, DURATION_LEAD, DURATION_SIDE, DURATION_TRAIL);
|
||||
|
||||
float dot_left_edge = (dot_tl + dot_bl) * 0.5;
|
||||
float dur_left_rail = getDurationFromDot(dot_left_edge, DURATION_LEAD, DURATION_SIDE, DURATION_TRAIL);
|
||||
|
||||
float final_dur_tl = mix(dur_tl, dur_left_rail, isMovingLeft);
|
||||
float final_dur_bl = mix(dur_bl, dur_left_rail, isMovingLeft);
|
||||
|
||||
float final_dur_tr = mix(dur_tr, dur_right_rail, isMovingRight);
|
||||
float final_dur_br = mix(dur_br, dur_right_rail, isMovingRight);
|
||||
|
||||
// calculate progress for each corner based on the duration and time since cursor change
|
||||
float prog_tl = ease(clamp(baseProgress / final_dur_tl, 0.0, 1.0));
|
||||
float prog_tr = ease(clamp(baseProgress / final_dur_tr, 0.0, 1.0));
|
||||
float prog_bl = ease(clamp(baseProgress / final_dur_bl, 0.0, 1.0));
|
||||
float prog_br = ease(clamp(baseProgress / final_dur_br, 0.0, 1.0));
|
||||
|
||||
// get the trial corner positions based on progress
|
||||
vec2 v_tl = mix(cp_tl, cc_tl, prog_tl);
|
||||
vec2 v_tr = mix(cp_tr, cc_tr, prog_tr);
|
||||
vec2 v_br = mix(cp_br, cc_br, prog_br);
|
||||
vec2 v_bl = mix(cp_bl, cc_bl, prog_bl);
|
||||
|
||||
// DRAWING THE TRAIL
|
||||
float sdfTrail = getSdfConvexQuad(vu, v_tl, v_tr, v_br, v_bl);
|
||||
|
||||
// --- FADE GRADIENT CALCULATION ---
|
||||
vec2 fragVec = vu - centerCP;
|
||||
|
||||
// project fragment onto movement vector, normalize to [0, 1]
|
||||
// 0.0 at tail, 1.0 at head
|
||||
// tiny epsilon to avoid division by zero if moveVec is (0,0)
|
||||
float fadeProgress = clamp(dot(fragVec, moveVec) / (dot(moveVec, moveVec) + 1e-6), 0.0, 1.0);
|
||||
|
||||
vec4 trail = TRAIL_COLOR;
|
||||
|
||||
float effectiveBlur = BLUR;
|
||||
if (BLUR < 2.5) {
|
||||
// no antialising on horizontal/vertical movement, fixes 'pulse' like thing on end cursor
|
||||
float isDiagonal = abs(s.x) * abs(s.y); // 1.0 if diagonal, 0.0 if H/V
|
||||
float effectiveBlur = mix(0.0, BLUR, isDiagonal);
|
||||
}
|
||||
float shapeAlpha = antialising(sdfTrail, effectiveBlur); // shape mask
|
||||
|
||||
if (FADE_ENABLED > 0.5) {
|
||||
// apply fade gradient along the trail
|
||||
// float fadeStart = 0.2;
|
||||
// float easedProgress = smoothstep(fadeStart, 1.0, fadeProgress);
|
||||
// easedProgress = pow(2.0, 10.0 * (fadeProgress - 1.0));
|
||||
float easedProgress = pow(fadeProgress, FADE_EXPONENT);
|
||||
trail.a *= easedProgress;
|
||||
}
|
||||
|
||||
float finalAlpha = trail.a * shapeAlpha;
|
||||
|
||||
// newColor.a to preserve the background alpha.
|
||||
newColor = mix(newColor, vec4(trail.rgb, newColor.a), finalAlpha);
|
||||
|
||||
// punch hole on the trail, so current cursor is drawn on top
|
||||
newColor = mix(newColor, fragColor, step(sdfCurrentCursor, 0.));
|
||||
|
||||
}
|
||||
|
||||
fragColor = newColor;
|
||||
}
|
||||
170
dot_config/ghostty/shaders/custom/bling99_compat.glsl
Normal file
170
dot_config/ghostty/shaders/custom/bling99_compat.glsl
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#define PI 3.141592653589793
|
||||
|
||||
float spotlightBeam(vec2 uv, vec2 origin, float angle, float width, float lengthFade) {
|
||||
vec2 p = uv - origin;
|
||||
|
||||
float c = cos(angle);
|
||||
float s = sin(angle);
|
||||
|
||||
// Rotate into beam space
|
||||
vec2 q = vec2(
|
||||
c * p.x + s * p.y,
|
||||
-s * p.x + c * p.y
|
||||
);
|
||||
|
||||
// Beam extends along +Y in local space
|
||||
float across = abs(q.x);
|
||||
float along = q.y;
|
||||
|
||||
float beamCore = exp(-pow(across / width, 2.0));
|
||||
float beamLength = smoothstep(-0.05, 0.10, along) * (1.0 - smoothstep(lengthFade, 1.35, along));
|
||||
|
||||
return beamCore * beamLength;
|
||||
}
|
||||
|
||||
float hash12(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float sparkleGrid(vec2 uv, float scale, float threshold, float speed) {
|
||||
vec2 g = uv * vec2(scale, scale * 0.56);
|
||||
vec2 id = floor(g);
|
||||
vec2 f = fract(g) - 0.5;
|
||||
|
||||
float n = hash12(id);
|
||||
float gate = step(threshold, n);
|
||||
float twinkle = pow(max(0.0, sin(iTime * speed + n * 6.2831853)), 28.0);
|
||||
|
||||
float diamond = 1.0 - smoothstep(0.02, 0.13, abs(f.x) + abs(f.y));
|
||||
|
||||
float flareX = (1.0 - smoothstep(0.000, 0.016, abs(f.y))) *
|
||||
(1.0 - smoothstep(0.000, 0.42, abs(f.x)));
|
||||
float flareY = (1.0 - smoothstep(0.000, 0.016, abs(f.x))) *
|
||||
(1.0 - smoothstep(0.000, 0.42, abs(f.y)));
|
||||
|
||||
return gate * twinkle * (diamond + 0.35 * flareX + 0.35 * flareY);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec2 px = 1.0 / iResolution.xy;
|
||||
|
||||
// Very light late-90s video wobble.
|
||||
float wobble = sin(uv.y * 90.0 + iTime * 2.0) * 0.0008
|
||||
+ sin(uv.y * 12.0 - iTime * 0.35) * 0.0010;
|
||||
|
||||
vec2 tUv = clamp(uv + vec2(wobble, 0.0), vec2(0.001), vec2(0.999));
|
||||
|
||||
// Tiny chromatic shift.
|
||||
vec3 src;
|
||||
src.r = texture(iChannel0, clamp(tUv + vec2(px.x * 1.1, 0.0), vec2(0.001), vec2(0.999))).r;
|
||||
src.g = texture(iChannel0, tUv).g;
|
||||
src.b = texture(iChannel0, clamp(tUv - vec2(px.x * 1.1, 0.0), vec2(0.001), vec2(0.999))).b;
|
||||
|
||||
float lum = dot(src, vec3(0.299, 0.587, 0.114));
|
||||
float glyph = smoothstep(0.06, 0.30, lum);
|
||||
|
||||
// Velvet / leather background.
|
||||
vec3 velvet = vec3(0.012, 0.007, 0.002);
|
||||
vec3 brown = vec3(0.075, 0.038, 0.010);
|
||||
vec3 bg = mix(velvet, brown, uv.y + 0.15 * sin(uv.x * 4.0 + iTime * 0.12));
|
||||
|
||||
// Cash Money gold.
|
||||
vec3 gold = vec3(1.00, 0.62, 0.10);
|
||||
vec3 paleGold = vec3(1.00, 0.88, 0.45);
|
||||
vec3 hotGold = mix(gold, paleGold, pow(lum, 0.65));
|
||||
|
||||
// Tint glyphs gold while preserving some original terminal color.
|
||||
vec3 col = mix(bg, src, glyph * 0.28);
|
||||
col = mix(col, hotGold + src * 0.28, glyph * 0.82);
|
||||
|
||||
// Chrome sweep, like jewelry-store lights / spinning rims.
|
||||
float sweep1 = pow(max(0.0, sin((uv.x * 1.8 + uv.y * 0.65) * PI * 2.0 - iTime * 0.55)), 22.0);
|
||||
float sweep2 = pow(max(0.0, sin((uv.x * -1.1 + uv.y * 1.20) * PI * 2.0 + iTime * 0.40)), 30.0);
|
||||
col += (sweep1 * 0.15 + sweep2 * 0.10) * vec3(1.0, 0.77, 0.32) * (0.35 + glyph);
|
||||
|
||||
// Independent moving spotlight trails
|
||||
float ray1 = spotlightBeam(
|
||||
uv,
|
||||
vec2(0.10, 1.10),
|
||||
-0.95 + 0.22 * sin(iTime * 0.63 + 0.3),
|
||||
0.045 + 0.008 * sin(iTime * 1.10 + 0.7),
|
||||
1.00
|
||||
);
|
||||
|
||||
float ray2 = spotlightBeam(
|
||||
uv,
|
||||
vec2(0.35, 1.12),
|
||||
-1.20 + 0.18 * sin(iTime * 0.47 + 1.7),
|
||||
0.055 + 0.006 * sin(iTime * 0.90 + 2.1),
|
||||
1.05
|
||||
);
|
||||
|
||||
float ray3 = spotlightBeam(
|
||||
uv,
|
||||
vec2(0.72, 1.08),
|
||||
-1.55 + 0.20 * sin(iTime * 0.71 + 2.8),
|
||||
0.050 + 0.010 * sin(iTime * 1.30 + 0.5),
|
||||
0.95
|
||||
);
|
||||
|
||||
float ray4 = spotlightBeam(
|
||||
uv,
|
||||
vec2(0.92, 1.15),
|
||||
-1.85 + 0.24 * sin(iTime * 0.58 + 4.0),
|
||||
0.060 + 0.007 * sin(iTime * 0.80 + 3.4),
|
||||
1.10
|
||||
);
|
||||
|
||||
// Optional faint upward beam from bottom-left for extra motion
|
||||
float ray5 = spotlightBeam(
|
||||
uv,
|
||||
vec2(-0.05, -0.05),
|
||||
0.70 + 0.15 * sin(iTime * 0.52 + 5.2),
|
||||
0.040 + 0.005 * sin(iTime * 1.00 + 1.3),
|
||||
0.90
|
||||
);
|
||||
|
||||
float rays = 0.0;
|
||||
rays += ray1 * (0.75 + 0.25 * sin(iTime * 0.90 + 0.2));
|
||||
rays += ray2 * (0.65 + 0.35 * sin(iTime * 0.70 + 1.9));
|
||||
rays += ray3 * (0.80 + 0.20 * sin(iTime * 1.10 + 2.6));
|
||||
rays += ray4 * (0.70 + 0.30 * sin(iTime * 0.85 + 4.3));
|
||||
rays += ray5 * (0.45 + 0.25 * sin(iTime * 0.95 + 3.1));
|
||||
|
||||
// Warm gold spotlight tint
|
||||
vec3 rayColorA = vec3(1.00, 0.74, 0.22);
|
||||
vec3 rayColorB = vec3(1.00, 0.86, 0.48);
|
||||
|
||||
// Mix two shades so it feels less flat
|
||||
vec3 spotlightColor = mix(rayColorA, rayColorB, 0.5 + 0.5 * sin(iTime * 0.33));
|
||||
|
||||
// Add trails mostly into background, not too hard on text
|
||||
col += rays * spotlightColor * (0.10 + 0.10 * (1.0 - glyph));
|
||||
|
||||
// Diamond glints.
|
||||
float spark = sparkleGrid(uv, 62.0, 0.978, 4.0);
|
||||
spark += 0.50 * sparkleGrid(uv + vec2(0.13, -0.09), 38.0, 0.965, 3.0);
|
||||
col += spark * vec3(1.0, 0.90, 0.55) * (0.8 + 0.5 * glyph);
|
||||
|
||||
// Gold frame around the terminal.
|
||||
float edgeD = min(min(uv.x, 1.0 - uv.x), min(uv.y, 1.0 - uv.y));
|
||||
float frame = 1.0 - smoothstep(0.000, 0.045, edgeD);
|
||||
float frameWave = pow(0.5 + 0.5 * sin((uv.x + uv.y) * 90.0 - iTime * 1.8), 8.0);
|
||||
col += frame * vec3(1.0, 0.72, 0.20) * (0.10 + 0.22 * frameWave);
|
||||
|
||||
// Scanline shimmer, not too heavy.
|
||||
float scan = 0.965 + 0.035 * sin(fragCoord.y * PI);
|
||||
col *= scan;
|
||||
|
||||
// Music-video vignette.
|
||||
float vig = 1.0 - smoothstep(0.22, 0.82, distance(uv, vec2(0.5)));
|
||||
col *= 0.78 + 0.22 * vig;
|
||||
|
||||
// Keep text readable.
|
||||
col = mix(col, src, glyph * 0.16);
|
||||
|
||||
fragColor = vec4(clamp(col, 0.0, 1.0), 1.0);
|
||||
}
|
||||
267
dot_config/ghostty/shaders/custom/cash_money_badge.glsl
Normal file
267
dot_config/ghostty/shaders/custom/cash_money_badge.glsl
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
#define PI 3.141592653589793
|
||||
|
||||
float smin(float a, float b, float k) {
|
||||
float h = max(k - abs(a - b), 0.0) / k;
|
||||
return min(a, b) - h * h * h * k * (1.0 / 6.0);
|
||||
}
|
||||
|
||||
float rectSDF(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
float fill(float d, float aa) {
|
||||
return 1.0 - smoothstep(0.0, aa, d);
|
||||
}
|
||||
|
||||
float stroke(float d, float w, float aa) {
|
||||
return 1.0 - smoothstep(0.0, aa, abs(d) - w);
|
||||
}
|
||||
|
||||
float box01(vec2 uv, vec2 c, vec2 s, float aa) {
|
||||
return fill(rectSDF(uv - c, s), aa);
|
||||
}
|
||||
|
||||
float frame01(vec2 uv, vec2 c, vec2 s, float w, float aa) {
|
||||
return stroke(rectSDF(uv - c, s), w, aa);
|
||||
}
|
||||
|
||||
float in01(vec2 uv) {
|
||||
return step(0.0, uv.x) * step(0.0, uv.y) * step(uv.x, 1.0) * step(uv.y, 1.0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Very simple block-letter glyphs in a 0..1 local cell.
|
||||
// Not perfect typography, but close enough to read.
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
float glyphC(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.22, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.52, 0.84), vec2(0.30, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.52, 0.16), vec2(0.30, 0.08), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphA(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.22, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.78, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.84), vec2(0.30, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.30, 0.08), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphS(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.50, 0.84), vec2(0.30, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.30, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.16), vec2(0.30, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.22, 0.67), vec2(0.10, 0.17), aa));
|
||||
m = max(m, box01(uv, vec2(0.78, 0.33), vec2(0.10, 0.17), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphH(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.22, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.78, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.30, 0.08), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphM(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.16, 0.50), vec2(0.09, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.84, 0.50), vec2(0.09, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.38, 0.65), vec2(0.08, 0.27), aa));
|
||||
m = max(m, box01(uv, vec2(0.62, 0.65), vec2(0.08, 0.27), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.84), vec2(0.25, 0.08), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphO(vec2 uv, float aa) {
|
||||
float outer = box01(uv, vec2(0.50, 0.50), vec2(0.34, 0.42), aa);
|
||||
float inner = box01(uv, vec2(0.50, 0.50), vec2(0.18, 0.24), aa);
|
||||
return max(0.0, outer - inner) * in01(uv);
|
||||
}
|
||||
|
||||
float glyphN(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.20, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.80, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.08, 0.42), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphE(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.22, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.52, 0.84), vec2(0.30, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.48, 0.50), vec2(0.26, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.52, 0.16), vec2(0.30, 0.08), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphY(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.22, 0.72), vec2(0.10, 0.20), aa));
|
||||
m = max(m, box01(uv, vec2(0.78, 0.72), vec2(0.10, 0.20), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.10, 0.12), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.20), vec2(0.10, 0.20), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphR(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.22, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.84), vec2(0.28, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.72, 0.68), vec2(0.10, 0.16), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.26, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.68, 0.24), vec2(0.10, 0.20), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float glyphD(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
m = max(m, box01(uv, vec2(0.22, 0.50), vec2(0.10, 0.42), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.84), vec2(0.26, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.16), vec2(0.26, 0.08), aa));
|
||||
m = max(m, box01(uv, vec2(0.74, 0.50), vec2(0.10, 0.34), aa));
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
float drawGlyph(int g, vec2 uv, float aa) {
|
||||
if (g == 0) return glyphC(uv, aa);
|
||||
if (g == 1) return glyphA(uv, aa);
|
||||
if (g == 2) return glyphS(uv, aa);
|
||||
if (g == 3) return glyphH(uv, aa);
|
||||
if (g == 4) return glyphM(uv, aa);
|
||||
if (g == 5) return glyphO(uv, aa);
|
||||
if (g == 6) return glyphN(uv, aa);
|
||||
if (g == 7) return glyphE(uv, aa);
|
||||
if (g == 8) return glyphY(uv, aa);
|
||||
if (g == 9) return glyphR(uv, aa);
|
||||
if (g == 10) return glyphD(uv, aa);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
float placeGlyph(vec2 q, vec4 box, int glyphId, float aa) {
|
||||
vec2 uv = (q - box.xy) / (box.zw - box.xy);
|
||||
return drawGlyph(glyphId, uv, aa);
|
||||
}
|
||||
|
||||
float dollarMark(vec2 uv, float aa) {
|
||||
float m = 0.0;
|
||||
|
||||
// vertical bar
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.05, 0.42), aa));
|
||||
|
||||
// top/bottom heavy bars to make a chunky $
|
||||
m = max(m, box01(uv, vec2(0.50, 0.82), vec2(0.22, 0.10), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.50), vec2(0.22, 0.10), aa));
|
||||
m = max(m, box01(uv, vec2(0.50, 0.18), vec2(0.22, 0.10), aa));
|
||||
|
||||
// left upper / right lower chunks
|
||||
m = max(m, box01(uv, vec2(0.30, 0.66), vec2(0.10, 0.18), aa));
|
||||
m = max(m, box01(uv, vec2(0.70, 0.34), vec2(0.10, 0.18), aa));
|
||||
|
||||
return m * in01(uv);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec4 base = texture(iChannel0, uv);
|
||||
vec3 col = base.rgb;
|
||||
|
||||
float aa = 1.6 / iResolution.y;
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Bouncing rectangular badge, DVD-logo style
|
||||
// ----------------------------------------------------------
|
||||
vec2 badgeSize = vec2(0.18, 0.44);
|
||||
vec2 minP = badgeSize * 0.5 + vec2(0.02, 0.03);
|
||||
vec2 maxP = vec2(1.0) - minP;
|
||||
|
||||
vec2 travel = maxP - minP;
|
||||
vec2 phase = fract(vec2(iTime * 0.060, iTime * 0.047) + vec2(0.21, 0.58));
|
||||
vec2 tri = abs(phase * 2.0 - 1.0);
|
||||
vec2 center = minP + travel * tri;
|
||||
|
||||
vec2 p = uv - center;
|
||||
p.x *= iResolution.x / iResolution.y;
|
||||
|
||||
vec2 halfSize = vec2(badgeSize.x * 0.5 * iResolution.x / iResolution.y, badgeSize.y * 0.5);
|
||||
|
||||
// q = normalized coordinates inside the badge
|
||||
vec2 q = p / halfSize;
|
||||
q = q * 0.5 + 0.5;
|
||||
|
||||
float outer = fill(rectSDF(p, halfSize), aa);
|
||||
float border = frame01(p, vec2(0.0), halfSize, 0.006, aa);
|
||||
|
||||
// shadow
|
||||
float shadow = fill(rectSDF(p - vec2(0.010, -0.012), halfSize), aa) * 0.18;
|
||||
col = mix(col, col * 0.80, shadow);
|
||||
|
||||
// white sticker body
|
||||
vec3 logoCol = vec3(0.0);
|
||||
logoCol += outer * vec3(0.96);
|
||||
logoCol = mix(logoCol, vec3(0.04), border);
|
||||
|
||||
// top word: CASH MONEY
|
||||
float top = 0.0;
|
||||
float y0 = 0.78;
|
||||
float y1 = 0.96;
|
||||
float w = 0.075;
|
||||
float gap = 0.010;
|
||||
|
||||
top = max(top, placeGlyph(q, vec4(0.04, y0, 0.04 + w, y1), 0, aa)); // C
|
||||
top = max(top, placeGlyph(q, vec4(0.04 + 1.0*(w+gap), y0, 0.04 + 1.0*(w+gap) + w, y1), 1, aa)); // A
|
||||
top = max(top, placeGlyph(q, vec4(0.04 + 2.0*(w+gap), y0, 0.04 + 2.0*(w+gap) + w, y1), 2, aa)); // S
|
||||
top = max(top, placeGlyph(q, vec4(0.04 + 3.0*(w+gap), y0, 0.04 + 3.0*(w+gap) + w, y1), 3, aa)); // H
|
||||
|
||||
float start2 = 0.40;
|
||||
top = max(top, placeGlyph(q, vec4(start2 + 0.0*(w+gap), y0, start2 + 0.0*(w+gap) + w, y1), 4, aa)); // M
|
||||
top = max(top, placeGlyph(q, vec4(start2 + 1.0*(w+gap), y0, start2 + 1.0*(w+gap) + w, y1), 5, aa)); // O
|
||||
top = max(top, placeGlyph(q, vec4(start2 + 2.0*(w+gap), y0, start2 + 2.0*(w+gap) + w, y1), 6, aa)); // N
|
||||
top = max(top, placeGlyph(q, vec4(start2 + 3.0*(w+gap), y0, start2 + 3.0*(w+gap) + w, y1), 7, aa)); // E
|
||||
top = max(top, placeGlyph(q, vec4(start2 + 4.0*(w+gap), y0, start2 + 4.0*(w+gap) + w, y1), 8, aa)); // Y
|
||||
|
||||
// bottom word: RECORDS
|
||||
float bottom = 0.0;
|
||||
float by0 = 0.03;
|
||||
float by1 = 0.19;
|
||||
float bw = 0.095;
|
||||
float bg = 0.012;
|
||||
float bstart = 0.10;
|
||||
|
||||
bottom = max(bottom, placeGlyph(q, vec4(bstart + 0.0*(bw+bg), by0, bstart + 0.0*(bw+bg) + bw, by1), 9, aa)); // R
|
||||
bottom = max(bottom, placeGlyph(q, vec4(bstart + 1.0*(bw+bg), by0, bstart + 1.0*(bw+bg) + bw, by1), 7, aa)); // E
|
||||
bottom = max(bottom, placeGlyph(q, vec4(bstart + 2.0*(bw+bg), by0, bstart + 2.0*(bw+bg) + bw, by1), 0, aa)); // C
|
||||
bottom = max(bottom, placeGlyph(q, vec4(bstart + 3.0*(bw+bg), by0, bstart + 3.0*(bw+bg) + bw, by1), 5, aa)); // O
|
||||
bottom = max(bottom, placeGlyph(q, vec4(bstart + 4.0*(bw+bg), by0, bstart + 4.0*(bw+bg) + bw, by1), 9, aa)); // R
|
||||
bottom = max(bottom, placeGlyph(q, vec4(bstart + 5.0*(bw+bg), by0, bstart + 5.0*(bw+bg) + bw, by1), 10, aa)); // D
|
||||
bottom = max(bottom, placeGlyph(q, vec4(bstart + 6.0*(bw+bg), by0, bstart + 6.0*(bw+bg) + bw, by1), 2, aa)); // S
|
||||
|
||||
// central $
|
||||
vec2 suv = (q - vec2(0.18, 0.23)) / vec2(0.64, 0.50);
|
||||
float dollar = dollarMark(suv, aa);
|
||||
|
||||
// black print
|
||||
float printMask = max(max(top, bottom), dollar);
|
||||
logoCol = mix(logoCol, vec3(0.03), printMask);
|
||||
|
||||
// small gold glint so it still fits the bling theme
|
||||
float glint = pow(max(0.0, sin((uv.x * 4.0 + uv.y * 2.0) * PI * 2.0 - iTime * 1.4)), 18.0);
|
||||
logoCol += outer * glint * vec3(1.0, 0.84, 0.35) * 0.12;
|
||||
|
||||
// subtle sticker highlight
|
||||
float shine = 1.0 - smoothstep(0.0, 0.25, abs(q.x - 0.25) + abs(q.y - 0.78));
|
||||
logoCol += outer * shine * vec3(1.0) * 0.08;
|
||||
|
||||
// composite behind text
|
||||
col = mix(col, col + logoCol, outer * 0.22);
|
||||
|
||||
fragColor = vec4(clamp(col, 0.0, 1.0), base.a);
|
||||
}
|
||||
142
dot_config/ghostty/shaders/custom/cash_money_dvd.glsl
Normal file
142
dot_config/ghostty/shaders/custom/cash_money_dvd.glsl
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#define PI 3.141592653589793
|
||||
|
||||
float sdEllipse(vec2 p, vec2 r) {
|
||||
vec2 q = p / r;
|
||||
return (length(q) - 1.0) * min(r.x, r.y);
|
||||
}
|
||||
|
||||
float sdCircle(vec2 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
float sdBox(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
float opStroke(float d, float w) {
|
||||
return abs(d) - w;
|
||||
}
|
||||
|
||||
float fill(float d) {
|
||||
return 1.0 - smoothstep(0.0, 0.004, d);
|
||||
}
|
||||
|
||||
float stroke(float d, float w) {
|
||||
return 1.0 - smoothstep(0.0, 0.004, opStroke(d, w));
|
||||
}
|
||||
|
||||
// Simple dollar sign SDF-ish shape
|
||||
float dollarSign(vec2 p) {
|
||||
float s = 0.0;
|
||||
|
||||
// main vertical bar
|
||||
float bar = fill(sdBox(p, vec2(0.018, 0.18)));
|
||||
|
||||
// upper curve
|
||||
vec2 pu = p - vec2(0.02, 0.07);
|
||||
float upperOuter = stroke(sdCircle(pu, 0.11), 0.020);
|
||||
float upperCut = fill(sdBox(pu - vec2(-0.07, 0.00), vec2(0.08, 0.14)));
|
||||
float upper = upperOuter * (1.0 - upperCut);
|
||||
|
||||
// lower curve
|
||||
vec2 pl = p - vec2(-0.02, -0.07);
|
||||
float lowerOuter = stroke(sdCircle(pl, 0.11), 0.020);
|
||||
float lowerCut = fill(sdBox(pl - vec2(0.07, 0.00), vec2(0.08, 0.14)));
|
||||
float lower = lowerOuter * (1.0 - lowerCut);
|
||||
|
||||
s = max(bar, max(upper, lower));
|
||||
return s;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec4 base = texture(iChannel0, uv);
|
||||
vec3 col = base.rgb;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Bouncing "DVD logo" style motion
|
||||
// ------------------------------------------------------------------
|
||||
vec2 logoSize = vec2(0.23, 0.13); // width/height of medallion in UV space
|
||||
vec2 minP = logoSize * 0.5 + vec2(0.03, 0.04);
|
||||
vec2 maxP = vec2(1.0) - minP;
|
||||
|
||||
// Ping-pong motion
|
||||
vec2 travel = maxP - minP;
|
||||
vec2 phase = fract(vec2(iTime * 0.070, iTime * 0.052) + vec2(0.17, 0.61));
|
||||
vec2 tri = abs(phase * 2.0 - 1.0);
|
||||
vec2 center = minP + travel * tri;
|
||||
|
||||
// Local coordinates around logo center
|
||||
vec2 p = uv - center;
|
||||
p.x *= iResolution.x / iResolution.y; // aspect correction
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Cash Money inspired medallion
|
||||
// ------------------------------------------------------------------
|
||||
float outer = sdEllipse(p, vec2(0.17, 0.095));
|
||||
float inner = sdEllipse(p, vec2(0.145, 0.078));
|
||||
float core = sdEllipse(p, vec2(0.122, 0.060));
|
||||
|
||||
float outerFill = fill(outer);
|
||||
float innerRing = stroke(inner, 0.010);
|
||||
float coreFill = fill(core);
|
||||
|
||||
// Rim beading / jewelry vibe
|
||||
float angle = atan(p.y, p.x);
|
||||
float beads = pow(0.5 + 0.5 * sin(angle * 26.0 - iTime * 2.2), 8.0);
|
||||
beads *= stroke(sdEllipse(p, vec2(0.158, 0.086)), 0.008);
|
||||
|
||||
// Chrome/gold light sweep
|
||||
float sweep = pow(max(0.0, sin((uv.x * 4.0 + uv.y * 2.6) * PI * 2.0 - iTime * 1.7)), 18.0);
|
||||
|
||||
vec3 darkGold = vec3(0.28, 0.12, 0.02);
|
||||
vec3 gold = vec3(0.95, 0.67, 0.16);
|
||||
vec3 paleGold = vec3(1.00, 0.88, 0.52);
|
||||
vec3 diamond = vec3(1.00, 0.96, 0.85);
|
||||
|
||||
vec3 logoCol = vec3(0.0);
|
||||
|
||||
// outer medallion
|
||||
logoCol += outerFill * mix(darkGold, gold, 0.65);
|
||||
logoCol += innerRing * paleGold * 0.9;
|
||||
logoCol += beads * paleGold * 0.8;
|
||||
logoCol += coreFill * mix(gold, paleGold, 0.35);
|
||||
|
||||
// embossed center
|
||||
float emboss = 0.5 + 0.5 * sin(p.x * 28.0 + p.y * 12.0 - iTime * 0.6);
|
||||
logoCol += coreFill * emboss * vec3(0.10, 0.05, 0.01);
|
||||
|
||||
// dollar sign centerpiece
|
||||
float ds = dollarSign(p * 1.7);
|
||||
logoCol = mix(logoCol, diamond, ds * 0.9);
|
||||
logoCol += ds * paleGold * 0.35;
|
||||
|
||||
// little sparkle hits
|
||||
float sparkle1 = exp(-length((p - vec2(-0.07, 0.03)) * vec2(1.0, 1.2)) * 60.0);
|
||||
float sparkle2 = exp(-length((p - vec2(0.08, -0.01)) * vec2(1.0, 1.2)) * 80.0);
|
||||
float cross1 = (1.0 - smoothstep(0.0, 0.004, abs(p.x + 0.07))) * (1.0 - smoothstep(0.0, 0.05, abs(p.y - 0.03)));
|
||||
cross1 += (1.0 - smoothstep(0.0, 0.004, abs(p.y - 0.03))) * (1.0 - smoothstep(0.0, 0.05, abs(p.x + 0.07)));
|
||||
float cross2 = (1.0 - smoothstep(0.0, 0.003, abs(p.x - 0.08))) * (1.0 - smoothstep(0.0, 0.04, abs(p.y + 0.01)));
|
||||
cross2 += (1.0 - smoothstep(0.0, 0.003, abs(p.y + 0.01))) * (1.0 - smoothstep(0.0, 0.04, abs(p.x - 0.08)));
|
||||
|
||||
float twinkle = 0.65 + 0.35 * sin(iTime * 5.0);
|
||||
logoCol += (sparkle1 * cross1 + sparkle2 * cross2) * paleGold * twinkle * 0.9;
|
||||
|
||||
// moving light sweep across logo
|
||||
logoCol += outerFill * sweep * vec3(1.0, 0.92, 0.60) * 0.45;
|
||||
|
||||
// subtle shadow behind logo
|
||||
float shadow = fill(sdEllipse(p - vec2(0.010, -0.010), vec2(0.17, 0.095)));
|
||||
shadow *= 0.18;
|
||||
|
||||
// Logo mask
|
||||
float logoMask = outerFill;
|
||||
|
||||
// Keep it in background so text stays readable
|
||||
// Darken behind medallion slightly, then add logo
|
||||
col = mix(col, col * 0.82, shadow);
|
||||
col = mix(col, col + logoCol, logoMask * 0.32);
|
||||
|
||||
fragColor = vec4(clamp(col, 0.0, 1.0), base.a);
|
||||
}
|
||||
5
dot_config/ghostty/shaders/custom/probe_invert.glsl
Normal file
5
dot_config/ghostty/shaders/custom/probe_invert.glsl
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec4 c = texture(iChannel0, uv);
|
||||
fragColor = vec4(1.0 - c.rgb, 1.0);
|
||||
}
|
||||
30
dot_config/ghostty/shaders/dot_claude/settings.local.json
Normal file
30
dot_config/ghostty/shaders/dot_claude/settings.local.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(mount)",
|
||||
"Bash(getenforce)",
|
||||
"Bash(podman --version)",
|
||||
"Read(//etc/**)",
|
||||
"Bash(grep \"^$\\(whoami\\):\")",
|
||||
"Bash(mkdir -p \"/run/media/mr0xb/1TB Samsung 860/postgres-data\")",
|
||||
"Bash(mkdir -p ~/podman)",
|
||||
"Bash(podman unshare *)",
|
||||
"Bash(podman secret *)",
|
||||
"Bash(openssl rand *)",
|
||||
"Bash(podman kube *)",
|
||||
"Bash(podman pod *)",
|
||||
"Bash(podman ps *)",
|
||||
"Bash(podman logs *)",
|
||||
"Bash(rm -rf \"/run/media/mr0xb/1TB Samsung 860/postgres-data\")",
|
||||
"Bash(podman exec *)",
|
||||
"Bash(podman inspect *)",
|
||||
"Bash(podman image *)",
|
||||
"Bash(podman run *)",
|
||||
"Bash(chcon -Rt container_file_t \"/run/media/mr0xb/1TB Samsung 860/postgres-data\")",
|
||||
"Bash(PGPASSWORD='ksJZqsVlMZZ2G+f6qSp+GdykGIIKjZq3' psql -h 127.0.0.1 -p 5432 -U postgres -c \"select 1;\")",
|
||||
"Bash(timeout 2 bash -c \"echo > /dev/tcp/127.0.0.1/5432\")",
|
||||
"Bash(ip -4 addr show)",
|
||||
"Bash(timeout 2 bash -c \"echo > /dev/tcp/192.168.1.69/5432\")"
|
||||
]
|
||||
}
|
||||
}
|
||||
109
dot_config/ghostty/shaders/fireworks-rockets.glsl
Normal file
109
dot_config/ghostty/shaders/fireworks-rockets.glsl
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
// This Ghostty shader is a lightly modified port of https://www.shadertoy.com/view/4dBGRw
|
||||
|
||||
#define BLACK_BLEND_THRESHOLD .4
|
||||
|
||||
//Creates a diagonal red-and-white striped pattern.
|
||||
vec3 barberpole(vec2 pos, vec2 rocketpos) {
|
||||
float d = (pos.x - rocketpos.x) + (pos.y - rocketpos.y);
|
||||
vec3 col = vec3(1.0);
|
||||
|
||||
d = mod(d * 20., 2.0);
|
||||
if (d > 1.0) {
|
||||
col = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 rocket(vec2 pos, vec2 rocketpos) {
|
||||
vec3 col = vec3(0.0);
|
||||
float f = 0.;
|
||||
float absx = abs(rocketpos.x - pos.x);
|
||||
float absy = abs(rocketpos.y - pos.y);
|
||||
|
||||
// Wooden stick
|
||||
if (absx < 0.01 && absy < 0.22) {
|
||||
col = vec3(1.0, 0.5, 0.5);
|
||||
}
|
||||
|
||||
// Barberpole
|
||||
if (absx < 0.05 && absy < 0.15) {
|
||||
col = barberpole(pos, rocketpos);
|
||||
}
|
||||
|
||||
// Rocket Point
|
||||
float pointw = (rocketpos.y - pos.y - 0.25) * -0.7;
|
||||
if ((rocketpos.y - pos.y) > 0.1) {
|
||||
f = smoothstep(pointw - 0.001, pointw + 0.001, absx);
|
||||
|
||||
col = mix(vec3(1.0, 0.0, 0.0), col, f);
|
||||
}
|
||||
|
||||
// Shadow
|
||||
f = -.5 + smoothstep(-0.05, 0.05, (rocketpos.x - pos.x));
|
||||
col *= 0.7 + f;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
float rand(float val, float seed) {
|
||||
return cos(val * sin(val * seed) * seed);
|
||||
}
|
||||
|
||||
float distance2(in vec2 a, in vec2 b) {
|
||||
return dot(a - b, a - b);
|
||||
}
|
||||
|
||||
mat2 rr = mat2(cos(1.0), -sin(1.0), sin(1.0), cos(1.0));
|
||||
|
||||
vec3 drawParticles(vec2 pos, vec3 particolor, float time, vec2 cpos, float gravity, float seed, float timelength) {
|
||||
vec3 col = vec3(0.0);
|
||||
vec2 pp = vec2(1.0, 0.0);
|
||||
for (float i = 1.0; i <= 128.0; i++) {
|
||||
float d = rand(i, seed);
|
||||
float fade = (i / 128.0) * time;
|
||||
vec2 particpos = cpos + time * pp * d;
|
||||
pp = rr * pp;
|
||||
col = mix(particolor / fade, col, smoothstep(0.0, 0.0001, distance2(particpos, pos)));
|
||||
}
|
||||
col *= smoothstep(0.0, 1.0, (timelength - time) / timelength);
|
||||
|
||||
return col;
|
||||
}
|
||||
vec3 drawFireworks(float time, vec2 uv, vec3 particolor, float seed) {
|
||||
float timeoffset = 2.0;
|
||||
vec3 col = vec3(0.0);
|
||||
if (time <= 0.) {
|
||||
return col;
|
||||
}
|
||||
if (mod(time, 6.0) > timeoffset) {
|
||||
col = drawParticles(uv, particolor, mod(time, 6.0) - timeoffset, vec2(rand(ceil(time / 6.0), seed), -0.5), 0.5, ceil(time / 6.0), seed);
|
||||
} else {
|
||||
col = rocket(uv * 3., vec2(3. * rand(ceil(time / 6.0), seed), 3. * (-0.5 + (timeoffset - mod(time, 6.0)))));
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
vec2 uv = 1.0 - 2.0 * fragCoord.xy / iResolution.xy;
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
vec3 col = vec3(0.1, 0.1, 0.2);
|
||||
|
||||
// Flip the y-axis so that the rocket is drawn from the bottom of the screen
|
||||
uv.y = -uv.y;
|
||||
|
||||
col += 0.1 * uv.y;
|
||||
|
||||
col += drawFireworks(iTime, uv, vec3(1.0, 0.1, 0.1), 1.);
|
||||
col += drawFireworks(iTime - 2.0, uv, vec3(0.0, 1.0, 0.5), 2.);
|
||||
col += drawFireworks(iTime - 4.0, uv, vec3(1.0, 1.0, 0.1), 3.);
|
||||
|
||||
vec2 termUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, termUV);
|
||||
|
||||
float alpha = step(length(terminalColor.rgb), BLACK_BLEND_THRESHOLD);
|
||||
vec3 blendedColor = mix(terminalColor.rgb * 1.0, col.rgb * 0.3, alpha);
|
||||
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
139
dot_config/ghostty/shaders/galaxy.glsl
Normal file
139
dot_config/ghostty/shaders/galaxy.glsl
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
float triangle(float x, float period) {
|
||||
return 2.0 * abs(3.0* ((x / period) - floor((x / period) + 0.5))) - 1.0;
|
||||
}
|
||||
|
||||
float field(in vec3 position) {
|
||||
float strength = 7.0 + 0.03 * log(1.0e-6 + fract(sin(iTime) * 373.11));
|
||||
float accumulated = 0.0;
|
||||
float previousMagnitude = 0.0;
|
||||
float totalWeight = 0.0;
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
float magnitude = dot(position, position);
|
||||
position = abs(position) / magnitude + vec3(-0.5, -0.8 + 0.1 * sin(-iTime * 0.1 + 2.0), -1.1 + 0.3 * cos(iTime * 0.3));
|
||||
float weight = exp(-float(i) / 7.0);
|
||||
accumulated += weight * exp(-strength * pow(abs(magnitude - previousMagnitude), 2.3));
|
||||
totalWeight += weight;
|
||||
previousMagnitude = magnitude;
|
||||
}
|
||||
|
||||
return max(0.0, 5.0 * accumulated / totalWeight - 0.7);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
const float baseSpeed = 0.02;
|
||||
const int maxIterations = 16;
|
||||
const float formulaParameter = 0.79;
|
||||
const float volumeSteps = 7.0;
|
||||
const float stepSize = 0.24;
|
||||
const float zoomFactor = 0.1;
|
||||
const float tilingFactor = 0.85;
|
||||
const float baseBrightness = 0.0008;
|
||||
const float darkMatter = 0.2;
|
||||
const float distanceFading = 0.56;
|
||||
const float colorSaturation = 0.9;
|
||||
const float transverseMotion = 0.2;
|
||||
const float cloudOpacity = 0.28;
|
||||
const float zoomSpeed = 0.00002;
|
||||
const float effectIntensity = 0.02; // 0.0 = terminal only, 1.0 = original intensity
|
||||
|
||||
vec2 normalizedCoordinates = 2.0 * fragCoord.xy / vec2(512) - 1.0;
|
||||
vec2 scaledCoordinates = normalizedCoordinates * vec2(512) / 512.0;
|
||||
|
||||
float timeElapsed = iTime;
|
||||
float speedAdjustment = -baseSpeed;
|
||||
float formulaAdjustment = formulaParameter;
|
||||
|
||||
speedAdjustment = zoomSpeed * cos(iTime * 0.02 + 3.1415926 / 4.0);
|
||||
|
||||
vec2 uvCoordinates = scaledCoordinates;
|
||||
|
||||
float rotationXZ = 0.9;
|
||||
float rotationYZ = -0.6;
|
||||
float rotationXY = 0.9 + iTime * 0.08;
|
||||
|
||||
mat2 rotationMatrixXZ = mat2(vec2(cos(rotationXZ), sin(rotationXZ)), vec2(-sin(rotationXZ), cos(rotationXZ)));
|
||||
mat2 rotationMatrixYZ = mat2(vec2(cos(rotationYZ), sin(rotationYZ)), vec2(-sin(rotationYZ), cos(rotationYZ)));
|
||||
mat2 rotationMatrixXY = mat2(vec2(cos(rotationXY), sin(rotationXY)), vec2(-sin(rotationXY), cos(rotationXY)));
|
||||
|
||||
vec2 canvasCenter = vec2(0.5, 0.5);
|
||||
vec3 rayDirection = vec3(uvCoordinates * zoomFactor, 1.0);
|
||||
vec3 cameraPosition = vec3(0.0, 0.0, 0.0);
|
||||
cameraPosition.x -= 2.0 * (canvasCenter.x - 0.5);
|
||||
cameraPosition.y -= 2.0 * (canvasCenter.y - 0.5);
|
||||
|
||||
vec3 forwardVector = vec3(0.0, 0.0, 1.0);
|
||||
cameraPosition.x += transverseMotion * cos(0.01 * iTime) + 0.001 * iTime;
|
||||
cameraPosition.y += transverseMotion * sin(0.01 * iTime) + 0.001 * iTime;
|
||||
cameraPosition.z += 0.003 * iTime;
|
||||
|
||||
rayDirection.xz *= rotationMatrixXZ;
|
||||
forwardVector.xz *= rotationMatrixXZ;
|
||||
rayDirection.yz *= rotationMatrixYZ;
|
||||
forwardVector.yz *= rotationMatrixYZ;
|
||||
|
||||
cameraPosition.xy *= -1.0 * rotationMatrixXY;
|
||||
cameraPosition.xz *= rotationMatrixXZ;
|
||||
cameraPosition.yz *= rotationMatrixYZ;
|
||||
|
||||
float zoomOffset = (timeElapsed - 3311.0) * speedAdjustment;
|
||||
cameraPosition += forwardVector * zoomOffset;
|
||||
float sampleOffset = mod(zoomOffset, stepSize);
|
||||
float normalizedSampleOffset = sampleOffset / stepSize;
|
||||
|
||||
float stepDistance = 0.24;
|
||||
float secondaryStepDistance = stepDistance + stepSize / 2.0;
|
||||
vec3 accumulatedColor = vec3(0.0);
|
||||
float fieldContribution = 0.0;
|
||||
vec3 backgroundColor = vec3(0.0);
|
||||
|
||||
for (float stepIndex = 0.0; stepIndex < volumeSteps; ++stepIndex) {
|
||||
vec3 primaryPosition = cameraPosition + (stepDistance + sampleOffset) * rayDirection;
|
||||
vec3 secondaryPosition = cameraPosition + (secondaryStepDistance + sampleOffset) * rayDirection;
|
||||
|
||||
primaryPosition = abs(vec3(tilingFactor) - mod(primaryPosition, vec3(tilingFactor * 2.0)));
|
||||
secondaryPosition = abs(vec3(tilingFactor) - mod(secondaryPosition, vec3(tilingFactor * 2.0)));
|
||||
|
||||
fieldContribution = field(secondaryPosition);
|
||||
|
||||
float particleAccumulator = 0.0, particleDistance = 0.0;
|
||||
for (int i = 0; i < maxIterations; ++i) {
|
||||
primaryPosition = abs(primaryPosition) / dot(primaryPosition, primaryPosition) - formulaAdjustment;
|
||||
float distanceChange = abs(length(primaryPosition) - particleDistance);
|
||||
particleAccumulator += i > 2 ? min(12.0, distanceChange) : distanceChange;
|
||||
particleDistance = length(primaryPosition);
|
||||
}
|
||||
particleAccumulator *= particleAccumulator * particleAccumulator;
|
||||
|
||||
float fadeFactor = pow(distanceFading, max(0.0, float(stepIndex) - normalizedSampleOffset));
|
||||
accumulatedColor += vec3(stepDistance, stepDistance * stepDistance, stepDistance * stepDistance * stepDistance * stepDistance)
|
||||
* particleAccumulator * baseBrightness * fadeFactor;
|
||||
backgroundColor += mix(0.4, 1.0, cloudOpacity) * vec3(1.8 * fieldContribution * fieldContribution * fieldContribution,
|
||||
1.4 * fieldContribution * fieldContribution, fieldContribution) * fadeFactor;
|
||||
stepDistance += stepSize;
|
||||
secondaryStepDistance += stepSize;
|
||||
}
|
||||
|
||||
accumulatedColor = mix(vec3(length(accumulatedColor)), accumulatedColor, colorSaturation);
|
||||
|
||||
vec4 foregroundColor = vec4(accumulatedColor * 0.01, 1.0);
|
||||
backgroundColor *= cloudOpacity;
|
||||
backgroundColor.b *= 1.8;
|
||||
backgroundColor.r *= 0.05;
|
||||
|
||||
backgroundColor.b = 0.5 * mix(backgroundColor.g, backgroundColor.b, 0.8);
|
||||
backgroundColor.g = 0.0;
|
||||
backgroundColor.bg = mix(backgroundColor.gb, backgroundColor.bg, 0.5 * (cos(iTime * 0.01) + 1.0));
|
||||
|
||||
vec2 terminalUV = fragCoord.xy / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, terminalUV);
|
||||
|
||||
float brightnessThreshold = 0.1;
|
||||
float terminalBrightness = dot(terminalColor.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
|
||||
if (terminalBrightness < brightnessThreshold) {
|
||||
fragColor = mix(terminalColor, vec4(foregroundColor.rgb + backgroundColor, 1.0), 0.24 * effectIntensity);
|
||||
} else {
|
||||
fragColor = terminalColor;
|
||||
}
|
||||
}
|
||||
202
dot_config/ghostty/shaders/geocities.glsl
Normal file
202
dot_config/ghostty/shaders/geocities.glsl
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
// geocities.glsl — a tribute to the golden age of blinking, tiled,
|
||||
// under-construction personal homepages. Caution-stripe wallpaper,
|
||||
// a rainbow sparkle field with hard blink (not a gentle twinkle),
|
||||
// a scrolling pixel-font "UNDER CONSTRUCTION" marquee, and a bouncing
|
||||
// rotating star badge, DVD-logo style.
|
||||
|
||||
// transparent background
|
||||
const bool transparent = true;
|
||||
|
||||
// terminal contents luminance threshold to be considered background (0.0 to 1.0)
|
||||
const float threshold = 0.02;
|
||||
|
||||
// show/hide individual gimmicks
|
||||
const bool showStripes = true;
|
||||
const bool showSparkles = true;
|
||||
const bool showMarquee = true;
|
||||
const bool showBadge = true;
|
||||
|
||||
// caution-stripe wallpaper opacity (0.0 to 1.0)
|
||||
const float stripeOpacity = 0.02;
|
||||
|
||||
// sparkle field brightness
|
||||
const float sparkleIntensity = 0.1;
|
||||
|
||||
// marquee scroll speed, in pixels per second
|
||||
const float scrollSpeed = 90.0;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// helpers
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
float luminance(vec3 color) {
|
||||
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
float hash21(vec2 p) {
|
||||
p = fract(p * vec2(233.34, 851.73));
|
||||
p += dot(p, p + 23.45);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
// 0 -> 1 -> 0 triangle wave, used to ping-pong the bouncing badge
|
||||
float triangleWave(float x, float period) {
|
||||
float t = fract(x / period);
|
||||
return 1.0 - abs(2.0 * t - 1.0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// tiny 5x7 pixel font, just enough glyphs to spell "UNDER CONSTRUCTION"
|
||||
// each row is packed as a 5-bit value, bit weight 16 = leftmost column
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
const int FONT_ROWS = 7;
|
||||
const int FONT[77] = int[77](
|
||||
0, 0, 0, 0, 0, 0, 0, // 0: space
|
||||
17, 17, 17, 17, 17, 17, 14, // 1: U
|
||||
17, 25, 21, 21, 19, 17, 17, // 2: N
|
||||
30, 17, 17, 17, 17, 17, 30, // 3: D
|
||||
31, 16, 16, 30, 16, 16, 31, // 4: E
|
||||
30, 17, 17, 30, 20, 18, 17, // 5: R
|
||||
15, 16, 16, 16, 16, 16, 15, // 6: C
|
||||
14, 17, 17, 17, 17, 17, 14, // 7: O
|
||||
15, 16, 16, 14, 1, 1, 30, // 8: S
|
||||
31, 4, 4, 4, 4, 4, 4, // 9: T
|
||||
31, 4, 4, 4, 4, 4, 31 // 10: I
|
||||
);
|
||||
|
||||
// "UNDER CONSTRUCTION" as indices into the glyph table above
|
||||
const int MSG_LEN = 18;
|
||||
const int MSG[18] = int[18](1, 2, 3, 4, 5, 0, 6, 7, 2, 8, 9, 5, 1, 6, 9, 10, 7, 2);
|
||||
|
||||
float fontBit(int code, int row, int col) {
|
||||
int rowVal = FONT[code * FONT_ROWS + row];
|
||||
float shifted = floor(float(rowVal) / pow(2.0, float(4 - col)));
|
||||
return mod(shifted, 2.0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// background gimmicks
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
vec3 hazardStripes(vec2 fragCoord) {
|
||||
float stripeWidth = 18.0;
|
||||
float diag = (fragCoord.x + fragCoord.y) + iTime * 40.0;
|
||||
float m = mod(diag, stripeWidth * 2.0);
|
||||
vec3 yellow = vec3(1.0, 0.82, 0.0);
|
||||
vec3 blk = vec3(0.05);
|
||||
return m < stripeWidth ? yellow : blk;
|
||||
}
|
||||
|
||||
vec3 sparkleStars(vec2 uv, vec2 resolution) {
|
||||
vec2 gridUV = uv;
|
||||
gridUV.x *= resolution.x / resolution.y;
|
||||
gridUV *= 26.0;
|
||||
|
||||
vec2 ipos = floor(gridUV);
|
||||
vec2 fpos = fract(gridUV);
|
||||
|
||||
// only a fraction of cells host a star
|
||||
float rnd = hash21(ipos);
|
||||
if (rnd > 0.12) return vec3(0.0);
|
||||
|
||||
vec2 center = vec2(hash21(ipos + 3.1), hash21(ipos + 7.7));
|
||||
float d = length(fpos - center);
|
||||
|
||||
// hard on/off blink rather than a smooth twinkle, tacky on purpose
|
||||
float phase = hash21(ipos + 11.0) * 10.0;
|
||||
float blink = step(0.5, fract(iTime * (1.5 + rnd * 4.0) + phase));
|
||||
|
||||
float glow = smoothstep(0.12, 0.0, d);
|
||||
vec3 hue = hsv2rgb(vec3(fract(rnd * 4.0 + iTime * 0.1), 1.0, 1.0));
|
||||
return hue * glow * blink;
|
||||
}
|
||||
|
||||
vec3 starBadge(vec2 fragCoord, vec2 resolution) {
|
||||
float radius = 26.0;
|
||||
float px = mix(radius, resolution.x - radius, triangleWave(iTime * 0.09, 1.0));
|
||||
float py = mix(radius, resolution.y - radius, triangleWave(iTime * 0.13 + 0.37, 1.0));
|
||||
vec2 p = fragCoord - vec2(px, py);
|
||||
|
||||
float d = length(p);
|
||||
float a = atan(p.y, p.x) - iTime * 2.0;
|
||||
float starR = radius * (0.55 + 0.45 * cos(a * 5.0));
|
||||
float shape = smoothstep(1.5, -1.5, d - starR);
|
||||
|
||||
vec3 hue = hsv2rgb(vec3(fract(iTime * 0.3), 1.0, 1.0));
|
||||
return hue * shape;
|
||||
}
|
||||
|
||||
// returns rgb + coverage alpha for the scrolling marquee ticker
|
||||
vec4 marquee(vec2 fragCoord, vec2 resolution) {
|
||||
float scale = clamp(resolution.y / 220.0, 2.0, 6.0);
|
||||
float charW = 6.0 * scale; // 5 columns + 1 spacing column
|
||||
float charH = 8.0 * scale; // 7 rows + 1 spacing row
|
||||
|
||||
int gap = 6; // blank characters between loops of the message
|
||||
int totalChars = MSG_LEN + gap;
|
||||
|
||||
// band hugs the bottom edge of the terminal
|
||||
float bandY0 = resolution.y - charH - scale * 2.0;
|
||||
float localY = fragCoord.y - bandY0;
|
||||
if (localY < 0.0 || localY >= charH) return vec4(0.0);
|
||||
int row = int(floor(localY / scale));
|
||||
if (row >= FONT_ROWS) return vec4(0.0);
|
||||
|
||||
float scrollX = fragCoord.x + iTime * scrollSpeed;
|
||||
float totalWidth = float(totalChars) * charW;
|
||||
float wrapped = mod(scrollX, totalWidth);
|
||||
int charIndex = int(floor(wrapped / charW));
|
||||
if (charIndex >= MSG_LEN) return vec4(0.0); // in the gap, blank
|
||||
|
||||
float localX = mod(wrapped, charW);
|
||||
int col = int(floor(localX / scale));
|
||||
if (col >= 5) return vec4(0.0);
|
||||
|
||||
int code = MSG[charIndex];
|
||||
if (fontBit(code, row, col) < 0.5) return vec4(0.0);
|
||||
|
||||
vec3 color = hsv2rgb(vec3(fract(float(charIndex) / float(MSG_LEN) + iTime * 0.15), 1.0, 1.0));
|
||||
return vec4(color, 1.0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// main
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
vec3 deco = vec3(0.0);
|
||||
|
||||
if (showStripes) {
|
||||
deco += hazardStripes(fragCoord) * stripeOpacity;
|
||||
}
|
||||
if (showSparkles) {
|
||||
deco += sparkleStars(uv, iResolution.xy) * sparkleIntensity;
|
||||
}
|
||||
if (showBadge) {
|
||||
deco = max(deco, starBadge(fragCoord, iResolution.xy));
|
||||
}
|
||||
if (showMarquee) {
|
||||
vec4 marq = marquee(fragCoord, iResolution.xy);
|
||||
deco = mix(deco, marq.rgb, marq.a);
|
||||
}
|
||||
|
||||
if (transparent) {
|
||||
deco += terminalColor.rgb;
|
||||
}
|
||||
|
||||
// only show the effect where the terminal is background (not text)
|
||||
float mask = 1.0 - step(threshold, luminance(terminalColor.rgb));
|
||||
vec3 blended = mix(terminalColor.rgb, deco, mask);
|
||||
|
||||
fragColor = vec4(blended, terminalColor.a);
|
||||
}
|
||||
91
dot_config/ghostty/shaders/iamond_teeth_cursor.glsl
Normal file
91
dot_config/ghostty/shaders/iamond_teeth_cursor.glsl
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#define PI 3.141592653589793
|
||||
|
||||
vec2 pxToNdc(vec2 p, float isPosition) {
|
||||
return (p * 2.0 - iResolution.xy * isPosition) / iResolution.y;
|
||||
}
|
||||
|
||||
float segPos(vec2 p, vec2 a, vec2 b) {
|
||||
vec2 ba = b - a;
|
||||
return clamp(dot(p - a, ba) / max(dot(ba, ba), 0.000001), 0.0, 1.0);
|
||||
}
|
||||
|
||||
float segDist(vec2 p, vec2 a, vec2 b) {
|
||||
float h = segPos(p, a, b);
|
||||
return length(p - (a + (b - a) * h));
|
||||
}
|
||||
|
||||
float diamond(vec2 p, vec2 c, float r) {
|
||||
float d = abs(p.x - c.x) + abs(p.y - c.y);
|
||||
return 1.0 - smoothstep(r * 0.25, r, d);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec4 base = texture(iChannel0, uv);
|
||||
vec3 col = base.rgb;
|
||||
|
||||
vec2 p = pxToNdc(fragCoord.xy, 1.0);
|
||||
|
||||
// Ghostty cursor rect: xy is the top-left-ish corner, zw is width/height.
|
||||
vec2 curPx = vec2(
|
||||
iCurrentCursor.x + iCurrentCursor.z * 0.5,
|
||||
iCurrentCursor.y - iCurrentCursor.w * 0.5
|
||||
);
|
||||
|
||||
vec2 prevPx = vec2(
|
||||
iPreviousCursor.x + iPreviousCursor.z * 0.5,
|
||||
iPreviousCursor.y - iPreviousCursor.w * 0.5
|
||||
);
|
||||
|
||||
vec2 cur = pxToNdc(curPx, 1.0);
|
||||
vec2 prev = pxToNdc(prevPx, 1.0);
|
||||
|
||||
float cell = max(0.008, max(iCurrentCursor.z, iCurrentCursor.w) * 2.0 / iResolution.y);
|
||||
float age = clamp(iTime - iTimeCursorChange, 0.0, 2.0);
|
||||
float pulse = exp(-age * 4.5);
|
||||
|
||||
float moved = smoothstep(cell * 1.2, cell * 5.0, distance(cur, prev));
|
||||
|
||||
// Orange-gold trail after cursor jumps.
|
||||
float h = segPos(p, prev, cur);
|
||||
float trailD = segDist(p, prev, cur);
|
||||
float trail = (1.0 - smoothstep(cell * 0.18, cell * 0.85, trailD));
|
||||
trail *= sin(h * PI) * moved * pulse;
|
||||
|
||||
col += trail * vec3(1.0, 0.36, 0.05) * 0.90;
|
||||
|
||||
// Gold glow around current cursor.
|
||||
float d = length(p - cur);
|
||||
float shimmer = 0.75 + 0.25 * sin(iTime * 9.0 + d * 90.0);
|
||||
float glow = exp(-d / (cell * 4.0)) * 0.28 * shimmer;
|
||||
col += glow * vec3(1.0, 0.62, 0.12);
|
||||
|
||||
// Expanding diamond ring when cursor moves.
|
||||
float ringRadius = cell * (1.30 + 2.20 * pulse);
|
||||
float ring = 1.0 - smoothstep(cell * 0.10, cell * 0.35, abs(d - ringRadius));
|
||||
col += ring * vec3(1.0, 0.92, 0.65) * (0.42 + 0.75 * pulse);
|
||||
|
||||
// Tiny orbiting diamonds: pinky ring / grill sparkle.
|
||||
float orbit = 0.0;
|
||||
for (int k = 0; k < 8; k++) {
|
||||
float fi = float(k);
|
||||
float dir = mix(-1.0, 1.0, step(0.5, mod(fi, 2.0)));
|
||||
float a = fi * PI * 2.0 / 8.0 + iTime * (1.5 + 0.1 * fi) * dir;
|
||||
float rad = cell * (2.4 + 0.45 * sin(iTime * 2.0 + fi * 1.7));
|
||||
vec2 q = cur + vec2(cos(a), sin(a)) * rad;
|
||||
|
||||
float tw = 0.65 + 0.35 * sin(iTime * 7.0 + fi * 2.0);
|
||||
orbit += diamond(p, q, cell * 0.45) * tw;
|
||||
}
|
||||
|
||||
col += orbit * vec3(1.0, 0.86, 0.50) * 0.70;
|
||||
|
||||
// Cross flare directly on cursor.
|
||||
float flareX = (1.0 - smoothstep(0.0, cell * 0.035, abs(p.y - cur.y))) *
|
||||
(1.0 - smoothstep(0.0, cell * 4.5, abs(p.x - cur.x)));
|
||||
float flareY = (1.0 - smoothstep(0.0, cell * 0.035, abs(p.x - cur.x))) *
|
||||
(1.0 - smoothstep(0.0, cell * 4.5, abs(p.y - cur.y)));
|
||||
col += (flareX + flareY) * vec3(1.0, 0.92, 0.60) * 0.11;
|
||||
|
||||
fragColor = vec4(clamp(col, 0.0, 1.0), base.a);
|
||||
}
|
||||
154
dot_config/ghostty/shaders/rectangle_boom_cursor.glsl
Normal file
154
dot_config/ghostty/shaders/rectangle_boom_cursor.glsl
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
// CONFIGURATION
|
||||
const float DURATION = 0.15; // How long the ripple animates (seconds)
|
||||
const float MAX_SIZE = 0.05; // Max radius in normalized coords (0.5 = 1/4 screen height)
|
||||
const float ANIMATION_START_OFFSET = 0.0; // Start the ripple slightly progressed (0.0 - 1.0)
|
||||
vec4 COLOR = vec4(0.35, 0.36, 0.44, 1.0); // change to iCurrentCursorColor for your cursor's color
|
||||
const float CURSOR_WIDTH_CHANGE_THRESHOLD = 0.5; // Triggers ripple if cursor width changes by this fraction
|
||||
const float BLUR = 3.0; // Blur level in pixels
|
||||
|
||||
// Easing functions
|
||||
float easeOutQuad(float t) {
|
||||
return 1.0 - (1.0 - t) * (1.0 - t);
|
||||
}
|
||||
float easeInOutQuad(float t) {
|
||||
return t < 0.5 ? 2.0 * t * t : 1.0 - pow(-2.0 * t + 2.0, 2.0) / 2.0;
|
||||
}
|
||||
float easeOutCubic(float t) {
|
||||
return 1.0 - pow(1.0 - t, 3.0);
|
||||
}
|
||||
float easeOutQuart(float t) {
|
||||
return 1.0 - pow(1.0 - t, 4.0);
|
||||
}
|
||||
float easeOutQuint(float t) {
|
||||
return 1.0 - pow(1.0 - t, 5.0);
|
||||
}
|
||||
float easeOutExpo(float t) {
|
||||
return t == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * t);
|
||||
}
|
||||
float easeOutCirc(float t) {
|
||||
return sqrt(1.0 - pow(t - 1.0, 2.0));
|
||||
}
|
||||
float easeOutSine(float t) {
|
||||
return sin((t * 3.1415916) / 2.0);
|
||||
}
|
||||
float easeOutElastic(float t) {
|
||||
const float c4 = (2.0 * 3.1415916) / 3.0;
|
||||
return t == 0.0 ? 0.0 : t == 1.0 ? 1.0 : pow(2.0, -10.0 * t) * sin((t * 10.0 - 0.75) * c4) + 1.0;
|
||||
}
|
||||
float easeOutBounce(float t) {
|
||||
const float n1 = 7.5625;
|
||||
const float d1 = 2.75;
|
||||
if (t < 1.0 / d1) {
|
||||
return n1 * t * t;
|
||||
} else if (t < 2.0 / d1) {
|
||||
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
||||
} else if (t < 2.5 / d1) {
|
||||
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
||||
} else {
|
||||
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
||||
}
|
||||
}
|
||||
float easeOutBack(float t) {
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1.0;
|
||||
return 1.0 + c3 * pow(t - 1.0, 3.0) + c1 * pow(t - 1.0, 2.0);
|
||||
}
|
||||
|
||||
// Pulse fade functions
|
||||
float smoothstepPulse(float t) {
|
||||
return 4.0 * t * (1.0 - t);
|
||||
}
|
||||
float easeOutPulse(float t) {
|
||||
return t * (2.0 - t);
|
||||
}
|
||||
float powerCurvePulse(float t) {
|
||||
float x = t * 2.0 - 1.0;
|
||||
return 1.0 - x * x;
|
||||
}
|
||||
float doubleSmoothstepPulse(float t) {
|
||||
return smoothstep(0.0, 0.5, t) * (1.0 - smoothstep(0.5, 1.0, t));
|
||||
}
|
||||
float exponentialDecayPulse(float t) {
|
||||
return exp(-3.0 * t) * sin(t * 3.1415916);
|
||||
}
|
||||
float sinPulse(float t) {
|
||||
return sin(t * 3.1415916);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 value, float isPosition) {
|
||||
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
||||
}
|
||||
|
||||
float getSdfRectangle(in vec2 p, in vec2 xy, in vec2 b){
|
||||
vec2 d = abs(p - xy) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
||||
#if !defined(WEB)
|
||||
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
||||
#endif
|
||||
|
||||
// Normalization & setup (-1 to 1 coords)
|
||||
vec2 vu = normalize(fragCoord, 1.);
|
||||
vec2 offsetFactor = vec2(-.5, 0.5);
|
||||
|
||||
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
||||
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
||||
|
||||
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
||||
|
||||
float cellWidth = max(currentCursor.z, previousCursor.z); // width of the 'block' cursor
|
||||
|
||||
// check for significant width change
|
||||
float widthChange = abs(currentCursor.z - previousCursor.z);
|
||||
float widthThresholdNorm = cellWidth * CURSOR_WIDTH_CHANGE_THRESHOLD;
|
||||
float isModeChange = step(widthThresholdNorm, widthChange);
|
||||
|
||||
|
||||
// ANIMATION
|
||||
float rippleProgress = (iTime - iTimeCursorChange) / DURATION + ANIMATION_START_OFFSET;
|
||||
// don't clamp yet; we need to know if it's > 1.0 (finished)
|
||||
float isAnimating = 1.0 - step(1.0, rippleProgress); // progress < 1.0 ? 1.0: 0.0
|
||||
|
||||
// WHY NOT BRANCHLESS??? here ya go:
|
||||
// because we NEVER have divergence, even in this if/else branchfull logic
|
||||
// why? because its UNIFORM branching (ie, all fragments take the same path) which modern GPUs handles efficiently
|
||||
// its far more efficient than calculating the ripple EVERY FRAME even when not needed(branchless)
|
||||
if (isModeChange > 0.0 && isAnimating > 0.0) {
|
||||
// float easedProgress = rippleProgress;
|
||||
// float easedProgress = easeOutQuad(rippleProgress);
|
||||
// float easedProgress = easeInOutQuad(rippleProgress);
|
||||
// float easedProgress = easeOutCubic(rippleProgress);
|
||||
// float easedProgress = easeOutQuart(rippleProgress);
|
||||
// float easedProgress = easeOutQuint(rippleProgress);
|
||||
// float easedProgress = easeOutExpo(rippleProgress);
|
||||
float easedProgress = easeOutCirc(rippleProgress);
|
||||
// float easedProgress = easeOutSine(rippleProgress);
|
||||
// float easedProgress = easeOutBack(rippleProgress);
|
||||
|
||||
// easedProgress = clamp(easedProgress, 0.0, 1.0);
|
||||
|
||||
// RIPPLE CALCULATION
|
||||
float rippleExpansion = easedProgress * MAX_SIZE;
|
||||
|
||||
// float fade = 1.0; // no fade
|
||||
// float fade = 1.0 - easedProgress; // linear fade
|
||||
// float fade = 1.0 - smoothstepPulse(rippleProgress);
|
||||
float fade = 1.0 - easeOutPulse(rippleProgress);
|
||||
// float fade = 1.0 - powerCurvePulse(rippleProgress);
|
||||
// float fade = doubleSmoothstepPulse(rippleProgress);
|
||||
// float fade = exponentialDecayPulse(rippleProgress);
|
||||
// float fade = sinPulse(rippleProgress);
|
||||
|
||||
vec2 halfSizeCC = vec2(currentCursor.z, currentCursor.w) * 0.5 + vec2(rippleExpansion);
|
||||
float sdfRectRing = getSdfRectangle(vu, centerCC, halfSizeCC);
|
||||
|
||||
// Antialias (1-pixel width in normalized coords)
|
||||
float antiAliasSize = normalize(vec2(BLUR, BLUR), 0.0).x;
|
||||
float ripple = (1.0 - smoothstep(-antiAliasSize, antiAliasSize, sdfRectRing)) * fade;
|
||||
// Apply ripple effect
|
||||
fragColor = mix(fragColor, COLOR, ripple * COLOR.a);
|
||||
}
|
||||
// else: do nothing, keep original fragColor
|
||||
}
|
||||
132
dot_config/ghostty/shaders/ripple_cursor.glsl
Normal file
132
dot_config/ghostty/shaders/ripple_cursor.glsl
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
// CONFIGURATION
|
||||
const float DURATION = 0.15; // How long the ripple animates (seconds)
|
||||
const float MAX_RADIUS = 0.05; // Max radius in normalized coords (0.5 = 1/4 screen height)
|
||||
const float RING_THICKNESS = 0.02; // Ring width in normalized coords
|
||||
const float CURSOR_WIDTH_CHANGE_THRESHOLD = 0.5; // Triggers ripple if cursor width changes by this fraction
|
||||
vec4 COLOR = vec4(0.35, 0.36, 0.44, 1.0); // change to iCurrentCursorColor for your cursor's color
|
||||
const float BLUR = 3.0; // Blur level in pixels
|
||||
const float ANIMATION_START_OFFSET = 0.0; // Start the ripple slightly progressed (0.0 - 1.0)
|
||||
|
||||
|
||||
// Easing functions
|
||||
float easeOutQuad(float t) {
|
||||
return 1.0 - (1.0 - t) * (1.0 - t);
|
||||
}
|
||||
float easeInOutQuad(float t) {
|
||||
return t < 0.5 ? 2.0 * t * t : 1.0 - pow(-2.0 * t + 2.0, 2.0) / 2.0;
|
||||
}
|
||||
float easeOutCubic(float t) {
|
||||
return 1.0 - pow(1.0 - t, 3.0);
|
||||
}
|
||||
float easeOutQuart(float t) {
|
||||
return 1.0 - pow(1.0 - t, 4.0);
|
||||
}
|
||||
float easeOutQuint(float t) {
|
||||
return 1.0 - pow(1.0 - t, 5.0);
|
||||
}
|
||||
float easeOutExpo(float t) {
|
||||
return t == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * t);
|
||||
}
|
||||
float easeOutCirc(float t) {
|
||||
return sqrt(1.0 - pow(t - 1.0, 2.0));
|
||||
}
|
||||
float easeOutSine(float t) {
|
||||
return sin((t * 3.1415916) / 2.0);
|
||||
}
|
||||
float easeOutElastic(float t) {
|
||||
const float c4 = (2.0 * 3.1415916) / 3.0;
|
||||
return t == 0.0 ? 0.0 : t == 1.0 ? 1.0 : pow(2.0, -10.0 * t) * sin((t * 10.0 - 0.75) * c4) + 1.0;
|
||||
}
|
||||
float easeOutBounce(float t) {
|
||||
const float n1 = 7.5625;
|
||||
const float d1 = 2.75;
|
||||
if (t < 1.0 / d1) {
|
||||
return n1 * t * t;
|
||||
} else if (t < 2.0 / d1) {
|
||||
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
||||
} else if (t < 2.5 / d1) {
|
||||
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
||||
} else {
|
||||
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
||||
}
|
||||
}
|
||||
float easeOutBack(float t) {
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1.0;
|
||||
return 1.0 + c3 * pow(t - 1.0, 3.0) + c1 * pow(t - 1.0, 2.0);
|
||||
}
|
||||
|
||||
// Pulse fade functions
|
||||
float easeOutPulse(float t) {
|
||||
return t * (2.0 - t);
|
||||
}
|
||||
float exponentialDecayPulse(float t) {
|
||||
return exp(-3.0 * t) * sin(t * 3.1415916);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 value, float isPosition) {
|
||||
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
||||
#if !defined(WEB)
|
||||
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
||||
#endif
|
||||
|
||||
// Normalization & setup (-1 to 1 coords)
|
||||
vec2 vu = normalize(fragCoord, 1.);
|
||||
vec2 offsetFactor = vec2(-.5, 0.5);
|
||||
|
||||
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
||||
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
||||
|
||||
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
||||
|
||||
float cellWidth = max(currentCursor.z, previousCursor.z); // width of the 'block' cursor
|
||||
|
||||
// check for significant width change
|
||||
float widthChange = abs(currentCursor.z - previousCursor.z);
|
||||
float widthThresholdNorm = cellWidth * CURSOR_WIDTH_CHANGE_THRESHOLD;
|
||||
float isModeChange = step(widthThresholdNorm, widthChange);
|
||||
|
||||
|
||||
// ANIMATION
|
||||
float rippleProgress = (iTime - iTimeCursorChange) / DURATION + ANIMATION_START_OFFSET;
|
||||
// don't clamp yet; we need to know if it's > 1.0 (finished)
|
||||
float isAnimating = 1.0 - step(1.0, rippleProgress); // progress < 1.0 ? 1.0: 0.0
|
||||
|
||||
if (isModeChange > 0.0 && isAnimating > 0.0) {
|
||||
// Apply easing to progress
|
||||
// float easedProgress = rippleProgress;
|
||||
// float easedProgress = easeOutQuad(rippleProgress);
|
||||
// float easedProgress = easeInOutQuad(rippleProgress);
|
||||
// float easedProgress = easeOutCubic(rippleProgress);
|
||||
// float easedProgress = easeOutQuart(rippleProgress);
|
||||
// float easedProgress = easeOutQuint(rippleProgress);
|
||||
// float easedProgress = easeOutExpo(rippleProgress);
|
||||
float easedProgress = easeOutCirc(rippleProgress);
|
||||
// float easedProgress = easeOutSine(rippleProgress);
|
||||
// float easedProgress = easeOutBack(rippleProgress);
|
||||
|
||||
// RIPPLE CALCULATION
|
||||
float rippleRadius = easedProgress * MAX_RADIUS;
|
||||
|
||||
// float fade = 1.0; // no fade
|
||||
// float fade = 1.0 - easedProgress; // linear fade
|
||||
float fade = 1.0 - easeOutPulse(rippleProgress);
|
||||
// float fade = 1.0 - exponentialDecayPulse(rippleProgress);
|
||||
|
||||
// Calculate distance from frag to cursor center
|
||||
float dist = distance(vu, centerCC);
|
||||
|
||||
float sdfRing = abs(dist - rippleRadius) - RING_THICKNESS * 0.5;
|
||||
|
||||
// Antialias (1-pixel width in normalized coords)
|
||||
float antiAliasSize = normalize(vec2(BLUR, BLUR), 0.0).x;
|
||||
float ripple = (1.0 - smoothstep(-antiAliasSize, antiAliasSize, sdfRing)) * fade;
|
||||
|
||||
// Apply ripple effect
|
||||
fragColor = mix(fragColor, COLOR, ripple * COLOR.a);
|
||||
}
|
||||
// else: do nothing, keep original fragColor
|
||||
}
|
||||
138
dot_config/ghostty/shaders/ripple_rectangle_cursor.glsl
Normal file
138
dot_config/ghostty/shaders/ripple_rectangle_cursor.glsl
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
// CONFIGURATION
|
||||
const float DURATION = 0.15; // How long the ripple animates (seconds)
|
||||
const float MAX_SIZE = 0.05; // Max radius in normalized coords (0.5 = 1/4 screen height)
|
||||
const float RING_THICKNESS = 0.02; // Ring width in normalized coords
|
||||
const float CURSOR_WIDTH_CHANGE_THRESHOLD = 0.5; // Triggers ripple if cursor width changes by this fraction
|
||||
vec4 COLOR = vec4(0.35, 0.36, 0.44, 1.0); // change to iCurrentCursorColor for your cursor's color
|
||||
const float BLUR = 1.0; // Blur level in pixels
|
||||
const float ANIMATION_START_OFFSET = 0.0; // Start the ripple slightly progressed (0.0 - 1.0)
|
||||
|
||||
|
||||
// Easing functions
|
||||
float easeOutQuad(float t) {
|
||||
return 1.0 - (1.0 - t) * (1.0 - t);
|
||||
}
|
||||
float easeInOutQuad(float t) {
|
||||
return t < 0.5 ? 2.0 * t * t : 1.0 - pow(-2.0 * t + 2.0, 2.0) / 2.0;
|
||||
}
|
||||
float easeOutCubic(float t) {
|
||||
return 1.0 - pow(1.0 - t, 3.0);
|
||||
}
|
||||
float easeOutQuart(float t) {
|
||||
return 1.0 - pow(1.0 - t, 4.0);
|
||||
}
|
||||
float easeOutQuint(float t) {
|
||||
return 1.0 - pow(1.0 - t, 5.0);
|
||||
}
|
||||
float easeOutExpo(float t) {
|
||||
return t == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * t);
|
||||
}
|
||||
float easeOutCirc(float t) {
|
||||
return sqrt(1.0 - pow(t - 1.0, 2.0));
|
||||
}
|
||||
float easeOutSine(float t) {
|
||||
return sin((t * 3.1415916) / 2.0);
|
||||
}
|
||||
float easeOutElastic(float t) {
|
||||
const float c4 = (2.0 * 3.1415916) / 3.0;
|
||||
return t == 0.0 ? 0.0 : t == 1.0 ? 1.0 : pow(2.0, -10.0 * t) * sin((t * 10.0 - 0.75) * c4) + 1.0;
|
||||
}
|
||||
float easeOutBounce(float t) {
|
||||
const float n1 = 7.5625;
|
||||
const float d1 = 2.75;
|
||||
if (t < 1.0 / d1) {
|
||||
return n1 * t * t;
|
||||
} else if (t < 2.0 / d1) {
|
||||
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
||||
} else if (t < 2.5 / d1) {
|
||||
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
||||
} else {
|
||||
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
||||
}
|
||||
}
|
||||
float easeOutBack(float t) {
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1.0;
|
||||
return 1.0 + c3 * pow(t - 1.0, 3.0) + c1 * pow(t - 1.0, 2.0);
|
||||
}
|
||||
|
||||
// Pulse fade functions
|
||||
float easeOutPulse(float t) {
|
||||
return t * (2.0 - t);
|
||||
}
|
||||
float exponentialDecayPulse(float t) {
|
||||
return exp(-3.0 * t) * sin(t * 3.1415916);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 value, float isPosition) {
|
||||
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
||||
}
|
||||
|
||||
float getSdfRectangle(in vec2 p, in vec2 xy, in vec2 b){
|
||||
vec2 d = abs(p - xy) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
||||
#if !defined(WEB)
|
||||
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
||||
#endif
|
||||
|
||||
// Normalization & setup (-1 to 1 coords)
|
||||
vec2 vu = normalize(fragCoord, 1.);
|
||||
vec2 offsetFactor = vec2(-.5, 0.5);
|
||||
|
||||
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
||||
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
||||
|
||||
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
||||
|
||||
float cellWidth = max(currentCursor.z, previousCursor.z); // width of the 'block' cursor
|
||||
|
||||
// check for significant width change
|
||||
float widthChange = abs(currentCursor.z - previousCursor.z);
|
||||
float widthThresholdNorm = cellWidth * CURSOR_WIDTH_CHANGE_THRESHOLD;
|
||||
float isModeChange = step(widthThresholdNorm, widthChange);
|
||||
|
||||
|
||||
// ANIMATION
|
||||
float rippleProgress = (iTime - iTimeCursorChange) / DURATION + ANIMATION_START_OFFSET;
|
||||
// don't clamp yet; we need to know if it's > 1.0 (finished)
|
||||
float isAnimating = 1.0 - step(1.0, rippleProgress); // progress < 1.0 ? 1.0: 0.0
|
||||
|
||||
if (isModeChange > 0.0 && isAnimating > 0.0) {
|
||||
// Apply easing to progress
|
||||
// float easedProgress = rippleProgress;
|
||||
// float easedProgress = easeOutQuad(rippleProgress);
|
||||
// float easedProgress = easeInOutQuad(rippleProgress);
|
||||
// float easedProgress = easeOutCubic(rippleProgress);
|
||||
// float easedProgress = easeOutQuart(rippleProgress);
|
||||
// float easedProgress = easeOutQuint(rippleProgress);
|
||||
// float easedProgress = easeOutExpo(rippleProgress);
|
||||
float easedProgress = easeOutCirc(rippleProgress);
|
||||
// float easedProgress = easeOutSine(rippleProgress);
|
||||
// float easedProgress = easeOutBack(rippleProgress);
|
||||
|
||||
// RIPPLE CALCULATION
|
||||
float rippleExpansion = easedProgress * MAX_SIZE;
|
||||
|
||||
// float fade = 1.0; // no fade
|
||||
// float fade = 1.0 - easedProgress; // linear fade
|
||||
float fade = 1.0 - easeOutPulse(rippleProgress);
|
||||
// float fade = 1.0 - exponentialDecayPulse(rippleProgress);
|
||||
|
||||
// Calculate distance from frag to cursor center
|
||||
// float dist = distance(vu, centerCC);
|
||||
|
||||
// float sdfRing = abs(dist - rippleExpansion) - RING_THICKNESS * 0.5;
|
||||
vec2 halfSizeCC = vec2(currentCursor.z, currentCursor.w) * 0.5 + vec2(rippleExpansion);
|
||||
float sdfRectRing = abs(getSdfRectangle(vu, centerCC, halfSizeCC)) - RING_THICKNESS * 0.5;
|
||||
// Antialias (1-pixel width in normalized coords)
|
||||
float antiAliasSize = normalize(vec2(BLUR, BLUR), 0.0).x;
|
||||
float ripple = (1.0 - smoothstep(-antiAliasSize, antiAliasSize, sdfRectRing)) * fade;
|
||||
|
||||
// Apply ripple effect
|
||||
fragColor = mix(fragColor, COLOR, ripple * COLOR.a);
|
||||
}
|
||||
// else: do nothing, keep original fragColor
|
||||
}
|
||||
148
dot_config/ghostty/shaders/sonic_boom_cursor.glsl
Normal file
148
dot_config/ghostty/shaders/sonic_boom_cursor.glsl
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// CONFIGURATION
|
||||
const float DURATION = 0.15; // How long the ripple animates (seconds)
|
||||
const float MAX_RADIUS = 0.06; // Max radius in normalized coords (0.5 = 1/4 screen height)
|
||||
const float ANIMATION_START_OFFSET = 0.0; // Start the ripple slightly progressed (0.0 - 1.0)
|
||||
vec4 COLOR = vec4(0.35, 0.36, 0.44, 1.0); // change to iCurrentCursorColor for your cursor's color
|
||||
const float CURSOR_WIDTH_CHANGE_THRESHOLD = 0.5; // Triggers ripple if cursor width changes by this fraction
|
||||
const float BLUR = 3.0; // Blur level in pixels
|
||||
|
||||
|
||||
// Easing functions
|
||||
float easeOutQuad(float t) {
|
||||
return 1.0 - (1.0 - t) * (1.0 - t);
|
||||
}
|
||||
float easeInOutQuad(float t) {
|
||||
return t < 0.5 ? 2.0 * t * t : 1.0 - pow(-2.0 * t + 2.0, 2.0) / 2.0;
|
||||
}
|
||||
float easeOutCubic(float t) {
|
||||
return 1.0 - pow(1.0 - t, 3.0);
|
||||
}
|
||||
float easeOutQuart(float t) {
|
||||
return 1.0 - pow(1.0 - t, 4.0);
|
||||
}
|
||||
float easeOutQuint(float t) {
|
||||
return 1.0 - pow(1.0 - t, 5.0);
|
||||
}
|
||||
float easeOutExpo(float t) {
|
||||
return t == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * t);
|
||||
}
|
||||
float easeOutCirc(float t) {
|
||||
return sqrt(1.0 - pow(t - 1.0, 2.0));
|
||||
}
|
||||
float easeOutSine(float t) {
|
||||
return sin((t * 3.1415916) / 2.0);
|
||||
}
|
||||
float easeOutElastic(float t) {
|
||||
const float c4 = (2.0 * 3.1415916) / 3.0;
|
||||
return t == 0.0 ? 0.0 : t == 1.0 ? 1.0 : pow(2.0, -10.0 * t) * sin((t * 10.0 - 0.75) * c4) + 1.0;
|
||||
}
|
||||
float easeOutBounce(float t) {
|
||||
const float n1 = 7.5625;
|
||||
const float d1 = 2.75;
|
||||
if (t < 1.0 / d1) {
|
||||
return n1 * t * t;
|
||||
} else if (t < 2.0 / d1) {
|
||||
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
||||
} else if (t < 2.5 / d1) {
|
||||
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
||||
} else {
|
||||
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
||||
}
|
||||
}
|
||||
float easeOutBack(float t) {
|
||||
const float c1 = 1.70158;
|
||||
const float c3 = c1 + 1.0;
|
||||
return 1.0 + c3 * pow(t - 1.0, 3.0) + c1 * pow(t - 1.0, 2.0);
|
||||
}
|
||||
|
||||
// Pulse fade functions
|
||||
float smoothstepPulse(float t) {
|
||||
return 4.0 * t * (1.0 - t);
|
||||
}
|
||||
float easeOutPulse(float t) {
|
||||
return t * (2.0 - t);
|
||||
}
|
||||
float powerCurvePulse(float t) {
|
||||
float x = t * 2.0 - 1.0;
|
||||
return 1.0 - x * x;
|
||||
}
|
||||
float doubleSmoothstepPulse(float t) {
|
||||
return smoothstep(0.0, 0.5, t) * (1.0 - smoothstep(0.5, 1.0, t));
|
||||
}
|
||||
float exponentialDecayPulse(float t) {
|
||||
return exp(-3.0 * t) * sin(t * 3.1415916);
|
||||
}
|
||||
float sinPulse(float t) {
|
||||
return sin(t * 3.1415916);
|
||||
}
|
||||
|
||||
vec2 normalize(vec2 value, float isPosition) {
|
||||
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
||||
#if !defined(WEB)
|
||||
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
||||
#endif
|
||||
|
||||
// Normalization & setup (-1 to 1 coords)
|
||||
vec2 vu = normalize(fragCoord, 1.);
|
||||
vec2 offsetFactor = vec2(-.5, 0.5);
|
||||
|
||||
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
||||
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
||||
|
||||
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
||||
|
||||
float cellWidth = max(currentCursor.z, previousCursor.z); // width of the 'block' cursor
|
||||
|
||||
// check for significant width change
|
||||
float widthChange = abs(currentCursor.z - previousCursor.z);
|
||||
float widthThresholdNorm = cellWidth * CURSOR_WIDTH_CHANGE_THRESHOLD;
|
||||
float isModeChange = step(widthThresholdNorm, widthChange);
|
||||
|
||||
|
||||
// ANIMATION
|
||||
float rippleProgress = (iTime - iTimeCursorChange) / DURATION + ANIMATION_START_OFFSET;
|
||||
// don't clamp yet; we need to know if it's > 1.0 (finished)
|
||||
float isAnimating = 1.0 - step(1.0, rippleProgress); // progress < 1.0 ? 1.0: 0.0
|
||||
|
||||
if (isModeChange > 0.0 && isAnimating > 0.0) {
|
||||
// float easedProgress = rippleProgress;
|
||||
// float easedProgress = easeOutQuad(rippleProgress);
|
||||
// float easedProgress = easeInOutQuad(rippleProgress);
|
||||
// float easedProgress = easeOutCubic(rippleProgress);
|
||||
// float easedProgress = easeOutQuart(rippleProgress);
|
||||
// float easedProgress = easeOutQuint(rippleProgress);
|
||||
// float easedProgress = easeOutExpo(rippleProgress);
|
||||
float easedProgress = easeOutCirc(rippleProgress);
|
||||
// float easedProgress = easeOutSine(rippleProgress);
|
||||
// float easedProgress = easeOutBack(rippleProgress);
|
||||
|
||||
// easedProgress = clamp(easedProgress, 0.0, 1.0);
|
||||
|
||||
// RIPPLE CALCULATION
|
||||
float rippleRadius = easedProgress * MAX_RADIUS;
|
||||
|
||||
// float fade = 1.0; // no fade
|
||||
// float fade = 1.0 - easedProgress; // linear fade
|
||||
// float fade = 1.0 - smoothstepPulse(rippleProgress);
|
||||
float fade = 1.0 - easeOutPulse(rippleProgress);
|
||||
// float fade = 1.0 - powerCurvePulse(rippleProgress);
|
||||
// float fade = doubleSmoothstepPulse(rippleProgress);
|
||||
// float fade = exponentialDecayPulse(rippleProgress);
|
||||
// float fade = sinPulse(rippleProgress);
|
||||
|
||||
// Calculate distance from frag to cursor center
|
||||
float dist = distance(vu, centerCC);
|
||||
|
||||
float sdfCircle = dist - rippleRadius;
|
||||
|
||||
// Antialias (1-pixel width in normalized coords)
|
||||
float antiAliasSize = normalize(vec2(BLUR, BLUR), 0.0).x;
|
||||
float ripple = (1.0 - smoothstep(-antiAliasSize, antiAliasSize, sdfCircle)) * fade;
|
||||
|
||||
// Apply ripple effect
|
||||
fragColor = mix(fragColor, COLOR, ripple * COLOR.a);
|
||||
}
|
||||
}
|
||||
162
dot_config/ghostty/shaders/starfield-colors.glsl
Normal file
162
dot_config/ghostty/shaders/starfield-colors.glsl
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
// transparent background
|
||||
const bool transparent = true;
|
||||
|
||||
// terminal contents luminance threshold to be considered background (0.0 to 1.0)
|
||||
const float threshold = 0.05;
|
||||
|
||||
// overall star brightness (0.0 = invisible, 1.0 = original brightness)
|
||||
const float intensity = 0.09;
|
||||
|
||||
// divisions of grid
|
||||
const float repeats = 15.;
|
||||
|
||||
// number of layers
|
||||
const float layers = 20.;
|
||||
|
||||
// star colours
|
||||
const vec3 blue = vec3(51., 64., 195.) / 255.;
|
||||
const vec3 cyan = vec3(117., 250., 254.) / 255.;
|
||||
const vec3 white = vec3(255., 255., 255.) / 255.;
|
||||
const vec3 yellow = vec3(251., 245., 44.) / 255.;
|
||||
const vec3 red = vec3(247, 2., 20.) / 255.;
|
||||
|
||||
float luminance(vec3 color) {
|
||||
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
// spectrum function
|
||||
vec3 spectrum(vec2 pos) {
|
||||
pos.x *= 4.;
|
||||
vec3 outCol = vec3(0);
|
||||
if (pos.x > 0.) {
|
||||
outCol = mix(blue, cyan, fract(pos.x));
|
||||
}
|
||||
if (pos.x > 1.) {
|
||||
outCol = mix(cyan, white, fract(pos.x));
|
||||
}
|
||||
if (pos.x > 2.) {
|
||||
outCol = mix(white, yellow, fract(pos.x));
|
||||
}
|
||||
if (pos.x > 3.) {
|
||||
outCol = mix(yellow, red, fract(pos.x));
|
||||
}
|
||||
|
||||
return 1. - (pos.y * (1. - outCol));
|
||||
}
|
||||
|
||||
float N21(vec2 p) {
|
||||
p = fract(p * vec2(233.34, 851.73));
|
||||
p += dot(p, p + 23.45);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
vec2 N22(vec2 p) {
|
||||
float n = N21(p);
|
||||
return vec2(n, N21(p + n));
|
||||
}
|
||||
|
||||
mat2 scale(vec2 _scale) {
|
||||
return mat2(_scale.x, 0.0,
|
||||
0.0, _scale.y);
|
||||
}
|
||||
|
||||
// 2D Noise based on Morgan McGuire
|
||||
float noise(in vec2 st) {
|
||||
vec2 i = floor(st);
|
||||
vec2 f = fract(st);
|
||||
|
||||
// Four corners in 2D of a tile
|
||||
float a = N21(i);
|
||||
float b = N21(i + vec2(1.0, 0.0));
|
||||
float c = N21(i + vec2(0.0, 1.0));
|
||||
float d = N21(i + vec2(1.0, 1.0));
|
||||
|
||||
// Smooth Interpolation
|
||||
vec2 u = f * f * (3.0 - 2.0 * f); // Cubic Hermite Curve
|
||||
|
||||
// Mix 4 corners percentages
|
||||
return mix(a, b, u.x) +
|
||||
(c - a) * u.y * (1.0 - u.x) +
|
||||
(d - b) * u.x * u.y;
|
||||
}
|
||||
|
||||
float perlin2(vec2 uv, int octaves, float pscale) {
|
||||
float col = 1.;
|
||||
float initScale = 4.;
|
||||
for (int l; l < octaves; l++) {
|
||||
float val = noise(uv * initScale);
|
||||
if (col <= 0.01) {
|
||||
col = 0.;
|
||||
break;
|
||||
}
|
||||
val -= 0.01;
|
||||
val *= 0.5;
|
||||
col *= val;
|
||||
initScale *= pscale;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 stars(vec2 uv, float offset) {
|
||||
float timeScale = -(iTime + offset) / layers;
|
||||
float trans = fract(timeScale);
|
||||
float newRnd = floor(timeScale);
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
// Translate uv then scale for center
|
||||
uv -= vec2(0.5);
|
||||
uv = scale(vec2(trans)) * uv;
|
||||
uv += vec2(0.5);
|
||||
|
||||
// Create square aspect ratio
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
|
||||
// Create boxes
|
||||
uv *= repeats;
|
||||
|
||||
// Get position
|
||||
vec2 ipos = floor(uv);
|
||||
|
||||
// Return uv as 0 to 1
|
||||
uv = fract(uv);
|
||||
|
||||
// Calculate random xy and size
|
||||
vec2 rndXY = N22(newRnd + ipos * (offset + 1.)) * 0.9 + 0.05;
|
||||
float rndSize = N21(ipos) * 100. + 200.;
|
||||
|
||||
vec2 j = (rndXY - uv) * rndSize;
|
||||
float sparkle = 1. / dot(j, j);
|
||||
|
||||
// Set stars to be pure white
|
||||
col += spectrum(fract(rndXY * newRnd * ipos)) * vec3(sparkle);
|
||||
|
||||
col *= smoothstep(1., 0.8, trans);
|
||||
return col; // Return pure white stars only
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
// Normalized pixel coordinates (from 0 to 1)
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
for (float i = 0.; i < layers; i++) {
|
||||
col += stars(uv, i);
|
||||
}
|
||||
col *= intensity;
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
if (transparent) {
|
||||
col += terminalColor.rgb;
|
||||
}
|
||||
|
||||
// Make a mask that is 1.0 where the terminal content is not black
|
||||
float mask = 1 - step(threshold, luminance(terminalColor.rgb));
|
||||
vec3 blendedColor = mix(terminalColor.rgb, col, mask);
|
||||
|
||||
// Apply terminal's alpha to control overall opacity
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
135
dot_config/ghostty/shaders/starfield.glsl
Normal file
135
dot_config/ghostty/shaders/starfield.glsl
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// transparent background
|
||||
const bool transparent = false;
|
||||
|
||||
// terminal contents luminance threshold to be considered background (0.0 to 1.0)
|
||||
const float threshold = 0.15;
|
||||
|
||||
// divisions of grid
|
||||
const float repeats = 30.;
|
||||
|
||||
// number of layers
|
||||
const float layers = 21.;
|
||||
|
||||
// star colors
|
||||
const vec3 white = vec3(1.0); // Set star color to pure white
|
||||
|
||||
float luminance(vec3 color) {
|
||||
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
float N21(vec2 p) {
|
||||
p = fract(p * vec2(233.34, 851.73));
|
||||
p += dot(p, p + 23.45);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
vec2 N22(vec2 p) {
|
||||
float n = N21(p);
|
||||
return vec2(n, N21(p + n));
|
||||
}
|
||||
|
||||
mat2 scale(vec2 _scale) {
|
||||
return mat2(_scale.x, 0.0,
|
||||
0.0, _scale.y);
|
||||
}
|
||||
|
||||
// 2D Noise based on Morgan McGuire
|
||||
float noise(in vec2 st) {
|
||||
vec2 i = floor(st);
|
||||
vec2 f = fract(st);
|
||||
|
||||
// Four corners in 2D of a tile
|
||||
float a = N21(i);
|
||||
float b = N21(i + vec2(1.0, 0.0));
|
||||
float c = N21(i + vec2(0.0, 1.0));
|
||||
float d = N21(i + vec2(1.0, 1.0));
|
||||
|
||||
// Smooth Interpolation
|
||||
vec2 u = f * f * (3.0 - 2.0 * f); // Cubic Hermite Curve
|
||||
|
||||
// Mix 4 corners percentages
|
||||
return mix(a, b, u.x) +
|
||||
(c - a) * u.y * (1.0 - u.x) +
|
||||
(d - b) * u.x * u.y;
|
||||
}
|
||||
|
||||
float perlin2(vec2 uv, int octaves, float pscale) {
|
||||
float col = 1.;
|
||||
float initScale = 4.;
|
||||
for (int l; l < octaves; l++) {
|
||||
float val = noise(uv * initScale);
|
||||
if (col <= 0.01) {
|
||||
col = 0.;
|
||||
break;
|
||||
}
|
||||
val -= 0.01;
|
||||
val *= 0.5;
|
||||
col *= val;
|
||||
initScale *= pscale;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 stars(vec2 uv, float offset) {
|
||||
float timeScale = -(iTime + offset) / layers;
|
||||
float trans = fract(timeScale);
|
||||
float newRnd = floor(timeScale);
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
// Translate uv then scale for center
|
||||
uv -= vec2(0.5);
|
||||
uv = scale(vec2(trans)) * uv;
|
||||
uv += vec2(0.5);
|
||||
|
||||
// Create square aspect ratio
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
|
||||
// Create boxes
|
||||
uv *= repeats;
|
||||
|
||||
// Get position
|
||||
vec2 ipos = floor(uv);
|
||||
|
||||
// Return uv as 0 to 1
|
||||
uv = fract(uv);
|
||||
|
||||
// Calculate random xy and size
|
||||
vec2 rndXY = N22(newRnd + ipos * (offset + 1.)) * 0.9 + 0.05;
|
||||
float rndSize = N21(ipos) * 100. + 200.;
|
||||
|
||||
vec2 j = (rndXY - uv) * rndSize;
|
||||
float sparkle = 1. / dot(j, j);
|
||||
|
||||
// Set stars to be pure white
|
||||
col += white * sparkle;
|
||||
|
||||
col *= smoothstep(1., 0.8, trans);
|
||||
return col; // Return pure white stars only
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||
{
|
||||
// Normalized pixel coordinates (from 0 to 1)
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
|
||||
vec3 col = vec3(0.);
|
||||
|
||||
for (float i = 0.; i < layers; i++) {
|
||||
col += stars(uv, i);
|
||||
}
|
||||
|
||||
// Sample the terminal screen texture including alpha channel
|
||||
vec4 terminalColor = texture(iChannel0, uv);
|
||||
|
||||
if (transparent) {
|
||||
col += terminalColor.rgb;
|
||||
}
|
||||
|
||||
// Make a mask that is 1.0 where the terminal content is not black
|
||||
float mask = 1 - step(threshold, luminance(terminalColor.rgb));
|
||||
|
||||
vec3 blendedColor = mix(terminalColor.rgb, col, mask);
|
||||
|
||||
// Apply terminal's alpha to control overall opacity
|
||||
fragColor = vec4(blendedColor, terminalColor.a);
|
||||
}
|
||||
Loading…
Reference in a new issue