diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.zig | 22 | ||||
| -rw-r--r-- | src/effect_sources.zig | 8 | ||||
| -rw-r--r-- | src/gui/Post.zig | 8 | ||||
| -rw-r--r-- | src/macos.zig | 17 | ||||
| -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 |
7 files changed, 19 insertions, 91 deletions
diff --git a/src/config.zig b/src/config.zig index e8c5a705..d1e5f23d 100644 --- a/src/config.zig +++ b/src/config.zig @@ -129,8 +129,6 @@ pub const leader_path = paths: { } if (builtins.capabilities.scene_shaders) { table.set(.Crt, "tr"); - table.set(.Ripple, "tR"); - table.set(.Glitch, "tg"); table.set(.Shader, null); table.set(.ShaderAnimation, null); } @@ -622,7 +620,7 @@ pub const Runtime = struct { pub const ShaderAnimation = enum { off, on, always }; - /// Each pass a bundled effect (Crt, Ripple, Glitch) or a Shadertoy file. + /// Each pass the bundled Crt or a Shadertoy file. pub const Post = struct { pub const max = 8; pub const Entry = struct { @@ -774,8 +772,8 @@ pub const Runtime = struct { pub const MessageTime = enum { linger, fall, dissolve }; pub const Toggle = enum { colors, wrap, tree_context_tag_style, tag_bottom, debug, focus_tint, column_tags, syntax_bold, verbose, message_animation, ligatures }; - /// The bundled post passes, each a Shadertoy file in shaders/post/. - pub const Scene = enum { crt, ripple, glitch }; + /// The bundled post pass, a Shadertoy file in shaders/post/. + pub const Scene = enum { crt }; pub const Action = union(enum) { toggle: Toggle, @@ -843,8 +841,6 @@ pub const Runtime = struct { .{ .word = "PanelScramble", .action = .{ .transition = .scramble }, .availability = .panel_transitions }, .{ .word = "PanelType", .action = .{ .transition = .typewriter }, .availability = .panel_transitions }, .{ .word = "Crt", .action = .{ .scene = .crt }, .availability = .scene_shaders }, - .{ .word = "Ripple", .action = .{ .scene = .ripple }, .availability = .scene_shaders }, - .{ .word = "Glitch", .action = .{ .scene = .glitch }, .availability = .scene_shaders }, .{ .word = "Shader", .action = .shader, .availability = .scene_shaders }, .{ .word = "ShaderAnimation", .action = .shader_animation, .availability = .scene_shaders }, }; @@ -1263,18 +1259,18 @@ pub const Runtime = struct { test "the post chain runs in the order its passes were put in, and Shader off empties it of files" { var state: Runtime = .{}; try std.testing.expect(apply(&state, find("Shader").?, " ~/a.glsl\n")); - try std.testing.expect(apply(&state, find("Glitch").?, "on")); + try std.testing.expect(apply(&state, find("Crt").?, "on")); try std.testing.expect(apply(&state, find("Shader").?, "/b.glsl")); const chain = state.post.list(); try std.testing.expectEqual(@as(usize, 3), chain.len); try std.testing.expectEqualStrings("~/a.glsl", chain[0].path.get()); - try std.testing.expectEqual(Scene.glitch, chain[1].scene.?); + try std.testing.expectEqual(Scene.crt, chain[1].scene.?); try std.testing.expectEqualStrings("/b.glsl", chain[2].path.get()); const moved = state.post.generation; // A file named again leaves; the others keep their order. try std.testing.expect(apply(&state, find("Shader").?, "~/a.glsl")); try std.testing.expect(state.post.generation != moved); - try std.testing.expectEqual(Scene.glitch, state.post.list()[0].scene.?); + try std.testing.expectEqual(Scene.crt, state.post.list()[0].scene.?); try std.testing.expect(apply(&state, find("Shader").?, "off")); try std.testing.expectEqual(@as(usize, 1), state.post.len); try std.testing.expect(!apply(&state, find("Shader").?, null)); @@ -1288,7 +1284,7 @@ pub const Runtime = struct { const crt = find("Crt").?; try std.testing.expect(apply(&state, crt, "on")); try std.testing.expectEqual(@as(u8, Post.default_level), state.post.level(.crt)); - try std.testing.expect(apply(&state, find("Glitch").?, "1")); + try std.testing.expect(apply(&state, find("Shader").?, "/after.glsl")); const moved = state.post.generation; try std.testing.expect(apply(&state, crt, "3")); try std.testing.expectEqual(@as(u8, 3), state.post.level(.crt)); @@ -1472,8 +1468,6 @@ pub const Runtime = struct { }, .scene => |effect| switch (effect) { .crt => "Crt 2\n", - .ripple => "Ripple 2\n", - .glitch => "Glitch 2\n", }, .shader => "Shader ~/crt.glsl\n", .shader_animation => "ShaderAnimation always\n", @@ -1544,8 +1538,6 @@ pub const Runtime = struct { try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Font requested") == null); try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Panel transition off\n") != null); try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Crt unsupported\n") != null); - try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Ripple unsupported\n") != null); - try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Glitch unsupported\n") != null); try std.testing.expect(std.mem.indexOf(u8, defaults_report, "TaglineSize unsupported\n") != null); try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Look hover delay: off\n") != null); try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Native images: off\n") != null); diff --git a/src/effect_sources.zig b/src/effect_sources.zig index 6ce11160..83bd1313 100644 --- a/src/effect_sources.zig +++ b/src/effect_sources.zig @@ -12,10 +12,8 @@ const ui_fragment_path = shader_dir ++ "ui.frag.glsl"; const image_vertex_path = shader_dir ++ "image.vert.glsl"; const image_fragment_path = shader_dir ++ "image.frag.glsl"; const post_vertex_path = shader_dir ++ "post.vert.glsl"; -// The bundled post passes as compiled: the prefix and the pass together. +// The bundled post pass as compiled: the prefix and the pass together. const post_crt_path = shader_dir ++ "post-crt.frag.glsl"; -const post_ripple_path = shader_dir ++ "post-ripple.frag.glsl"; -const post_glitch_path = shader_dir ++ "post-glitch.frag.glsl"; pub const Backend = @TypeOf(build_config.platform); pub const backend: Backend = build_config.platform; @@ -55,8 +53,6 @@ pub const files = switch (backend) { .{ .path = image_fragment_path, .contents = @embedFile("effect-source-image.frag.glsl") }, .{ .path = post_vertex_path, .contents = @embedFile("effect-source-post.vert.glsl") }, .{ .path = post_crt_path, .contents = @embedFile("effect-source-post-crt.frag.glsl") }, - .{ .path = post_ripple_path, .contents = @embedFile("effect-source-post-ripple.frag.glsl") }, - .{ .path = post_glitch_path, .contents = @embedFile("effect-source-post-glitch.frag.glsl") }, }, .macos => [_]filesystem.Source{ .{ .path = "src/macos/Sources/PardesView.swift", .contents = @embedFile("macos/Sources/PardesView.swift") }, @@ -77,8 +73,6 @@ pub fn forSetting(setting: config.Runtime.Setting) ?[]const []const u8 { .scene => |effect| switch (backend) { .gui => switch (effect) { .crt => &.{ "src/gui/Post.zig", "src/gui/gui.zig", post_vertex_path, post_crt_path }, - .ripple => &.{ "src/gui/Post.zig", "src/gui/gui.zig", post_vertex_path, post_ripple_path }, - .glitch => &.{ "src/gui/Post.zig", "src/gui/gui.zig", post_vertex_path, post_glitch_path }, }, .macos => &.{ "src/macos/Sources/PardesView.swift", "src/macos/Sources/ScenePostprocessor.swift", "shaders/crt.ci.metal" }, .tty, .web, .esp32p4 => null, diff --git a/src/gui/Post.zig b/src/gui/Post.zig index d9d3d53e..f715965f 100644 --- a/src/gui/Post.zig +++ b/src/gui/Post.zig @@ -1,7 +1,7 @@ //! The post chain (docs/render-pipeline.md ยง6): Shadertoy passes over the //! finished frame, each reading the one before it (the frame first) and the -//! last one writing the window. A pass is bundled (Crt, Ripple, Glitch: -//! shaders/post/, compiled with the build) or a user's file (Shader <path>), +//! last one writing the window. A pass is the bundled Crt (shaders/post/, +//! compiled with the build) or a user's file (Shader <path>), //! compiled when it joins the chain by the build's own glslc invocation on a //! thread of its own, never on the frame path. A file whose compile fails //! keeps its last good pipeline, and glslc missing is said once. @@ -28,8 +28,6 @@ const prefix = @embedFile("post-prefix.glsl"); const vert_spv = @embedFile("post.vert.spv"); const bundled_spv = std.EnumArray(Scene, []const u8).init(.{ .crt = @embedFile("post-crt.frag.spv"), - .ripple = @embedFile("post-ripple.frag.spv"), - .glitch = @embedFile("post-glitch.frag.spv"), }); /// ghostty's Shadertoy uniform block, member for member in the GLSL block's @@ -170,7 +168,7 @@ fn collect(post: *Post, gpa: std.mem.Allocator, device: *c.SDL_GPUDevice, format .none => {}, .missing => if (!post.missing_said) { post.missing_said = true; - core.setMessage(core.active, "Shader: glslc is not on PATH, so Shadertoy files do not run (Crt, Ripple and Glitch do)"); + core.setMessage(core.active, "Shader: glslc is not on PATH, so Shadertoy files do not run (Crt does)"); }, .failed => |text| { defer gpa.free(text); diff --git a/src/macos.zig b/src/macos.zig index 0bad86ee..6cd7838f 100644 --- a/src/macos.zig +++ b/src/macos.zig @@ -112,8 +112,6 @@ const cell_flag_default: u8 = 1; const cell_flag_tagline: u8 = 2; const cell_flag_hover: u8 = 4; const scene_flag_crt: u32 = 1 << 0; -const scene_flag_ripple: u32 = 1 << 1; -const scene_flag_glitch: u32 = 1 << 2; const scene_frame_hz: u32 = 60; const scene_wrap_ns: u64 = 4096 * std.time.ns_per_s; @@ -850,13 +848,11 @@ export fn pardes_should_quit() bool { return st.core.quit; } -// The Metal shell keeps its own CRT, ripple and glitch kernel: the bundled -// passes of the GUI's post chain, as flags. +// The Metal shell keeps its own CRT kernel: the GUI's bundled post pass, as +// a flag. fn encodeSceneEffects(post: *const pardes.config.Runtime.Post) u32 { var flags: u32 = 0; if (post.has(.crt)) flags |= scene_flag_crt; - if (post.has(.ripple)) flags |= scene_flag_ripple; - if (post.has(.glitch)) flags |= scene_flag_glitch; return flags; } @@ -2842,8 +2838,6 @@ test "pardes.h matches the Zig boundary" { try expectEqual(@as(u8, c.PARDES_CELL_HOVER), cell_flag_hover); try expectEqual(@as(u16, c.PARDES_TOPBAR_H), pardes.TOPBAR_H); try expectEqual(@as(u32, c.PARDES_SCENE_CRT), scene_flag_crt); - try expectEqual(@as(u32, c.PARDES_SCENE_RIPPLE), scene_flag_ripple); - try expectEqual(@as(u32, c.PARDES_SCENE_GLITCH), scene_flag_glitch); try expectEqual(@as(u8, c.PARDES_PANEL_OPENING), @intFromEnum(animation.Phase.opening)); try expectEqual(@as(u8, c.PARDES_PANEL_MOVING), @intFromEnum(animation.Phase.moving)); try expectEqual(@as(u8, c.PARDES_PANEL_CLOSING), @intFromEnum(animation.Phase.closing)); @@ -2918,13 +2912,6 @@ test "scene effect flags and display clock are compact and independent" { try expectEqual(@as(u32, 0), encodeSceneEffects(&post)); _ = post.set(.crt, "", true); try expectEqual(scene_flag_crt, encodeSceneEffects(&post)); - _ = post.set(.ripple, "", true); - _ = post.set(.glitch, "", true); - try expectEqual(scene_flag_crt | scene_flag_ripple | scene_flag_glitch, encodeSceneEffects(&post)); - try expectEqual( - scene_flag_crt | scene_flag_ripple | scene_flag_glitch, - encodeSceneEffects(.{ .crt = true, .ripple = true, .glitch = true }), - ); var st: State = undefined; st.scene_ns = scene_wrap_ns - (std.time.ns_per_ms * 5); 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 |
