summaryrefslogtreecommitdiff
path: root/shaders/crt.ci.metal
diff options
context:
space:
mode:
Diffstat (limited to 'shaders/crt.ci.metal')
-rw-r--r--shaders/crt.ci.metal75
1 files changed, 9 insertions, 66 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);