summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.zig22
-rw-r--r--src/effect_sources.zig8
-rw-r--r--src/gui/Post.zig8
-rw-r--r--src/macos.zig17
-rw-r--r--src/macos/Sources/PardesView.swift2
-rw-r--r--src/macos/Sources/ScenePostprocessor.swift48
-rw-r--r--src/macos/pardes.h5
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