summaryrefslogtreecommitdiff
path: root/shaders
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 16:44:51 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commita007457cb007b03f310bca55c339e8cd5d9baafc (patch)
tree31e57644c6df2eef04fb3c2a200482571c6e6857 /shaders
parent1ed34e1538f45daecc2c8a551dc0fb7aba5f3f54 (diff)
downloadpardes-a007457cb007b03f310bca55c339e8cd5d9baafc.tar.gz
pardes-a007457cb007b03f310bca55c339e8cd5d9baafc.zip
Ripple and Glitch are gone; Crt stays
The user tried them live and wants them removed entirely: the builtins, their levels, config keys and leader paths (tR, tg), their slots in the built-in chain, their shaders (source and prebuilt), EffectCode paths, and on macOS their scene flags (pardes.h), the Metal kernel's coordinate warps and the Swift pointer mapping that mirrored them. Docs say so (decision 8 in docs/render-pipeline.md); config.md documents Crt's levels, Shader and ShaderAnimation instead. Shared files touched: macos.zig (flags). Not touched: pardes.zig, Messages.zig, mouse.zig, gui.zig, detached/*.
Diffstat (limited to 'shaders')
-rw-r--r--shaders/crt.ci.metal75
-rw-r--r--shaders/post/glitch.glsl64
-rw-r--r--shaders/post/ripple.glsl52
-rw-r--r--shaders/prebuilt/post-glitch.frag.glsl138
-rw-r--r--shaders/prebuilt/post-glitch.frag.spvbin10764 -> 0 bytes
-rw-r--r--shaders/prebuilt/post-ripple.frag.glsl126
-rw-r--r--shaders/prebuilt/post-ripple.frag.spvbin9096 -> 0 bytes
7 files changed, 9 insertions, 446 deletions
diff --git a/shaders/crt.ci.metal b/shaders/crt.ci.metal
index c7e91a7e..9159af18 100644
--- a/shaders/crt.ci.metal
+++ b/shaders/crt.ci.metal
@@ -1,7 +1,6 @@
// Native macOS panel and scene postprocess. Panel kernels consume the core's
-// plain tracks; the final full-window kernel ports crt.frag.glsl and combines
-// CRT, ripple and glitch. Scene constants and sampling geometry stay in step
-// with GLSL, while panel easing/noise stays in step with panel_animation.zig.
+// plain tracks; the final full-window kernel is the CRT. Panel easing/noise
+// stays in step with panel_animation.zig.
//
// The three entry points are `extern "C" [[stitchable]]`. Both halves are
// load-bearing: this source is compiled at runtime by
@@ -38,24 +37,6 @@ float pardesCellNoise(float2 serialParts, float colValue, float rowValue) {
return float(x & 0xffffu) / 65535.0;
}
-float2 pardesSceneUV(float2 uv, float timeSeconds, float rippleOn, float glitchOn) {
- if (rippleOn > 0.5) {
- float2 centered = uv - 0.5;
- float radius = length(centered);
- // Reversed smoothstep edges are undefined in GLSL and Metal alike.
- float envelope = 1.0 - smoothstep(0.04, 0.72, radius);
- float wave = sin(radius * 42.0 - timeSeconds * 5.2);
- uv += centered / max(radius, 0.00001) * wave * envelope * 0.0032;
- }
- if (glitchOn > 0.5) {
- float band = floor(uv.y * 96.0);
- float seed = pardesNoise(float2(band, floor(timeSeconds * 13.0)));
- float tear = smoothstep(0.955, 1.0, seed);
- uv.x += (pardesNoise(float2(seed, band)) - 0.5) * tear * 0.020;
- }
- return uv;
-}
-
float4 pardesSceneSample(
coreimage::sampler source,
float2 origin,
@@ -66,42 +47,13 @@ float4 pardesSceneSample(
source.sample(source.transform(origin + uv * size)));
}
-// Keep this ordering identical to crt.frag.glsl's sceneSrgb: every caller
-// supplies its own pre-warp coordinate, then ripple/glitch move that sample,
-// then glitch splits its red/blue channels around the moved center.
-float4 pardesSceneSrgb(
- coreimage::sampler source,
- float2 origin,
- float2 size,
- float2 uv,
- float timeSeconds,
- float rippleOn,
- float glitchOn
-) {
- float2 warped = pardesSceneUV(uv, timeSeconds, rippleOn, glitchOn);
- float4 center = pardesSceneSample(source, origin, size, warped);
- if (glitchOn <= 0.5) return center;
-
- float band = floor(warped.y * 96.0);
- float seed = pardesNoise(float2(band, floor(timeSeconds * 13.0)));
- float tear = smoothstep(0.955, 1.0, seed);
- float2 chroma = float2((0.35 + 1.25 * tear) / size.x, 0.0);
- float4 red = pardesSceneSample(source, origin, size, warped + chroma);
- float4 blue = pardesSceneSample(source, origin, size, warped - chroma);
- return float4(red.r, center.g, blue.b, center.a);
-}
-
float3 pardesSceneLinear(
coreimage::sampler source,
float2 origin,
float2 size,
- float2 uv,
- float timeSeconds,
- float rippleOn,
- float glitchOn
+ float2 uv
) {
- return coreimage::srgb_to_linear(pardesSceneSrgb(
- source, origin, size, uv, timeSeconds, rippleOn, glitchOn).rgb);
+ return coreimage::srgb_to_linear(pardesSceneSample(source, origin, size, uv).rgb);
}
bool pardesInside(float2 p, float4 box) {
@@ -242,8 +194,6 @@ extern "C" [[stitchable]] float4 pardesScene(
float timeSeconds,
float frame,
float crtOn,
- float rippleOn,
- float glitchOn,
float2 sceneSize,
float2 sceneOrigin,
coreimage::destination destination
@@ -277,24 +227,18 @@ extern "C" [[stitchable]] float4 pardesScene(
// transparent theme.
if (crtOn > 0.5 && edge <= 0.0) return float4(0.0, 0.0, 0.0, 1.0);
- float4 center = pardesSceneSrgb(
- source, origin, size, uv, timeSeconds, rippleOn, glitchOn);
+ float4 center = pardesSceneSample(source, origin, size, uv);
float3 scene = center.rgb;
- // Ripple/glitch alone are coordinate effects. Returning the sampled sRGB
- // values directly keeps exact theme colors exact.
+ // Without the CRT the scene passes through, exact.
if (crtOn <= 0.5) {
return coreimage::premultiply(float4(clamp(scene, 0.0, 1.0), center.a));
}
float3 centerLinear = coreimage::srgb_to_linear(scene);
float2 radialChroma = cc * (chromaPx * r2) * texel;
- float3 redSample = pardesSceneLinear(
- source, origin, size, uv + radialChroma,
- timeSeconds, rippleOn, glitchOn);
- float3 blueSample = pardesSceneLinear(
- source, origin, size, uv - radialChroma,
- timeSeconds, rippleOn, glitchOn);
+ float3 redSample = pardesSceneLinear(source, origin, size, uv + radialChroma);
+ float3 blueSample = pardesSceneLinear(source, origin, size, uv - radialChroma);
float3 col = float3(
redSample.r,
centerLinear.g,
@@ -308,8 +252,7 @@ extern "C" [[stitchable]] float4 pardesScene(
float2(0.0, bloom.y), float2(0.0, -bloom.y)
};
for (uint i = 0; i < 4; i++) {
- // Deliberately raw, like GLSL brightPass: bloom belongs to the source
- // image and does not recursively warp through the scene effects.
+ // Deliberately raw, like GLSL brightPass.
float4 sampleValue = pardesSceneSample(
source, origin, size, uv + bloomOffsets[i]);
float3 linearValue = coreimage::srgb_to_linear(sampleValue.rgb);
diff --git a/shaders/post/glitch.glsl b/shaders/post/glitch.glsl
deleted file mode 100644
index 8f420d9c..00000000
--- a/shaders/post/glitch.glsl
+++ /dev/null
@@ -1,64 +0,0 @@
-// Glitch: now and then the signal slips. At the default level, every couple
-// of seconds a short
-// burst tears a few horizontal bands sideways and pulls their red and blue
-// apart; the bands are sized in pixels and the burst eases in and out over
-// a fraction of a second, so it reads as one event rather than a flicker,
-// and it looks the same at 60 or 144 Hz because every step is keyed to
-// iTime, not to frames. Between bursts the page is left exactly as it is.
-// A torn band's brightness dips in linear light. It is a Shadertoy file:
-// pardes puts its prefix before it.
-
-// Each at levels 1, 2 and 3 (`Glitch 1`..`Glitch 3`); 2 is the default. A
-// higher level slips more often and harder.
-float period() { return pardesByLevel(4.5, 2.4, 0.55); } // seconds between bursts, on average
-float burst() { return pardesByLevel(0.2, 0.28, 0.5); } // seconds a burst lasts
-float stepHz() { return pardesByLevel(20.0, 24.0, 30.0); } // how often a burst re-tears
-float shiftPx() { return pardesByLevel(8.0, 14.0, 34.0); }
-float splitPx() { return pardesByLevel(1.5, 2.5, 6.0); }
-float dip() { return pardesByLevel(0.08, 0.12, 0.22); }
-float tearFrom() { return pardesByLevel(0.8, 0.72, 0.35); } // how few bands tear
-
-float hash(vec2 p) {
- vec3 q = fract(vec3(p.xyx) * 0.1031);
- q += dot(q, q.yzx + 33.33);
- return fract((q.x + q.y) * q.z);
-}
-
-vec3 toLinear(vec3 c) {
- return mix(pow((c + 0.055) / 1.055, vec3(2.4)), c / 12.92, lessThanEqual(c, vec3(0.04045)));
-}
-
-vec3 toSrgb(vec3 c) {
- c = max(c, vec3(0.0));
- return mix(1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, c * 12.92, lessThanEqual(c, vec3(0.0031308)));
-}
-
-void mainImage(out vec4 fragColor, in vec2 fragCoord) {
- vec2 size = iResolution.xy;
- vec2 uv = fragCoord / size;
- // Which burst window this is, when in it the burst starts, and how far
- // into the burst we are: 0 outside one.
- float window = floor(iTime / period());
- float start = window * period() + hash(vec2(window, 7.0)) * (period() - burst());
- float t = (iTime - start) / burst();
- float live = step(0.0, t) * step(t, 1.0);
- float envelope = live * sin(3.14159265 * clamp(t, 0.0, 1.0));
- if (envelope <= 0.0) {
- fragColor = texture(iChannel0, uv);
- return;
- }
- // Bands of 6 to 40 px, re-cut at stepHz() during the burst; about one
- // band in four tears.
- float tick = floor(iTime * stepHz());
- float band_px = mix(6.0, 40.0, hash(vec2(tick, 3.0)));
- float band = floor(fragCoord.y / band_px);
- float roll = hash(vec2(band, tick));
- float tear = smoothstep(tearFrom(), tearFrom() + 0.18, roll) * envelope;
- float shift = (hash(vec2(tick, band + 11.0)) - 0.5) * 2.0 * shiftPx() * tear;
- vec2 at = vec2(fragCoord.x + shift, fragCoord.y);
- vec2 split = vec2(splitPx() * tear, 0.0);
- vec4 center = texture(iChannel0, at / size);
- vec3 col = vec3(texture(iChannel0, (at + split) / size).r, center.g, texture(iChannel0, (at - split) / size).b);
- col = toSrgb(toLinear(col) * (1.0 - dip() * tear));
- fragColor = vec4(col, center.a);
-}
diff --git a/shaders/post/ripple.glsl b/shaders/post/ripple.glsl
deleted file mode 100644
index 3236d339..00000000
--- a/shaders/post/ripple.glsl
+++ /dev/null
@@ -1,52 +0,0 @@
-// Ripple: the page as a still pool a slow swell crosses. Rings travel out
-// from the middle of the window at a fixed speed in pixels, so they look
-// the same at any size and frame rate; at the default level the displacement
-// is at most a couple of pixels, so text stays readable, and it eases in over its first half
-// second instead of snapping on. Each ring catches the light a little on its
-// rising side, in linear light, and the result is dithered so the shading
-// never bands. It is a Shadertoy file: pardes puts its prefix before it.
-
-const float TAU = 6.28318530718;
-const float EASE_IN = 0.5; // seconds
-
-// Each at levels 1, 2 and 3 (`Ripple 1`..`Ripple 3`); 2 is the default.
-float wavelengthPx() { return pardesByLevel(170.0, 150.0, 120.0); }
-float speedPx() { return pardesByLevel(40.0, 55.0, 80.0); } // outward, per second
-float amplitudePx() { return pardesByLevel(1.2, 2.2, 5.0); }
-float shade() { return pardesByLevel(0.02, 0.035, 0.09); } // light on a slope, linear
-float reachEnd() { return pardesByLevel(0.85, 0.95, 1.3); } // how far out it dies away
-
-vec3 toLinear(vec3 c) {
- return mix(pow((c + 0.055) / 1.055, vec3(2.4)), c / 12.92, lessThanEqual(c, vec3(0.04045)));
-}
-
-vec3 toSrgb(vec3 c) {
- c = max(c, vec3(0.0));
- return mix(1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, c * 12.92, lessThanEqual(c, vec3(0.0031308)));
-}
-
-float ign(vec2 p) {
- return fract(52.9829189 * fract(dot(p, vec2(0.06711056, 0.00583715))));
-}
-
-void mainImage(out vec4 fragColor, in vec2 fragCoord) {
- vec2 size = iResolution.xy;
- vec2 center = 0.5 * size;
- vec2 offset = fragCoord - center;
- float radius = length(offset);
- float reach = 0.5 * length(size);
- // Strongest a third of the way out, fading to nothing at the middle
- // and at the edges, so the window's frame never wobbles.
- float envelope = smoothstep(0.0, 0.18, radius / reach) * (1.0 - smoothstep(0.35, reachEnd(), radius / reach));
- float ease = smoothstep(0.0, EASE_IN, iTime);
- float phase = (radius - iTime * speedPx()) * TAU / wavelengthPx();
- float height = sin(phase);
- float slope = cos(phase);
- vec2 dir = offset / max(radius, 1e-3);
- vec2 moved = fragCoord + dir * height * amplitudePx() * envelope * ease;
-
- vec4 s = texture(iChannel0, moved / size);
- vec3 col = toLinear(s.rgb) * (1.0 + shade() * slope * envelope * ease);
- vec3 srgb = toSrgb(col) + (ign(fragCoord + float(iFrame % 64) * 5.588238) - 0.5) / 255.0;
- fragColor = vec4(clamp(srgb, 0.0, 1.0), s.a);
-}
diff --git a/shaders/prebuilt/post-glitch.frag.glsl b/shaders/prebuilt/post-glitch.frag.glsl
deleted file mode 100644
index 7b288237..00000000
--- a/shaders/prebuilt/post-glitch.frag.glsl
+++ /dev/null
@@ -1,138 +0,0 @@
-#version 450
-// pardes's Shadertoy prefix (docs/render-pipeline.md §6), put before every
-// post pass: a bundled one in shaders/post/ at build time, a user's file at
-// run time. The uniform names, types and std140 order are ghostty 1.3.2's
-// (src/renderer/shaders/shadertoy_prefix.glsl), so a shader written for
-// ghostty runs here; only the bindings are SDL GPU's (a fragment shader's
-// textures in set 2, its uniform blocks in set 3). Y is down everywhere, as
-// on ghostty's Metal renderer: fragCoord, iChannel0's uv and the cursor
-// rectangles share one top-left space, and iCurrentCursor is (left x,
-// BOTTOM-edge y, width, height) in framebuffer pixels.
-
-layout(set = 3, binding = 0, std140) uniform Globals {
- uniform vec3 iResolution;
- uniform float iTime;
- uniform float iTimeDelta;
- uniform float iFrameRate;
- uniform int iFrame;
- uniform float iChannelTime[4];
- uniform vec3 iChannelResolution[4];
- uniform vec4 iMouse;
- uniform vec4 iDate;
- uniform float iSampleRate;
- uniform vec4 iCurrentCursor;
- uniform vec4 iPreviousCursor;
- uniform vec4 iCurrentCursorColor;
- uniform vec4 iPreviousCursorColor;
- uniform int iCurrentCursorStyle;
- uniform int iPreviousCursorStyle;
- uniform int iCursorVisible;
- uniform float iTimeCursorChange;
- uniform float iTimeFocus;
- uniform int iFocus;
- uniform vec3 iPalette[256];
- uniform vec3 iBackgroundColor;
- uniform vec3 iForegroundColor;
- uniform vec3 iCursorColor;
- uniform vec3 iCursorText;
- uniform vec3 iSelectionForegroundColor;
- uniform vec3 iSelectionBackgroundColor;
-};
-
-// pardes's own: pardesOpaque is 1 when the window is opaque, so a pass
-// cannot punch holes in it through its alpha; pardesLevel is a bundled
-// pass's strength, 1 to 3 (`Crt 3`), and 0 for a user's file.
-layout(set = 3, binding = 1, std140) uniform PardesPost {
- float pardesOpaque;
- float pardesLevel;
-};
-
-// A bundled pass's constant at levels 1, 2 and 3.
-float pardesByLevel(float one, float two, float three) {
- return pardesLevel < 1.5 ? one : (pardesLevel < 2.5 ? two : three);
-}
-
-#define CURSORSTYLE_BLOCK 0
-#define CURSORSTYLE_BLOCK_HOLLOW 1
-#define CURSORSTYLE_BAR 2
-#define CURSORSTYLE_UNDERLINE 3
-#define CURSORSTYLE_LOCK 4
-
-layout(set = 2, binding = 0) uniform sampler2D iChannel0;
-
-layout(location = 0) out vec4 _fragColor;
-
-#define texture2D texture
-
-void mainImage(out vec4 fragColor, in vec2 fragCoord);
-void main() {
- mainImage(_fragColor, gl_FragCoord.xy);
- if (pardesOpaque > 0.5) _fragColor.a = 1.0;
-}
-
-// The shader's own lines count from 1, so glslc's errors name them.
-#line 1
-// Glitch: now and then the signal slips. At the default level, every couple
-// of seconds a short
-// burst tears a few horizontal bands sideways and pulls their red and blue
-// apart; the bands are sized in pixels and the burst eases in and out over
-// a fraction of a second, so it reads as one event rather than a flicker,
-// and it looks the same at 60 or 144 Hz because every step is keyed to
-// iTime, not to frames. Between bursts the page is left exactly as it is.
-// A torn band's brightness dips in linear light. It is a Shadertoy file:
-// pardes puts its prefix before it.
-
-// Each at levels 1, 2 and 3 (`Glitch 1`..`Glitch 3`); 2 is the default. A
-// higher level slips more often and harder.
-float period() { return pardesByLevel(4.5, 2.4, 0.55); } // seconds between bursts, on average
-float burst() { return pardesByLevel(0.2, 0.28, 0.5); } // seconds a burst lasts
-float stepHz() { return pardesByLevel(20.0, 24.0, 30.0); } // how often a burst re-tears
-float shiftPx() { return pardesByLevel(8.0, 14.0, 34.0); }
-float splitPx() { return pardesByLevel(1.5, 2.5, 6.0); }
-float dip() { return pardesByLevel(0.08, 0.12, 0.22); }
-float tearFrom() { return pardesByLevel(0.8, 0.72, 0.35); } // how few bands tear
-
-float hash(vec2 p) {
- vec3 q = fract(vec3(p.xyx) * 0.1031);
- q += dot(q, q.yzx + 33.33);
- return fract((q.x + q.y) * q.z);
-}
-
-vec3 toLinear(vec3 c) {
- return mix(pow((c + 0.055) / 1.055, vec3(2.4)), c / 12.92, lessThanEqual(c, vec3(0.04045)));
-}
-
-vec3 toSrgb(vec3 c) {
- c = max(c, vec3(0.0));
- return mix(1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, c * 12.92, lessThanEqual(c, vec3(0.0031308)));
-}
-
-void mainImage(out vec4 fragColor, in vec2 fragCoord) {
- vec2 size = iResolution.xy;
- vec2 uv = fragCoord / size;
- // Which burst window this is, when in it the burst starts, and how far
- // into the burst we are: 0 outside one.
- float window = floor(iTime / period());
- float start = window * period() + hash(vec2(window, 7.0)) * (period() - burst());
- float t = (iTime - start) / burst();
- float live = step(0.0, t) * step(t, 1.0);
- float envelope = live * sin(3.14159265 * clamp(t, 0.0, 1.0));
- if (envelope <= 0.0) {
- fragColor = texture(iChannel0, uv);
- return;
- }
- // Bands of 6 to 40 px, re-cut at stepHz() during the burst; about one
- // band in four tears.
- float tick = floor(iTime * stepHz());
- float band_px = mix(6.0, 40.0, hash(vec2(tick, 3.0)));
- float band = floor(fragCoord.y / band_px);
- float roll = hash(vec2(band, tick));
- float tear = smoothstep(tearFrom(), tearFrom() + 0.18, roll) * envelope;
- float shift = (hash(vec2(tick, band + 11.0)) - 0.5) * 2.0 * shiftPx() * tear;
- vec2 at = vec2(fragCoord.x + shift, fragCoord.y);
- vec2 split = vec2(splitPx() * tear, 0.0);
- vec4 center = texture(iChannel0, at / size);
- vec3 col = vec3(texture(iChannel0, (at + split) / size).r, center.g, texture(iChannel0, (at - split) / size).b);
- col = toSrgb(toLinear(col) * (1.0 - dip() * tear));
- fragColor = vec4(col, center.a);
-}
diff --git a/shaders/prebuilt/post-glitch.frag.spv b/shaders/prebuilt/post-glitch.frag.spv
deleted file mode 100644
index 619616a8..00000000
--- a/shaders/prebuilt/post-glitch.frag.spv
+++ /dev/null
Binary files differ
diff --git a/shaders/prebuilt/post-ripple.frag.glsl b/shaders/prebuilt/post-ripple.frag.glsl
deleted file mode 100644
index d29a4c22..00000000
--- a/shaders/prebuilt/post-ripple.frag.glsl
+++ /dev/null
@@ -1,126 +0,0 @@
-#version 450
-// pardes's Shadertoy prefix (docs/render-pipeline.md §6), put before every
-// post pass: a bundled one in shaders/post/ at build time, a user's file at
-// run time. The uniform names, types and std140 order are ghostty 1.3.2's
-// (src/renderer/shaders/shadertoy_prefix.glsl), so a shader written for
-// ghostty runs here; only the bindings are SDL GPU's (a fragment shader's
-// textures in set 2, its uniform blocks in set 3). Y is down everywhere, as
-// on ghostty's Metal renderer: fragCoord, iChannel0's uv and the cursor
-// rectangles share one top-left space, and iCurrentCursor is (left x,
-// BOTTOM-edge y, width, height) in framebuffer pixels.
-
-layout(set = 3, binding = 0, std140) uniform Globals {
- uniform vec3 iResolution;
- uniform float iTime;
- uniform float iTimeDelta;
- uniform float iFrameRate;
- uniform int iFrame;
- uniform float iChannelTime[4];
- uniform vec3 iChannelResolution[4];
- uniform vec4 iMouse;
- uniform vec4 iDate;
- uniform float iSampleRate;
- uniform vec4 iCurrentCursor;
- uniform vec4 iPreviousCursor;
- uniform vec4 iCurrentCursorColor;
- uniform vec4 iPreviousCursorColor;
- uniform int iCurrentCursorStyle;
- uniform int iPreviousCursorStyle;
- uniform int iCursorVisible;
- uniform float iTimeCursorChange;
- uniform float iTimeFocus;
- uniform int iFocus;
- uniform vec3 iPalette[256];
- uniform vec3 iBackgroundColor;
- uniform vec3 iForegroundColor;
- uniform vec3 iCursorColor;
- uniform vec3 iCursorText;
- uniform vec3 iSelectionForegroundColor;
- uniform vec3 iSelectionBackgroundColor;
-};
-
-// pardes's own: pardesOpaque is 1 when the window is opaque, so a pass
-// cannot punch holes in it through its alpha; pardesLevel is a bundled
-// pass's strength, 1 to 3 (`Crt 3`), and 0 for a user's file.
-layout(set = 3, binding = 1, std140) uniform PardesPost {
- float pardesOpaque;
- float pardesLevel;
-};
-
-// A bundled pass's constant at levels 1, 2 and 3.
-float pardesByLevel(float one, float two, float three) {
- return pardesLevel < 1.5 ? one : (pardesLevel < 2.5 ? two : three);
-}
-
-#define CURSORSTYLE_BLOCK 0
-#define CURSORSTYLE_BLOCK_HOLLOW 1
-#define CURSORSTYLE_BAR 2
-#define CURSORSTYLE_UNDERLINE 3
-#define CURSORSTYLE_LOCK 4
-
-layout(set = 2, binding = 0) uniform sampler2D iChannel0;
-
-layout(location = 0) out vec4 _fragColor;
-
-#define texture2D texture
-
-void mainImage(out vec4 fragColor, in vec2 fragCoord);
-void main() {
- mainImage(_fragColor, gl_FragCoord.xy);
- if (pardesOpaque > 0.5) _fragColor.a = 1.0;
-}
-
-// The shader's own lines count from 1, so glslc's errors name them.
-#line 1
-// Ripple: the page as a still pool a slow swell crosses. Rings travel out
-// from the middle of the window at a fixed speed in pixels, so they look
-// the same at any size and frame rate; at the default level the displacement
-// is at most a couple of pixels, so text stays readable, and it eases in over its first half
-// second instead of snapping on. Each ring catches the light a little on its
-// rising side, in linear light, and the result is dithered so the shading
-// never bands. It is a Shadertoy file: pardes puts its prefix before it.
-
-const float TAU = 6.28318530718;
-const float EASE_IN = 0.5; // seconds
-
-// Each at levels 1, 2 and 3 (`Ripple 1`..`Ripple 3`); 2 is the default.
-float wavelengthPx() { return pardesByLevel(170.0, 150.0, 120.0); }
-float speedPx() { return pardesByLevel(40.0, 55.0, 80.0); } // outward, per second
-float amplitudePx() { return pardesByLevel(1.2, 2.2, 5.0); }
-float shade() { return pardesByLevel(0.02, 0.035, 0.09); } // light on a slope, linear
-float reachEnd() { return pardesByLevel(0.85, 0.95, 1.3); } // how far out it dies away
-
-vec3 toLinear(vec3 c) {
- return mix(pow((c + 0.055) / 1.055, vec3(2.4)), c / 12.92, lessThanEqual(c, vec3(0.04045)));
-}
-
-vec3 toSrgb(vec3 c) {
- c = max(c, vec3(0.0));
- return mix(1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, c * 12.92, lessThanEqual(c, vec3(0.0031308)));
-}
-
-float ign(vec2 p) {
- return fract(52.9829189 * fract(dot(p, vec2(0.06711056, 0.00583715))));
-}
-
-void mainImage(out vec4 fragColor, in vec2 fragCoord) {
- vec2 size = iResolution.xy;
- vec2 center = 0.5 * size;
- vec2 offset = fragCoord - center;
- float radius = length(offset);
- float reach = 0.5 * length(size);
- // Strongest a third of the way out, fading to nothing at the middle
- // and at the edges, so the window's frame never wobbles.
- float envelope = smoothstep(0.0, 0.18, radius / reach) * (1.0 - smoothstep(0.35, reachEnd(), radius / reach));
- float ease = smoothstep(0.0, EASE_IN, iTime);
- float phase = (radius - iTime * speedPx()) * TAU / wavelengthPx();
- float height = sin(phase);
- float slope = cos(phase);
- vec2 dir = offset / max(radius, 1e-3);
- vec2 moved = fragCoord + dir * height * amplitudePx() * envelope * ease;
-
- vec4 s = texture(iChannel0, moved / size);
- vec3 col = toLinear(s.rgb) * (1.0 + shade() * slope * envelope * ease);
- vec3 srgb = toSrgb(col) + (ign(fragCoord + float(iFrame % 64) * 5.588238) - 0.5) / 255.0;
- fragColor = vec4(clamp(srgb, 0.0, 1.0), s.a);
-}
diff --git a/shaders/prebuilt/post-ripple.frag.spv b/shaders/prebuilt/post-ripple.frag.spv
deleted file mode 100644
index 5f05f9f3..00000000
--- a/shaders/prebuilt/post-ripple.frag.spv
+++ /dev/null
Binary files differ