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,
|
exp: f32,
|
||||||
level: i32,
|
level: i32,
|
||||||
mult: FixedDec,
|
mult: FixedDec,
|
||||||
|
inv_mult: FixedDec,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -41,12 +42,16 @@ impl Zoom {
|
|||||||
Self {
|
Self {
|
||||||
exp: scale,
|
exp: scale,
|
||||||
level,
|
level,
|
||||||
mult: mult(level, scale),
|
mult: zoom_mult(level, scale),
|
||||||
|
inv_mult: inv_zoom_mult(level, scale),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn mult(&self) -> &FixedDec {
|
pub fn mult(&self) -> &FixedDec {
|
||||||
&self.mult
|
&self.mult
|
||||||
}
|
}
|
||||||
|
pub fn inv_mult(&self) -> &FixedDec {
|
||||||
|
&self.inv_mult
|
||||||
|
}
|
||||||
pub fn level(&self) -> i32 {
|
pub fn level(&self) -> i32 {
|
||||||
self.level
|
self.level
|
||||||
}
|
}
|
||||||
@@ -67,10 +72,15 @@ impl AddAssign<f32> for Zoom {
|
|||||||
self.exp -= 1.0;
|
self.exp -= 1.0;
|
||||||
self.level -= 1;
|
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())
|
(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) {
|
if input.pressed(K::KeyD) {
|
||||||
camera.pos.x += &speed;
|
camera.pos.x += &speed;
|
||||||
}
|
}
|
||||||
|
if input.pressed(K::KeyQ) {
|
||||||
|
self.snapshot = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ pub struct Client<'a> {
|
|||||||
exit: bool,
|
exit: bool,
|
||||||
prev_update: Instant,
|
prev_update: Instant,
|
||||||
renderer: Renderer<'a>,
|
renderer: Renderer<'a>,
|
||||||
|
snapshot: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client<'_> {
|
impl Client<'_> {
|
||||||
@@ -40,6 +41,7 @@ impl Client<'_> {
|
|||||||
exit: false,
|
exit: false,
|
||||||
prev_update: Instant::now(),
|
prev_update: Instant::now(),
|
||||||
renderer,
|
renderer,
|
||||||
|
snapshot: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +62,8 @@ impl Client<'_> {
|
|||||||
WindowEvent::CloseRequested => self.exit = true,
|
WindowEvent::CloseRequested => self.exit = true,
|
||||||
WindowEvent::Resized(size) => self.renderer.resize(size),
|
WindowEvent::Resized(size) => self.renderer.resize(size),
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
self.renderer.render(&self.camera);
|
self.renderer.render(&self.camera, self.snapshot);
|
||||||
|
self.snapshot = false;
|
||||||
self.window.request_redraw();
|
self.window.request_redraw();
|
||||||
}
|
}
|
||||||
WindowEvent::CursorLeft { .. } => {
|
WindowEvent::CursorLeft { .. } => {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ impl Layout {
|
|||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
dimension: wgpu::TextureDimension::D2,
|
dimension: wgpu::TextureDimension::D2,
|
||||||
format: wgpu::TextureFormat::Rgba8Unorm,
|
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: &[],
|
view_formats: &[],
|
||||||
};
|
};
|
||||||
let output = Texture::init(
|
let output = Texture::init(
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ impl ComputePipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len != self.old_len {
|
if len != self.old_len {
|
||||||
|
println!("len: {}", len);
|
||||||
self.old_len = len;
|
self.old_len = len;
|
||||||
self.pipeline = self.pipeline(device, &Self::shader(device, len));
|
self.pipeline = self.pipeline(device, &Self::shader(device, len));
|
||||||
self.work.set(work_vec(size.x, size.y, 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;
|
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.compute_pipeline.update(
|
||||||
&self.device,
|
&self.device,
|
||||||
@@ -136,12 +135,14 @@ impl Renderer<'_> {
|
|||||||
&self.size,
|
&self.size,
|
||||||
self.len,
|
self.len,
|
||||||
);
|
);
|
||||||
self.chunk_view.update(camera, &self.size);
|
self.chunk_view.update(camera, &self.size, snapshot);
|
||||||
self.render_pipeline.update(
|
self.render_pipeline.update(
|
||||||
&self.device,
|
&self.device,
|
||||||
&mut self.encoder,
|
&mut self.encoder,
|
||||||
&mut self.staging_belt,
|
&mut self.staging_belt,
|
||||||
&self.chunk_view.render,
|
&self.chunk_view.render,
|
||||||
|
&self.compute_pipeline.output,
|
||||||
|
snapshot,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut encoder = std::mem::replace(&mut self.encoder, Self::create_encoder(&self.device));
|
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 stretch: Vector2<f32>,
|
||||||
pub pos: Vector2<f32>,
|
pub pos: Vector2<f32>,
|
||||||
pub rendered_chunks: Vector2<u32>,
|
pub rendered_chunks: Vector2<u32>,
|
||||||
|
pub snapshot: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl bytemuck::Pod for WindowView {}
|
unsafe impl bytemuck::Pod for WindowView {}
|
||||||
unsafe impl bytemuck::Zeroable for WindowView {}
|
unsafe impl bytemuck::Zeroable for WindowView {}
|
||||||
|
|
||||||
impl 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 visible_chunks = (size * 2 / CHUNK_WIDTH).add_scalar(1);
|
||||||
let rendered_chunks = Vector2::new(
|
let rendered_chunks = Vector2::new(
|
||||||
visible_chunks.x.next_power_of_two(),
|
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 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 {
|
Self {
|
||||||
pos,
|
pos,
|
||||||
stretch,
|
stretch,
|
||||||
rendered_chunks,
|
rendered_chunks,
|
||||||
|
snapshot: snapshot as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ pub struct Layout {
|
|||||||
format: wgpu::TextureFormat,
|
format: wgpu::TextureFormat,
|
||||||
pub view: Storage,
|
pub view: Storage,
|
||||||
pub chunks: ResizableTexture,
|
pub chunks: ResizableTexture,
|
||||||
|
pub snapshot: Texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const LABEL: &str = file!();
|
pub const LABEL: &str = file!();
|
||||||
@@ -46,6 +47,29 @@ impl Layout {
|
|||||||
};
|
};
|
||||||
let chunks = ResizableTexture::new(device, texture_desc, view_desc);
|
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 =
|
let render_bind_layout =
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
entries: &[
|
entries: &[
|
||||||
@@ -80,6 +104,22 @@ impl Layout {
|
|||||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||||
count: None,
|
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),
|
label: Some(LABEL),
|
||||||
});
|
});
|
||||||
@@ -97,6 +137,7 @@ impl Layout {
|
|||||||
render_bind_layout,
|
render_bind_layout,
|
||||||
render_pipeline_layout,
|
render_pipeline_layout,
|
||||||
format: config.format,
|
format: config.format,
|
||||||
|
snapshot,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +149,8 @@ impl Layout {
|
|||||||
self.chunks.view_entry(1),
|
self.chunks.view_entry(1),
|
||||||
input.view_bind_group_entry(2),
|
input.view_bind_group_entry(2),
|
||||||
input.sampler_bind_group_entry(3),
|
input.sampler_bind_group_entry(3),
|
||||||
|
self.snapshot.view_bind_group_entry(4),
|
||||||
|
self.snapshot.sampler_bind_group_entry(5),
|
||||||
],
|
],
|
||||||
label: Some(LABEL),
|
label: Some(LABEL),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -39,7 +39,31 @@ impl RenderPipeline {
|
|||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
belt: &mut wgpu::util::StagingBelt,
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
view: &WindowView,
|
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
|
self.view
|
||||||
.update(device, encoder, belt, bytemuck::bytes_of(view));
|
.update(device, encoder, belt, bytemuck::bytes_of(view));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ struct View {
|
|||||||
stretch: vec2<f32>,
|
stretch: vec2<f32>,
|
||||||
pos: vec2<f32>,
|
pos: vec2<f32>,
|
||||||
rendered_chunks: vec2<u32>,
|
rendered_chunks: vec2<u32>,
|
||||||
|
snapshot: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
@@ -13,11 +14,16 @@ var chunks: texture_2d_array<u32>;
|
|||||||
var tex: texture_2d<f32>;
|
var tex: texture_2d<f32>;
|
||||||
@group(0) @binding(3)
|
@group(0) @binding(3)
|
||||||
var sam: sampler;
|
var sam: sampler;
|
||||||
|
@group(0) @binding(4)
|
||||||
|
var ss_t: texture_2d<f32>;
|
||||||
|
@group(0) @binding(5)
|
||||||
|
var ss_s: sampler;
|
||||||
|
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
@builtin(position) vertex_pos: vec4<f32>,
|
@builtin(position) vertex_pos: vec4<f32>,
|
||||||
@location(0) world_pos: vec2<f32>,
|
@location(0) world_pos: vec2<f32>,
|
||||||
@location(1) tex_pos: vec2<f32>,
|
@location(1) tex_pos: vec2<f32>,
|
||||||
|
@location(2) ss_pos: vec2<f32>,
|
||||||
};
|
};
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
@@ -43,6 +49,9 @@ fn vs_main(
|
|||||||
);
|
);
|
||||||
out.tex_pos = pos2;
|
out.tex_pos = pos2;
|
||||||
out.tex_pos.y = 1.0 - out.tex_pos.y;
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -61,7 +70,14 @@ fn fs_main(
|
|||||||
// );
|
// );
|
||||||
// let cposf = vec2<f32>(cposu);
|
// let cposf = vec2<f32>(cposu);
|
||||||
// return vec4(cposf / rcf, 0.0, 1.0);
|
// 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 {
|
fn div_euclid(x: i32, y: i32) -> i32 {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub struct ChunkView {
|
|||||||
pub render: WindowView,
|
pub render: WindowView,
|
||||||
pub chunk_queue: HashSet<Vector2<FixedDec>>,
|
pub chunk_queue: HashSet<Vector2<FixedDec>>,
|
||||||
pub visible_chunks: HashSet<Vector2<FixedDec>>,
|
pub visible_chunks: HashSet<Vector2<FixedDec>>,
|
||||||
|
pub snapshot: Option<Camera>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChunkView {
|
impl ChunkView {
|
||||||
@@ -18,8 +19,11 @@ impl ChunkView {
|
|||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, camera: &Camera, size: &Vector2<u32>) {
|
pub fn update(&mut self, camera: &Camera, size: &Vector2<u32>, snapshot: bool) {
|
||||||
let render = WindowView::from_camera_size(camera, size);
|
if snapshot {
|
||||||
|
self.snapshot = Some(camera.clone());
|
||||||
|
}
|
||||||
|
let render = WindowView::from_camera_size(camera, self.snapshot.as_ref(), size, snapshot);
|
||||||
|
|
||||||
if self.render == render {
|
if self.render == render {
|
||||||
return;
|
return;
|
||||||
@@ -63,4 +67,3 @@ impl ChunkView {
|
|||||||
self.visible_chunks = visible;
|
self.visible_chunks = visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user