From f5f7422d829089c54632c74a7d6cbbfe5872b5e4 Mon Sep 17 00:00:00 2001 From: winlith Date: Fri, 17 Jan 2025 22:37:48 +0100 Subject: [PATCH] color mix animation --- res/config.ini | 16 ++++++-- src/animations/ColorMix.zig | 76 +++++++++++++++++++++++++++++++++++++ src/config/Config.zig | 3 ++ src/enums.zig | 3 +- src/main.zig | 7 ++++ 5 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 src/animations/ColorMix.zig diff --git a/res/config.ini b/res/config.ini index 1d28cb8..debb6df 100644 --- a/res/config.ini +++ b/res/config.ini @@ -30,9 +30,10 @@ # config) will be used by Ly for fg = 0x0008. # The active animation -# none -> Nothing -# doom -> PSX DOOM fire -# matrix -> CMatrix +# none -> Nothing +# doom -> PSX DOOM fire +# matrix -> CMatrix +# colormix -> Color mixing shader animation = none # Stop the animation after some time @@ -90,6 +91,15 @@ clock = null # CMatrix animation foreground color id cmatrix_fg = 0x0003 +# Color mixing animation first color id +colormix_col1 = 0x0002 + +# Color mixing animation second color id +colormix_col2 = 0x0005 + +# Color mixing animation third color id +colormix_col3 = 0x0001 + # Console path console_dev = /dev/console diff --git a/src/animations/ColorMix.zig b/src/animations/ColorMix.zig new file mode 100644 index 0000000..d9b262a --- /dev/null +++ b/src/animations/ColorMix.zig @@ -0,0 +1,76 @@ +const math = @import("std").math; +const TerminalBuffer = @import("../tui/TerminalBuffer.zig"); +const utils = @import("../tui/utils.zig"); + +const ColorMix = @This(); + +const Vec2 = @Vector(2, f32); + +const time_scale: f32 = 0.01; +const palette_len: usize = 12; + +fn length(vec: Vec2) f32 { + return math.sqrt(vec[0] * vec[0] + vec[1] * vec[1]); +} + +terminal_buffer: *TerminalBuffer, +frames: u64, +pattern_cos_mod: f32, +pattern_sin_mod: f32, +palette: [palette_len]utils.Cell, + +pub fn init(terminal_buffer: *TerminalBuffer, col1: u16, col2: u16, col3: u16) ColorMix { + return .{ + .terminal_buffer = terminal_buffer, + .frames = 0, + .pattern_cos_mod = terminal_buffer.random.float(f32) * math.pi * 2.0, + .pattern_sin_mod = terminal_buffer.random.float(f32) * math.pi * 2.0, + .palette = [palette_len]utils.Cell{ + utils.initCell(0x2588, col1, col2), + utils.initCell(0x2593, col1, col2), + utils.initCell(0x2592, col1, col2), + utils.initCell(0x2591, col1, col2), + utils.initCell(0x2588, col2, col3), + utils.initCell(0x2593, col2, col3), + utils.initCell(0x2592, col2, col3), + utils.initCell(0x2591, col2, col3), + utils.initCell(0x2588, col3, col1), + utils.initCell(0x2593, col3, col1), + utils.initCell(0x2592, col3, col1), + utils.initCell(0x2591, col3, col1), + }, + }; +} + +pub fn draw(self: *ColorMix) void { + self.frames +%= 1; + const time: f32 = @as(f32, @floatFromInt(self.frames)) * time_scale; + + for (0..self.terminal_buffer.width) |x| { + for (0..self.terminal_buffer.height) |y| { + var uv: Vec2 = .{ + @as(f32, @floatFromInt(@as(i32, @intCast(x)) * 2 - @as(i32, @intCast(self.terminal_buffer.width)))) / @as(f32, @floatFromInt(self.terminal_buffer.height * 2)), + @as(f32, @floatFromInt(@as(i32, @intCast(y)) * 2 - @as(i32, @intCast(self.terminal_buffer.height)))) / @as(f32, @floatFromInt(self.terminal_buffer.height)), + }; + + var uv2: Vec2 = @splat(uv[0] + uv[1]); + + for (0..3) |_| { + uv2 += uv + @as(Vec2, @splat(length(uv))); + uv += @as(Vec2, @splat(0.5)) * Vec2{ + math.cos(self.pattern_cos_mod + uv2[1] * 0.2 + time * 0.1), + math.sin(self.pattern_sin_mod + uv2[0] - time * 0.1), + }; + uv -= @splat(1.0 * math.cos(uv[0] + uv[1]) - math.sin(uv[0] * 0.7 - uv[1])); + } + + const cell = self.palette[@as(usize, @intFromFloat(math.floor(length(uv) * 5.0))) % palette_len]; + const screen_index: usize = y * self.terminal_buffer.width + x; + self.terminal_buffer.buffer[screen_index] = .{ + .ch = cell.ch, + .fg = cell.fg, + .bg = cell.bg, + }; + } + } +} diff --git a/src/config/Config.zig b/src/config/Config.zig index 38c8b4c..1ab4232 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -22,6 +22,9 @@ brightness_up_key: []const u8 = "F6", clear_password: bool = false, clock: ?[:0]const u8 = null, cmatrix_fg: u16 = 3, +colormix_col1: u16 = 2, +colormix_col2: u16 = 5, +colormix_col3: u16 = 1, console_dev: []const u8 = "/dev/console", default_input: Input = .login, error_bg: u16 = 0, diff --git a/src/enums.zig b/src/enums.zig index ad0cc47..6d1f1f3 100644 --- a/src/enums.zig +++ b/src/enums.zig @@ -2,6 +2,7 @@ pub const Animation = enum { none, doom, matrix, + colormix, }; pub const DisplayServer = enum { @@ -27,4 +28,4 @@ pub const Bigclock = enum { none, en, fa, -}; \ No newline at end of file +}; diff --git a/src/main.zig b/src/main.zig index 4afefad..e58fafe 100644 --- a/src/main.zig +++ b/src/main.zig @@ -8,6 +8,7 @@ const bigclock = @import("bigclock.zig"); const interop = @import("interop.zig"); const Doom = @import("animations/Doom.zig"); const Matrix = @import("animations/Matrix.zig"); +const ColorMix = @import("animations/ColorMix.zig"); const TerminalBuffer = @import("tui/TerminalBuffer.zig"); const Session = @import("tui/components/Session.zig"); const Text = @import("tui/components/Text.zig"); @@ -303,17 +304,20 @@ pub fn main() !void { // Initialize the animation, if any var doom: Doom = undefined; var matrix: Matrix = undefined; + var color_mix: ColorMix = undefined; switch (config.animation) { .none => {}, .doom => doom = try Doom.init(allocator, &buffer), .matrix => matrix = try Matrix.init(allocator, &buffer, config.cmatrix_fg), + .colormix => color_mix = ColorMix.init(&buffer, config.colormix_col1, config.colormix_col2, config.colormix_col3), } defer { switch (config.animation) { .none => {}, .doom => doom.deinit(), .matrix => matrix.deinit(), + .colormix => {}, } } @@ -365,6 +369,7 @@ pub fn main() !void { .matrix => matrix.realloc() catch { try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg); }, + .colormix => {}, } update = true; @@ -382,6 +387,7 @@ pub fn main() !void { .none => {}, .doom => doom.draw(), .matrix => matrix.draw(), + .colormix => color_mix.draw(), } } @@ -542,6 +548,7 @@ pub fn main() !void { .none => {}, .doom => doom.deinit(), .matrix => matrix.deinit(), + .colormix => {}, } } } else if (config.bigclock != .none and config.clock == null) {