Configuration files

ghostty: add cursor trail shader

Changed files
+113
.config
+2
.config/ghostty/config
··· 24 window-padding-color = extend 25 26 theme = "Kanagawa Wave"
··· 24 window-padding-color = extend 25 26 theme = "Kanagawa Wave" 27 + 28 + custom-shader = "cursor.glsl"
+111
.config/ghostty/cursor.glsl
···
··· 1 + // Adapted from: https://github.com/KroneCorylus/shader-playground/blob/main/shaders/cursor_smear_fade.glsl 2 + 3 + float getSdfRectangle(in vec2 p, in vec2 xy, in vec2 b) 4 + { 5 + vec2 d = abs(p - xy) - b; 6 + return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0); 7 + } 8 + 9 + // Based on Inigo Quilez's 2D distance functions article: https://iquilezles.org/articles/distfunctions2d/ 10 + // Potencially optimized by eliminating conditionals and loops to enhance performance and reduce branching 11 + 12 + float seg(in vec2 p, in vec2 a, in vec2 b, inout float s, float d) { 13 + vec2 e = b - a; 14 + vec2 w = p - a; 15 + vec2 proj = a + e * clamp(dot(w, e) / dot(e, e), 0.0, 1.0); 16 + float segd = dot(p - proj, p - proj); 17 + d = min(d, segd); 18 + 19 + float c0 = step(0.0, p.y - a.y); 20 + float c1 = 1.0 - step(0.0, p.y - b.y); 21 + float c2 = 1.0 - step(0.0, e.x * w.y - e.y * w.x); 22 + float allCond = c0 * c1 * c2; 23 + float noneCond = (1.0 - c0) * (1.0 - c1) * (1.0 - c2); 24 + float flip = mix(1.0, -1.0, step(0.5, allCond + noneCond)); 25 + s *= flip; 26 + return d; 27 + } 28 + 29 + float getSdfParallelogram(in vec2 p, in vec2 v0, in vec2 v1, in vec2 v2, in vec2 v3) { 30 + float s = 1.0; 31 + float d = dot(p - v0, p - v0); 32 + 33 + d = seg(p, v0, v3, s, d); 34 + d = seg(p, v1, v0, s, d); 35 + d = seg(p, v2, v1, s, d); 36 + d = seg(p, v3, v2, s, d); 37 + 38 + return s * sqrt(d); 39 + } 40 + 41 + vec2 normalize(vec2 value, float isPosition) { 42 + return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y; 43 + } 44 + 45 + float antialising(float distance) { 46 + return 1. - smoothstep(0., normalize(vec2(2., 2.), 0.).x, distance); 47 + } 48 + 49 + float determineStartVertexFactor(vec2 a, vec2 b) { 50 + // Conditions using step 51 + float condition1 = step(b.x, a.x) * step(a.y, b.y); // a.x < b.x && a.y > b.y 52 + float condition2 = step(a.x, b.x) * step(b.y, a.y); // a.x > b.x && a.y < b.y 53 + 54 + // If neither condition is met, return 1 (else case) 55 + return 1.0 - max(condition1, condition2); 56 + } 57 + 58 + vec2 getRectangleCenter(vec4 rectangle) { 59 + return vec2(rectangle.x + (rectangle.z / 2.), rectangle.y - (rectangle.w / 2.)); 60 + } 61 + float ease(float x) { 62 + return pow(1.0 - x, 3.0); 63 + } 64 + 65 + const float DURATION = 0.25; //IN SECONDS 66 + 67 + void mainImage(out vec4 fragColor, in vec2 fragCoord) 68 + { 69 + #if !defined(WEB) 70 + fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy); 71 + #endif 72 + // Normalization for fragCoord to a space of -1 to 1; 73 + vec2 vu = normalize(fragCoord, 1.); 74 + vec2 offsetFactor = vec2(-.5, 0.5); 75 + 76 + // Normalization for cursor position and size; 77 + // cursor xy has the postion in a space of -1 to 1; 78 + // zw has the width and height 79 + vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.)); 80 + vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.)); 81 + 82 + // When drawing a parellelogram between cursors for the trail i need to determine where to start at the top-left or top-right vertex of the cursor 83 + float vertexFactor = determineStartVertexFactor(currentCursor.xy, previousCursor.xy); 84 + float invertedVertexFactor = 1.0 - vertexFactor; 85 + 86 + // Set every vertex of my parellogram 87 + vec2 v0 = vec2(currentCursor.x + currentCursor.z * vertexFactor, currentCursor.y - currentCursor.w); 88 + vec2 v1 = vec2(currentCursor.x + currentCursor.z * invertedVertexFactor, currentCursor.y); 89 + vec2 v2 = vec2(previousCursor.x + currentCursor.z * invertedVertexFactor, previousCursor.y); 90 + vec2 v3 = vec2(previousCursor.x + currentCursor.z * vertexFactor, previousCursor.y - previousCursor.w); 91 + 92 + float sdfCurrentCursor = getSdfRectangle(vu, currentCursor.xy - (currentCursor.zw * offsetFactor), currentCursor.zw * 0.5); 93 + float sdfTrail = getSdfParallelogram(vu, v0, v1, v2, v3); 94 + 95 + float progress = clamp((iTime - iTimeCursorChange) / DURATION, 0.0, 1.0); 96 + float easedProgress = ease(progress); 97 + // Distance between cursors determine the total length of the parallelogram; 98 + vec2 centerCC = getRectangleCenter(currentCursor); 99 + vec2 centerCP = getRectangleCenter(previousCursor); 100 + float lineLength = distance(centerCC, centerCP); 101 + 102 + vec4 newColor = vec4(fragColor); 103 + vec4 trailColor = mix(iPreviousCursorColor * 0.9, iCurrentCursorColor * 0.9, easedProgress); 104 + trailColor = mix(trailColor, vec4(trailColor.rgb * 0.1, 0), easedProgress); 105 + 106 + newColor = mix(newColor, trailColor, antialising(sdfTrail)); 107 + // Draw current cursor 108 + newColor = mix(newColor, trailColor, antialising(sdfCurrentCursor)); 109 + newColor = mix(newColor, fragColor, step(sdfCurrentCursor, 0.)); 110 + fragColor = mix(fragColor, newColor, step(sdfCurrentCursor, easedProgress * lineLength)); 111 + }