added snapshot button (q) so you can actually see where you're moving
This commit is contained in:
@@ -8,6 +8,7 @@ pub struct Zoom {
|
||||
exp: f32,
|
||||
level: i32,
|
||||
mult: FixedDec,
|
||||
inv_mult: FixedDec,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -41,12 +42,16 @@ impl Zoom {
|
||||
Self {
|
||||
exp: scale,
|
||||
level,
|
||||
mult: mult(level, scale),
|
||||
mult: zoom_mult(level, scale),
|
||||
inv_mult: inv_zoom_mult(level, scale),
|
||||
}
|
||||
}
|
||||
pub fn mult(&self) -> &FixedDec {
|
||||
&self.mult
|
||||
}
|
||||
pub fn inv_mult(&self) -> &FixedDec {
|
||||
&self.inv_mult
|
||||
}
|
||||
pub fn level(&self) -> i32 {
|
||||
self.level
|
||||
}
|
||||
@@ -67,10 +72,15 @@ impl AddAssign<f32> for Zoom {
|
||||
self.exp -= 1.0;
|
||||
self.level -= 1;
|
||||
}
|
||||
self.mult = mult(self.level, self.exp);
|
||||
self.mult = zoom_mult(self.level, self.exp);
|
||||
self.inv_mult = inv_zoom_mult(self.level, self.exp);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mult(level: i32, exp: f32) -> FixedDec {
|
||||
pub fn zoom_mult(level: i32, exp: f32) -> FixedDec {
|
||||
(FixedDec::from(1) >> level) * FixedDec::from(exp.exp2())
|
||||
}
|
||||
|
||||
pub fn inv_zoom_mult(level: i32, exp: f32) -> FixedDec {
|
||||
(FixedDec::from(1) << level) * FixedDec::from(1.0 / exp.exp2())
|
||||
}
|
||||
|
||||
@@ -28,5 +28,8 @@ impl Client<'_> {
|
||||
if input.pressed(K::KeyD) {
|
||||
camera.pos.x += &speed;
|
||||
}
|
||||
if input.pressed(K::KeyQ) {
|
||||
self.snapshot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ pub struct Client<'a> {
|
||||
exit: bool,
|
||||
prev_update: Instant,
|
||||
renderer: Renderer<'a>,
|
||||
snapshot: bool,
|
||||
}
|
||||
|
||||
impl Client<'_> {
|
||||
@@ -40,6 +41,7 @@ impl Client<'_> {
|
||||
exit: false,
|
||||
prev_update: Instant::now(),
|
||||
renderer,
|
||||
snapshot: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +62,8 @@ impl Client<'_> {
|
||||
WindowEvent::CloseRequested => self.exit = true,
|
||||
WindowEvent::Resized(size) => self.renderer.resize(size),
|
||||
WindowEvent::RedrawRequested => {
|
||||
self.renderer.render(&self.camera);
|
||||
self.renderer.render(&self.camera, self.snapshot);
|
||||
self.snapshot = false;
|
||||
self.window.request_redraw();
|
||||
}
|
||||
WindowEvent::CursorLeft { .. } => {
|
||||
|
||||
@@ -37,7 +37,7 @@ impl Layout {
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8Unorm,
|
||||
usage: wgpu::TextureUsages::STORAGE_BINDING | wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
usage: wgpu::TextureUsages::STORAGE_BINDING | wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[],
|
||||
};
|
||||
let output = Texture::init(
|
||||
|
||||
@@ -46,6 +46,7 @@ impl ComputePipeline {
|
||||
}
|
||||
}
|
||||
if len != self.old_len {
|
||||
println!("len: {}", len);
|
||||
self.old_len = len;
|
||||
self.pipeline = self.pipeline(device, &Self::shader(device, len));
|
||||
self.work.set(work_vec(size.x, size.y, len));
|
||||
|
||||
@@ -121,12 +121,11 @@ impl Renderer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&mut self, camera: &Camera) {
|
||||
pub fn render(&mut self, camera: &Camera, snapshot: bool) {
|
||||
|
||||
// this comes from the fact that I want (0, 2) and (30, 4)
|
||||
// probably a much better formula, or better yet let the user select
|
||||
self.len = (camera.zoom.level() as f32 / 15.0 + 2.0).round() as usize;
|
||||
println!("{}", self.len);
|
||||
// let new = (camera.zoom.level() as f32 / 15.0 + 2.0).round() as usize;
|
||||
// println!("{}", new);
|
||||
|
||||
self.compute_pipeline.update(
|
||||
&self.device,
|
||||
@@ -136,12 +135,14 @@ impl Renderer<'_> {
|
||||
&self.size,
|
||||
self.len,
|
||||
);
|
||||
self.chunk_view.update(camera, &self.size);
|
||||
self.chunk_view.update(camera, &self.size, snapshot);
|
||||
self.render_pipeline.update(
|
||||
&self.device,
|
||||
&mut self.encoder,
|
||||
&mut self.staging_belt,
|
||||
&self.chunk_view.render,
|
||||
&self.compute_pipeline.output,
|
||||
snapshot,
|
||||
);
|
||||
|
||||
let mut encoder = std::mem::replace(&mut self.encoder, Self::create_encoder(&self.device));
|
||||
|
||||
@@ -10,13 +10,20 @@ pub struct WindowView {
|
||||
pub stretch: Vector2<f32>,
|
||||
pub pos: Vector2<f32>,
|
||||
pub rendered_chunks: Vector2<u32>,
|
||||
pub snapshot: u32,
|
||||
}
|
||||
|
||||
unsafe impl bytemuck::Pod for WindowView {}
|
||||
unsafe impl bytemuck::Zeroable for WindowView {}
|
||||
|
||||
impl WindowView {
|
||||
pub fn from_camera_size(camera: &Camera, size: &Vector2<u32>) -> Self {
|
||||
pub fn from_camera_size(
|
||||
camera: &Camera,
|
||||
ss_cam: Option<&Camera>,
|
||||
size: &Vector2<u32>,
|
||||
snapshot: bool,
|
||||
) -> Self {
|
||||
// TODO: most of this is useless and just preparation for chunked textures if I add them
|
||||
let visible_chunks = (size * 2 / CHUNK_WIDTH).add_scalar(1);
|
||||
let rendered_chunks = Vector2::new(
|
||||
visible_chunks.x.next_power_of_two(),
|
||||
@@ -36,10 +43,21 @@ impl WindowView {
|
||||
|
||||
let stretch = size.cast::<f32>() * camera.zoom.rel_zoom() / (CHUNK_WIDTH as f32);
|
||||
|
||||
let (pos, stretch) = if let Some(ss_cam) = ss_cam {
|
||||
let s = camera.zoom.mult() * ss_cam.zoom.inv_mult();
|
||||
(
|
||||
((&camera.pos - &ss_cam.pos) * ss_cam.zoom.inv_mult().clone()).map(f32::from) * 2.0,
|
||||
Vector2::from_element(f32::from(s)),
|
||||
)
|
||||
} else {
|
||||
(Vector2::default(), Vector2::default())
|
||||
};
|
||||
|
||||
Self {
|
||||
pos,
|
||||
stretch,
|
||||
rendered_chunks,
|
||||
snapshot: snapshot as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ pub struct Layout {
|
||||
format: wgpu::TextureFormat,
|
||||
pub view: Storage,
|
||||
pub chunks: ResizableTexture,
|
||||
pub snapshot: Texture,
|
||||
}
|
||||
|
||||
pub const LABEL: &str = file!();
|
||||
@@ -46,6 +47,29 @@ impl Layout {
|
||||
};
|
||||
let chunks = ResizableTexture::new(device, texture_desc, view_desc);
|
||||
|
||||
let desc = wgpu::TextureDescriptor {
|
||||
label: Some("compute output"),
|
||||
size: wgpu::Extent3d {
|
||||
width: config.width,
|
||||
height: config.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8Unorm,
|
||||
usage: wgpu::TextureUsages::STORAGE_BINDING
|
||||
| wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::COPY_DST,
|
||||
view_formats: &[],
|
||||
};
|
||||
let snapshot = Texture::init(
|
||||
device,
|
||||
desc,
|
||||
wgpu::TextureViewDescriptor::default(),
|
||||
wgpu::SamplerDescriptor::default(),
|
||||
);
|
||||
|
||||
let render_bind_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
@@ -80,6 +104,22 @@ impl Layout {
|
||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 4,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT | wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
multisampled: false,
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 5,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some(LABEL),
|
||||
});
|
||||
@@ -97,6 +137,7 @@ impl Layout {
|
||||
render_bind_layout,
|
||||
render_pipeline_layout,
|
||||
format: config.format,
|
||||
snapshot,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +149,8 @@ impl Layout {
|
||||
self.chunks.view_entry(1),
|
||||
input.view_bind_group_entry(2),
|
||||
input.sampler_bind_group_entry(3),
|
||||
self.snapshot.view_bind_group_entry(4),
|
||||
self.snapshot.sampler_bind_group_entry(5),
|
||||
],
|
||||
label: Some(LABEL),
|
||||
})
|
||||
|
||||
@@ -39,7 +39,31 @@ impl RenderPipeline {
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
belt: &mut wgpu::util::StagingBelt,
|
||||
view: &WindowView,
|
||||
input: &Texture,
|
||||
snapshot: bool,
|
||||
) {
|
||||
if snapshot {
|
||||
let size = input.texture.size();
|
||||
if self.snapshot.texture.size() != size {
|
||||
self.snapshot.resize(device, size);
|
||||
}
|
||||
encoder.copy_texture_to_texture(
|
||||
wgpu::TexelCopyTextureInfoBase {
|
||||
texture: &input.texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
},
|
||||
wgpu::TexelCopyTextureInfoBase {
|
||||
texture: &self.snapshot.texture,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
},
|
||||
size,
|
||||
);
|
||||
self.bind_group = self.bind_group(device, input);
|
||||
}
|
||||
self.view
|
||||
.update(device, encoder, belt, bytemuck::bytes_of(view));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ struct View {
|
||||
stretch: vec2<f32>,
|
||||
pos: vec2<f32>,
|
||||
rendered_chunks: vec2<u32>,
|
||||
snapshot: u32,
|
||||
}
|
||||
|
||||
@group(0) @binding(0)
|
||||
@@ -13,11 +14,16 @@ var chunks: texture_2d_array<u32>;
|
||||
var tex: texture_2d<f32>;
|
||||
@group(0) @binding(3)
|
||||
var sam: sampler;
|
||||
@group(0) @binding(4)
|
||||
var ss_t: texture_2d<f32>;
|
||||
@group(0) @binding(5)
|
||||
var ss_s: sampler;
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) vertex_pos: vec4<f32>,
|
||||
@location(0) world_pos: vec2<f32>,
|
||||
@location(1) tex_pos: vec2<f32>,
|
||||
@location(2) ss_pos: vec2<f32>,
|
||||
};
|
||||
|
||||
@vertex
|
||||
@@ -43,6 +49,9 @@ fn vs_main(
|
||||
);
|
||||
out.tex_pos = pos2;
|
||||
out.tex_pos.y = 1.0 - out.tex_pos.y;
|
||||
let pos3 = vec2(pos.x, -pos.y);
|
||||
out.ss_pos = pos3 * view.stretch + view.pos;
|
||||
out.ss_pos = (out.ss_pos + 1.0) / 2.0;
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -61,7 +70,14 @@ fn fs_main(
|
||||
// );
|
||||
// let cposf = vec2<f32>(cposu);
|
||||
// return vec4(cposf / rcf, 0.0, 1.0);
|
||||
return textureSample(tex, sam, in.tex_pos);
|
||||
let cur = textureSample(tex, sam, in.tex_pos);
|
||||
let snp_bounds = all(in.ss_pos >= vec2(0.0)) && all(in.ss_pos <= vec2(1.0));
|
||||
if all(cur.rgb == vec3(0.0)) && snp_bounds {
|
||||
let snp = textureSample(ss_t, ss_s, in.ss_pos).rgb;
|
||||
return vec4(snp * 0.3, 1.0);
|
||||
} else {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
fn div_euclid(x: i32, y: i32) -> i32 {
|
||||
|
||||
@@ -11,6 +11,7 @@ pub struct ChunkView {
|
||||
pub render: WindowView,
|
||||
pub chunk_queue: HashSet<Vector2<FixedDec>>,
|
||||
pub visible_chunks: HashSet<Vector2<FixedDec>>,
|
||||
pub snapshot: Option<Camera>,
|
||||
}
|
||||
|
||||
impl ChunkView {
|
||||
@@ -18,8 +19,11 @@ impl ChunkView {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn update(&mut self, camera: &Camera, size: &Vector2<u32>) {
|
||||
let render = WindowView::from_camera_size(camera, size);
|
||||
pub fn update(&mut self, camera: &Camera, size: &Vector2<u32>, snapshot: bool) {
|
||||
if snapshot {
|
||||
self.snapshot = Some(camera.clone());
|
||||
}
|
||||
let render = WindowView::from_camera_size(camera, self.snapshot.as_ref(), size, snapshot);
|
||||
|
||||
if self.render == render {
|
||||
return;
|
||||
@@ -63,4 +67,3 @@ impl ChunkView {
|
||||
self.visible_chunks = visible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user