Skip to content

Commit

Permalink
Optional bilinier 'smooth' sampling
Browse files Browse the repository at this point in the history
  • Loading branch information
connorslade committed Jan 27, 2025
1 parent 90aa038 commit 9bf63e1
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 3 deletions.
58 changes: 56 additions & 2 deletions src/shaders/render.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,60 @@ fn index(x: u32, y: u32, n: u32) -> u32 {
return (ctx.size.x * ctx.size.y * n) + (y * ctx.size.x) + x;
}

fn nearest_neighbor_sample_avg_energy(pos: vec2<i32>) -> f32 {
return average_energy[u32(pos.y) * ctx.size.x + u32(pos.x)];
}

fn bilinear_sample_avg_energy(origin: vec2<f32>, pos: vec2<i32>) -> f32 {
let x = vec2<i32>(max(0, min(i32(ctx.size.x) - 1, pos.x)), max(0, min(i32(ctx.size.x) - 1, pos.x + 1)));
let y = vec2<i32>(max(0, min(i32(ctx.size.y) - 1, pos.y)), max(0, min(i32(ctx.size.y) - 1, pos.y + 1)));

let s = vec4<f32>(
nearest_neighbor_sample_avg_energy(vec2<i32>(x.x, y.x)),
nearest_neighbor_sample_avg_energy(vec2<i32>(x.y, y.x)),
nearest_neighbor_sample_avg_energy(vec2<i32>(x.x, y.y)),
nearest_neighbor_sample_avg_energy(vec2<i32>(x.y, y.y))
);

let f = fract((origin - ctx.pan) * ctx.zoom);
return mix(mix(s.x, s.y, f.x), mix(s.z, s.w, f.x), f.y);
}

fn sample_avg_energy(origin: vec2<f32>, pos: vec2<i32>) -> f32 {
if (ctx.flags & 0x04) != 0 {
return bilinear_sample_avg_energy(origin, pos);
} else {
return nearest_neighbor_sample_avg_energy(pos);
}
}

fn nearest_neighbor_sample(pos: vec2<i32>, tick: u32) -> f32 {
return states[index(u32(pos.x), u32(pos.y), tick % 3)];
}

fn bilinear_sample(origin: vec2<f32>, pos: vec2<i32>, tick: u32) -> f32 {
let x = vec2<i32>(max(0, min(i32(ctx.size.x) - 1, pos.x)), max(0, min(i32(ctx.size.x) - 1, pos.x + 1)));
let y = vec2<i32>(max(0, min(i32(ctx.size.y) - 1, pos.y)), max(0, min(i32(ctx.size.y) - 1, pos.y + 1)));

let s = vec4<f32>(
nearest_neighbor_sample(vec2<i32>(x.x, y.x), tick),
nearest_neighbor_sample(vec2<i32>(x.y, y.x), tick),
nearest_neighbor_sample(vec2<i32>(x.x, y.y), tick),
nearest_neighbor_sample(vec2<i32>(x.y, y.y), tick)
);

let f = fract((origin - ctx.pan) * ctx.zoom);
return mix(mix(s.x, s.y, f.x), mix(s.z, s.w, f.x), f.y);
}

fn sample(origin: vec2<f32>, pos: vec2<i32>) -> f32 {
if (ctx.flags & 0x04) != 0 {
return bilinear_sample(origin, pos, ctx.tick);
} else {
return nearest_neighbor_sample(pos, ctx.tick);
}
}

@fragment
fn frag(in: VertexOutput) -> @location(0) vec4<f32> {
let pos = vec2<i32>((in.position.xy - ctx.pan) * ctx.zoom );
Expand All @@ -64,7 +118,7 @@ fn frag(in: VertexOutput) -> @location(0) vec4<f32> {
}

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

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

let val = states[index(u32(pos.x), u32(pos.y), ctx.tick % 3)] * ctx.gain;
let val = sample(in.position.xy, pos) * 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
3 changes: 2 additions & 1 deletion src/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ bitflags! {
pub struct SimulationFlags: u32 {
const REFLECTIVE_BOUNDARY = 1 << 0;
const ENERGY_VIEW = 1 << 1;
const BILINIER_SAMPLING = 1 << 2;
}
}

Expand Down Expand Up @@ -169,7 +170,7 @@ impl Simulation {
entry_point: "main",
});

let mut flags = SimulationFlags::empty();
let mut flags = SimulationFlags::BILINIER_SAMPLING();
if config.reflective_boundary {
flags |= SimulationFlags::REFLECTIVE_BOUNDARY;
}
Expand Down
6 changes: 6 additions & 0 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ impl Gui {
&mut simulation.flags,
SimulationFlags::ENERGY_VIEW,
);
bit_checkbox(
ui,
"Smooth Sampling",
&mut simulation.flags,
SimulationFlags::BILINIER_SAMPLING,
);

ui.separator();

Expand Down

0 comments on commit 9bf63e1

Please sign in to comment.