diff options
Diffstat (limited to 'src/macos')
| -rw-r--r-- | src/macos/Sources/PardesView.swift | 2 | ||||
| -rw-r--r-- | src/macos/Sources/ScenePostprocessor.swift | 48 | ||||
| -rw-r--r-- | src/macos/pardes.h | 5 |
3 files changed, 6 insertions, 49 deletions
diff --git a/src/macos/Sources/PardesView.swift b/src/macos/Sources/PardesView.swift index 70f467e3..8ba9c84b 100644 --- a/src/macos/Sources/PardesView.swift +++ b/src/macos/Sources/PardesView.swift @@ -684,7 +684,7 @@ final class PardesView: NSView { private var latchedButton: pardes_mouse_button_e? private var latchedCell: GridPoint? /// Last physical point delivered by AppKit and its mapping through the - /// accepted scene. Ripple/glitch can move a source cell under a stationary + /// accepted scene. The CRT's barrel moves a source cell under a stationary /// hand, so successful scene presentations reconcile this point again. private var pointerPoint: CGPoint? private var pointerCell: GridPoint? diff --git a/src/macos/Sources/ScenePostprocessor.swift b/src/macos/Sources/ScenePostprocessor.swift index cf7892b3..41d54e34 100644 --- a/src/macos/Sources/ScenePostprocessor.swift +++ b/src/macos/Sources/ScenePostprocessor.swift @@ -205,11 +205,9 @@ final class ScenePostprocessor { if scene.flags != 0 { let crt: Float = scene.flags & UInt32(PARDES_SCENE_CRT) != 0 ? 1 : 0 - let ripple: Float = scene.flags & UInt32(PARDES_SCENE_RIPPLE) != 0 ? 1 : 0 - let glitch: Float = scene.flags & UInt32(PARDES_SCENE_GLITCH) != 0 ? 1 : 0 // SDL samples the scene with CLAMP_TO_EDGE. A finite Core Image // instead supplies transparent black outside its extent, which - // would make ripple/glitch tear dark seams at the window edge. + // would tear dark seams at the window edge. // Clamp the input only; the kernel still emits true black before // sampling when a destination lies outside the CRT tube. let sceneInput = filtered.clampedToExtent() @@ -218,7 +216,7 @@ final class ScenePostprocessor { roiCallback: { _, _ in extent }, arguments: [ sceneInput, scene.time_seconds, Float(scene.frame), - crt, ripple, glitch, + crt, CIVector(x: extent.width, y: extent.height), CIVector(x: extent.minX, y: extent.minY), ]) @@ -291,7 +289,7 @@ final class ScenePostprocessor { /// The scene kernel is a destination-to-source mapping. Pointer input must /// apply that same mapping before the grid and its panel tracks see a cell, - /// otherwise a visible word under ripple/glitch is not the word Look gets. + /// otherwise a visible word under the barrel is not the word Look gets. static func sourcePoint( _ point: CGPoint, size: CGSize, @@ -311,27 +309,8 @@ final class ScenePostprocessor { ccY *= barrel uvX = ccX * 0.5 + 0.5 uvY = ccY * 0.5 + 0.5 - // Only CRT has a black tube. Ripple/glitch without CRT sample through - // the texture's clamp-to-edge policy and remain clickable there. + // The CRT's black tube has no cell under it. if crt > 0.5 && min(min(uvX, uvY), min(1 - uvX, 1 - uvY)) <= 0 { return nil } - - let time = scene.time_seconds - if scene.flags & UInt32(PARDES_SCENE_RIPPLE) != 0 { - let centeredX = uvX - 0.5 - let centeredY = uvY - 0.5 - let radius = sqrtf(centeredX * centeredX + centeredY * centeredY) - let envelope = 1 - smoothstep(0.04, 0.72, radius) - let wave = sinf(radius * 42 - time * 5.2) - let travel = wave * envelope * 0.0032 / max(radius, 0.00001) - uvX += centeredX * travel - uvY += centeredY * travel - } - if scene.flags & UInt32(PARDES_SCENE_GLITCH) != 0 { - let band = floorf(uvY * 96) - let seed = noise(band, floorf(time * 13)) - let tear = smoothstep(0.955, 1, seed) - uvX += (noise(seed, band) - 0.5) * tear * 0.020 - } uvX = min(max(uvX, 0), max(0, 1 - 1 / Float(size.width))) uvY = min(max(uvY, 0), max(0, 1 - 1 / Float(size.height))) return CGPoint( @@ -339,23 +318,4 @@ final class ScenePostprocessor { y: CGFloat(1 - uvY) * size.height) } - private static func smoothstep(_ edge0: Float, _ edge1: Float, _ x: Float) -> Float { - let t = min(max((x - edge0) / (edge1 - edge0), 0), 1) - return t * t * (3 - 2 * t) - } - - /// Scalar spelling of pardesNoise in crt.ci.metal. Float arithmetic is - /// deliberate: the shader's band decision must not move at a Double round. - private static func noise(_ x: Float, _ y: Float) -> Float { - var qx = fract(x * 0.1031) - var qy = fract(y * 0.1031) - var qz = fract(x * 0.1031) - let d = qx * (qy + 33.33) + qy * (qz + 33.33) + qz * (qx + 33.33) - qx += d - qy += d - qz += d - return fract((qx + qy) * qz) - } - - private static func fract(_ x: Float) -> Float { x - floorf(x) } } diff --git a/src/macos/pardes.h b/src/macos/pardes.h index f74330e5..29f8a37d 100644 --- a/src/macos/pardes.h +++ b/src/macos/pardes.h @@ -82,8 +82,7 @@ typedef struct { // from the background colour, which a real selection shares. #define PARDES_CELL_HOVER 0x04u -// One coherent snapshot for the full-window shader pass. The bitmask lets the -// host run CRT, ripple and glitch in one kernel instead of stacking filters; +// One coherent snapshot for the full-window shader pass (CRT); // time/frame advance only on pardes_animation_tick's display clock. typedef struct { uint32_t flags; @@ -92,8 +91,6 @@ typedef struct { } pardes_scene_s; #define PARDES_SCENE_CRT 0x01u -#define PARDES_SCENE_RIPPLE 0x02u -#define PARDES_SCENE_GLITCH 0x04u // One backend-neutral pane transition. Boxes are logical cell rectangles; // the native shader converts them to backing pixels using the same measured |
