diff options
| author | LLLL Colonq <llll@colonq> | 2025-08-14 22:28:39 -0400 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2025-08-14 22:28:39 -0400 |
| commit | e4ded2c09e6c378040f80e80886aa9c087fe14b4 (patch) | |
| tree | 74984adf49dde6a1fe7b3b22c0d9c3e2168df267 /crates/renderer/src/overlay/drawing.rs | |
| parent | 4fb92d6fa3ce2d93c2ce720429f46aa104972674 (diff) | |
Automata rendering
Diffstat (limited to 'crates/renderer/src/overlay/drawing.rs')
| -rw-r--r-- | crates/renderer/src/overlay/drawing.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/crates/renderer/src/overlay/drawing.rs b/crates/renderer/src/overlay/drawing.rs new file mode 100644 index 0000000..8088b5a --- /dev/null +++ b/crates/renderer/src/overlay/drawing.rs @@ -0,0 +1,128 @@ +use teleia::*; + +use glow::HasContext; + +use crate::{background, input}; + +pub const SCALE: usize = 4; +pub const WIDTH: usize = 1920 / SCALE; +pub const HEIGHT: usize = 1080 / SCALE; +pub struct Drawing { + pub tex: texture::Texture, + pub pixels: [u8; WIDTH * HEIGHT], + pub last_point: Option<(i32, i32)>, + pub shader_white: shader::Shader, + pub shader_background: shader::Shader, +} +impl Drawing { + pub fn new(ctx: &context::Context) -> Self { + let shader_background = shader::Shader::new( + ctx, + include_str!("../assets/shaders/background/vert.glsl"), + include_str!("../assets/shaders/background/frag.glsl"), + ); + shader_background.set_i32(ctx, "background", 1); + Self { + tex: texture::Texture::new_empty(ctx), + pixels: [0; WIDTH * HEIGHT], + last_point: None, + shader_white: shader::Shader::new( + ctx, + include_str!("../assets/shaders/white/vert.glsl"), + include_str!("../assets/shaders/white/frag.glsl"), + ), + shader_background, + } + } + pub fn coord(&self, x: usize, y: usize) -> Option<usize> { + if x >= WIDTH || y >= HEIGHT { + None + } else { + Some(x + y * WIDTH) + } + } + pub fn set(&mut self, val: u8, x: i32, y: i32) { + self.coord(x as usize, y as usize).map(|idx| self.pixels[idx] = val); + } + pub fn point(&mut self, val: u8, x: i32, y: i32) { + self.set(val, x, y - 1); + self.set(val, x - 1, y); + self.set(val, x, y); + self.set(val, x + 1, y); + self.set(val, x, y + 1); + } + pub fn line(&mut self, val: u8, (mut x0, mut y0): (i32, i32), (x1, y1): (i32, i32)) { + let dx = (x1 - x0).abs(); + let sx = if x0 < x1 { 1 } else { -1 }; + let dy = -((y1 - y0).abs()); + let sy = if y0 < y1 { 1 } else { -1 }; + let mut error = dx + dy; + loop { + self.point(val, x0, y0); + let e2 = 2 * error; + if e2 >= dy { + if x0 == x1 { break; } + error += dy; + x0 += sx; + } + if e2 <= dx { + if y0 == y1 { break; } + error += dx; + y0 += sy; + } + } + } + pub fn upload(&self, ctx: &context::Context) { + unsafe { + let err = ctx.gl.get_error(); + self.tex.bind(ctx); + ctx.gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::R8 as i32, + WIDTH as i32, + HEIGHT as i32, + 0, + glow::RED, + glow::UNSIGNED_BYTE, + Some(&self.pixels), + ); + ctx.gl.generate_mipmap(glow::TEXTURE_2D); + } + } + pub fn update(&mut self, ctx: &context::Context, st: &mut state::State, inp: &mut input::Input) { + match inp.get_command() { + input::Command::Drawing => { + let (sx, sy) = inp.get_mouse(); + let x = sx / (SCALE as i32); + let y = sy / (SCALE as i32); + if let Some(last) = self.last_point { + self.line(1, last, (x, y)); + } else { + self.point(1, x, y); + } + self.last_point = Some((x, y)); + }, + input::Command::EraseAll => { + self.pixels.fill(0); + self.last_point = None; + }, + input::Command::None => { + self.last_point = None; + }, + _ => {}, + } + self.upload(ctx); + } + pub fn render(&self, ctx: &context::Context, st: &mut state::State, bg: &background::Backgrounds) { + st.bind_2d(ctx, &self.shader_background); + self.tex.bind(ctx); + bg.drawing.bind_index(ctx, 1); + self.shader_background.set_position_2d( + ctx, + &glam::Vec2::new(0.0, 0.0), + &glam::Vec2::new(1920.0, 1080.0) + ); + st.mesh_square.render(ctx); + } +} |
