Skip to content

Commit

Permalink
Allow paning / zooming viewport
Browse files Browse the repository at this point in the history
  • Loading branch information
connorslade committed Jan 27, 2025
1 parent 6c6ed4d commit 90aa038
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 17 deletions.
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,13 @@ impl App<'_> {

self.renderer.render(self, &mut encoder, &view);
self.egui.render(gc, &mut encoder, &view, |ctx| {
self.gui.ui(ctx, gc, &mut self.simulation, &mut self.fps);
self.gui.ui(
ctx,
gc,
&mut self.simulation,
&mut self.renderer,
&mut self.fps,
);
});

let snapshot = self
Expand Down
13 changes: 8 additions & 5 deletions src/renderer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::mem;

use anyhow::Result;
use encase::{ShaderType, UniformBuffer};
use image::{GenericImageView, ImageBuffer, Rgba};
Expand All @@ -26,6 +24,7 @@ pub struct Renderer {
context: Buffer,

pub pan: Vector2<f32>,
pub zoom: f32,
}

#[derive(ShaderType, Default)]
Expand All @@ -37,6 +36,9 @@ pub struct RenderContext {
flags: u32,
gain: f32,
energy_gain: f32,

pan: Vector2<f32>,
zoom: f32,
}

impl Renderer {
Expand Down Expand Up @@ -78,9 +80,7 @@ impl Renderer {
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: BufferSize::new(
dbg!(mem::size_of::<RenderContext>()) as _
),
min_binding_size: BufferSize::new(48),
},
count: None,
},
Expand Down Expand Up @@ -138,6 +138,7 @@ impl Renderer {
context,

pan: Vector2::zeros(),
zoom: 1.0,
}
}

Expand Down Expand Up @@ -177,6 +178,8 @@ impl Renderer {
// TODO: move out of simulation
gain: app.simulation.gain,
energy_gain: app.simulation.energy_gain,
pan: self.pan,
zoom: self.zoom,
})
.unwrap();
gc.queue
Expand Down
21 changes: 10 additions & 11 deletions src/shaders/render.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@ struct Context {
// 1 << 1: energy_view
flags: u32,
gain: f32,
energy_gain: f32
energy_gain: f32,

pan: vec2<f32>,
zoom: f32,
}

// VERTEX SHADER //

struct VertexOutput {
@builtin(position)
position: vec4<f32>,
};
}

@vertex
fn vert(
Expand Down Expand Up @@ -52,20 +55,16 @@ fn index(x: u32, y: u32, n: u32) -> u32 {

@fragment
fn frag(in: VertexOutput) -> @location(0) vec4<f32> {
// ↓ Use vector operations
let x_offset = ctx.window.x / 2 - ctx.size.x / 2;
let y_offset = ctx.window.y / 2 - ctx.size.y / 2;
let x = i32(in.position.x) - i32(x_offset);
let y = i32(in.position.y) - i32(y_offset);
let pos = vec2<i32>((in.position.xy - ctx.pan) * ctx.zoom );

if x == -1 || y == -1 || x == i32(ctx.size.x) || y == i32(ctx.size.y) {
if pos.x == -1 || pos.y == -1 || pos.x == i32(ctx.size.x) || pos.y == i32(ctx.size.y) {
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
} else if x < 0 || x > i32(ctx.size.x) || y < 0 || y > i32(ctx.size.y) {
} else if pos.x < 0 || pos.x > i32(ctx.size.x) || pos.y < 0 || pos.y > i32(ctx.size.y) {
return vec4<f32>(1.0, 1.0, 1.0, 1.0);
}

if (ctx.flags & 0x02) != 0 {
var val = clamp(average_energy[u32(y) * ctx.size.x + u32(x)] * ctx.energy_gain, 0.0, 1.0);
var val = clamp(average_energy[u32(pos.y) * ctx.size.x + u32(pos.x)] * ctx.energy_gain, 0.0, 1.0);
let scheme_index = u32(val * 3.0);
val = val * 3.0 - f32(scheme_index);

Expand All @@ -86,7 +85,7 @@ fn frag(in: VertexOutput) -> @location(0) vec4<f32> {
return vec4<f32>(color, 1.0);
}

let val = states[index(u32(x), u32(y), ctx.tick % 3)] * ctx.gain;
let val = states[index(u32(pos.x), u32(pos.y), ctx.tick % 3)] * ctx.gain;
let color = (
vec3<f32>(0.0, 0.0, 1.0) * f32(val > 0.0)
+ vec3<f32>(1.0, 0.0, 0.0) * f32(val < 0.0)
Expand Down
20 changes: 20 additions & 0 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ use std::time::{Duration, Instant};

use bitflags::Flags;
use egui::{emath::Numeric, Color32, Context, DragValue, RichText, Slider, Ui, Window};
use nalgebra::Vector2;
use wgpu::{Buffer, CommandEncoder};

use crate::{
renderer::Renderer,
simulation::{Simulation, SimulationFlags},
FpsTracker, GraphicsContext,
};
Expand All @@ -31,12 +33,30 @@ impl Gui {
ctx: &Context,
gc: &GraphicsContext,
simulation: &mut Simulation,
render: &mut Renderer,
fps: &mut FpsTracker,
) {
let now = Instant::now();
let frame_time = now - fps.last_frame;
fps.last_frame = now;

let dragging_viewport = ctx.dragged_id().is_none();
let scale_factor = gc.window.scale_factor() as f32;

ctx.input(|input| {
let pointer = input.pointer.latest_pos().unwrap_or_default();
let pointer = Vector2::new(pointer.x, pointer.y) * scale_factor;

let old_zoom = render.zoom;
render.zoom = (old_zoom + input.smooth_scroll_delta.y / 1000.0).max(0.05);
render.pan += (pointer - render.pan) * (1.0 - (old_zoom / render.zoom));

if input.pointer.any_down() && dragging_viewport {
let delta = input.pointer.delta() * scale_factor;
render.pan += Vector2::new(delta.x, delta.y);
}
});

Window::new("Wave Simulator")
.default_width(0.0)
.show(ctx, |ui| {
Expand Down

0 comments on commit 90aa038

Please sign in to comment.