fix resizing snapshot stretch bug
This commit is contained in:
@@ -35,7 +35,6 @@ Snapshots will copy the current texture and let you view it as the new one gener
|
|||||||
## Known Bugs
|
## Known Bugs
|
||||||
|
|
||||||
- It crashes when you zoom out too far (relative to the starting view), because the renderer is currently not designed for zooming out, only in. This does not matter at all for fractals like the mandelbrot set where the detail is confined in a small circle (radius 2). An easy fix would be to cap the zoom, but I'm more interested in having the precision expand in the opposite direction as well for equations that require it (no clue if those exist).
|
- It crashes when you zoom out too far (relative to the starting view), because the renderer is currently not designed for zooming out, only in. This does not matter at all for fractals like the mandelbrot set where the detail is confined in a small circle (radius 2). An easy fix would be to cap the zoom, but I'm more interested in having the precision expand in the opposite direction as well for equations that require it (no clue if those exist).
|
||||||
- The snapshot texture gets stretched in some way when you resize the window. Don't know exactly why because that code was trial and errored (just wanted it to work), but I think I know where the fix would be and it shouldn't be complicated. Not a critical issue at all though, it only affects the previously taken snapshot.
|
|
||||||
|
|
||||||
## TODO List
|
## TODO List
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use nalgebra::Vector2;
|
use nalgebra::Vector2;
|
||||||
use std::ops::{AddAssign, Neg};
|
use std::ops::AddAssign;
|
||||||
|
|
||||||
use crate::util::FixedDec;
|
use crate::util::FixedDec;
|
||||||
|
|
||||||
@@ -88,9 +88,6 @@ impl Zoom {
|
|||||||
pub fn level(&self) -> i32 {
|
pub fn level(&self) -> i32 {
|
||||||
self.level
|
self.level
|
||||||
}
|
}
|
||||||
pub fn rel_zoom(&self) -> f32 {
|
|
||||||
self.exp.exp2()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddAssign<f32> for Zoom {
|
impl AddAssign<f32> for Zoom {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use super::{
|
|||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
bind_layout: wgpu::BindGroupLayout,
|
bind_layout: wgpu::BindGroupLayout,
|
||||||
pipeline_layout: wgpu::PipelineLayout,
|
pipeline_layout: wgpu::PipelineLayout,
|
||||||
format: wgpu::TextureFormat,
|
|
||||||
pub output: Texture,
|
pub output: Texture,
|
||||||
pub view: Storage,
|
pub view: Storage,
|
||||||
pub work: ArrayBuffer<u32>,
|
pub work: ArrayBuffer<u32>,
|
||||||
@@ -81,7 +80,6 @@ impl Layout {
|
|||||||
bind_layout,
|
bind_layout,
|
||||||
pipeline_layout,
|
pipeline_layout,
|
||||||
work,
|
work,
|
||||||
format: config.format,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ impl Renderer<'_> {
|
|||||||
camera,
|
camera,
|
||||||
self.len,
|
self.len,
|
||||||
);
|
);
|
||||||
self.chunk_view.update(camera, &self.size, snapshot);
|
self.chunk_view.update(camera, snapshot);
|
||||||
self.render_pipeline.update(
|
self.render_pipeline.update(
|
||||||
&self.device,
|
&self.device,
|
||||||
&mut self.encoder,
|
&mut self.encoder,
|
||||||
@@ -168,7 +168,7 @@ impl Renderer<'_> {
|
|||||||
self.compute_pipeline
|
self.compute_pipeline
|
||||||
.resize(&self.device, self.size, self.len);
|
.resize(&self.device, self.size, self.len);
|
||||||
self.render_pipeline
|
self.render_pipeline
|
||||||
.resize(&self.device, self.size, &self.compute_pipeline.output);
|
.resize(&self.device, &self.compute_pipeline.output);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_encoder(device: &wgpu::Device) -> wgpu::CommandEncoder {
|
fn create_encoder(device: &wgpu::Device) -> wgpu::CommandEncoder {
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use nalgebra::Vector2;
|
use nalgebra::Vector2;
|
||||||
|
|
||||||
use super::{Camera, CHUNK_WIDTH};
|
use super::Camera;
|
||||||
|
|
||||||
#[repr(C, align(8))]
|
#[repr(C, align(8))]
|
||||||
#[derive(Clone, Copy, Default, PartialEq)]
|
#[derive(Clone, Copy, Default, PartialEq)]
|
||||||
pub struct WindowView {
|
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 snapshot: u32,
|
pub snapshot: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,40 +14,16 @@ 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(
|
pub fn from_camera(camera: &Camera, ss_cam: Option<&Camera>, snapshot: bool) -> Self {
|
||||||
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(),
|
|
||||||
visible_chunks.y.next_power_of_two(),
|
|
||||||
);
|
|
||||||
// let adj_zoom = camera.zoom.level() - CHUNK_POW as i32;
|
|
||||||
// let pos = camera.pos.zip_map(&rendered_chunks, |pos, rc| {
|
|
||||||
// let p = (pos << adj_zoom).with_lens(1, 1);
|
|
||||||
// let (pw, pd) = p.split_whole_dec();
|
|
||||||
// let mut chunk = (pw.parts().first().unwrap_or(&0) & (rc - 1)) as f32;
|
|
||||||
// if pw.is_neg() {
|
|
||||||
// chunk = rc as f32 - chunk;
|
|
||||||
// }
|
|
||||||
// let dec = f32::from(pd);
|
|
||||||
// chunk + dec
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// let stretch = size.cast::<f32>() * camera.zoom.rel_zoom() / (CHUNK_WIDTH as f32);
|
|
||||||
|
|
||||||
let (pos, stretch) = if let Some(ss_cam) = ss_cam {
|
let (pos, stretch) = if let Some(ss_cam) = ss_cam {
|
||||||
let aspect = camera.inv_stretch() * 2.0;
|
let s_mult = camera.stretch().component_div(&ss_cam.stretch());
|
||||||
let s = camera.zoom.mult() * ss_cam.zoom.inv_mult();
|
let aspect = camera.inv_stretch().component_mul(&s_mult) * 2.0;
|
||||||
|
let s = s_mult * f32::from(camera.zoom.mult() * ss_cam.zoom.inv_mult());
|
||||||
(
|
(
|
||||||
((&camera.pos - &ss_cam.pos) * ss_cam.zoom.inv_mult().clone())
|
((&camera.pos - &ss_cam.pos) * ss_cam.zoom.inv_mult().clone())
|
||||||
.map(f32::from)
|
.map(f32::from)
|
||||||
.component_mul(&aspect),
|
.component_mul(&aspect),
|
||||||
Vector2::from_element(f32::from(s)),
|
s,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(Vector2::default(), Vector2::default())
|
(Vector2::default(), Vector2::default())
|
||||||
@@ -57,7 +32,6 @@ impl WindowView {
|
|||||||
Self {
|
Self {
|
||||||
pos,
|
pos,
|
||||||
stretch,
|
stretch,
|
||||||
rendered_chunks,
|
|
||||||
snapshot: snapshot as u32,
|
snapshot: snapshot as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use nalgebra::Vector2;
|
|
||||||
|
|
||||||
use crate::client::render::util::Texture;
|
use crate::client::render::util::Texture;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -22,7 +20,6 @@ impl Layout {
|
|||||||
pub fn init(
|
pub fn init(
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
config: &wgpu::SurfaceConfiguration,
|
config: &wgpu::SurfaceConfiguration,
|
||||||
input: &Texture,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let view = Storage::init_with(device, "view", bytemuck::bytes_of(&WindowView::default()));
|
let view = Storage::init_with(device, "view", bytemuck::bytes_of(&WindowView::default()));
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ pub struct RenderPipeline {
|
|||||||
layout: Layout,
|
layout: Layout,
|
||||||
pipeline: wgpu::RenderPipeline,
|
pipeline: wgpu::RenderPipeline,
|
||||||
bind_group: wgpu::BindGroup,
|
bind_group: wgpu::BindGroup,
|
||||||
size: Vector2<u32>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHADER: wgpu::ShaderModuleDescriptor<'_> = include_wgsl!("shader.wgsl");
|
const SHADER: wgpu::ShaderModuleDescriptor<'_> = include_wgsl!("shader.wgsl");
|
||||||
@@ -23,12 +22,11 @@ impl RenderPipeline {
|
|||||||
config: &wgpu::SurfaceConfiguration,
|
config: &wgpu::SurfaceConfiguration,
|
||||||
input: &Texture,
|
input: &Texture,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let layout = Layout::init(device, config, input);
|
let layout = Layout::init(device, config);
|
||||||
let shader = device.create_shader_module(SHADER);
|
let shader = device.create_shader_module(SHADER);
|
||||||
Self {
|
Self {
|
||||||
pipeline: layout.pipeline(device, &shader),
|
pipeline: layout.pipeline(device, &shader),
|
||||||
bind_group: layout.bind_group(device, input),
|
bind_group: layout.bind_group(device, input),
|
||||||
size: Vector2::zeros(),
|
|
||||||
layout,
|
layout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +90,7 @@ impl RenderPipeline {
|
|||||||
render_pass.draw(0..4, 0..1);
|
render_pass.draw(0..4, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, device: &wgpu::Device, size: Vector2<u32>, input: &Texture) {
|
pub fn resize(&mut self, device: &wgpu::Device, input: &Texture) {
|
||||||
self.bind_group = self.layout.bind_group(device, input);
|
self.bind_group = self.layout.bind_group(device, input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
struct View {
|
struct View {
|
||||||
stretch: vec2<f32>,
|
ss_stretch: vec2<f32>,
|
||||||
pos: vec2<f32>,
|
ss_pos: vec2<f32>,
|
||||||
rendered_chunks: vec2<u32>,
|
|
||||||
snapshot: u32,
|
snapshot: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,18 +31,15 @@ fn vs_main(
|
|||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
|
|
||||||
let pos = vec2<f32>(
|
let tpos = vec2<f32>(
|
||||||
f32(vi % 2u),
|
|
||||||
f32(1 - vi / 2u),
|
|
||||||
) * 2.0 - 1.0;
|
|
||||||
out.vertex_pos = vec4<f32>(pos.x, pos.y, 0.0, 1.0);
|
|
||||||
|
|
||||||
let pos2 = vec2<f32>(
|
|
||||||
f32(vi % 2u),
|
f32(vi % 2u),
|
||||||
f32(1 - vi / 2u),
|
f32(1 - vi / 2u),
|
||||||
);
|
);
|
||||||
out.tex_pos = pos2;
|
let vpos = tpos * 2.0 - 1.0;
|
||||||
out.ss_pos = pos * view.stretch + view.pos;
|
out.vertex_pos = vec4<f32>(vpos, 0.0, 1.0);
|
||||||
|
|
||||||
|
out.tex_pos = tpos;
|
||||||
|
out.ss_pos = vpos * view.ss_stretch + view.ss_pos;
|
||||||
out.ss_pos = (out.ss_pos + 1.0) / 2.0;
|
out.ss_pos = (out.ss_pos + 1.0) / 2.0;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@@ -63,13 +59,3 @@ fn fs_main(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn div_euclid(x: i32, y: i32) -> i32 {
|
|
||||||
if x < 0 {
|
|
||||||
return -((-x - 1) / y) - 1;
|
|
||||||
}
|
|
||||||
return x / y;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rem_euclid(x: i32, y: i32) -> i32 {
|
|
||||||
return x - div_euclid(x, y) * y;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
use nalgebra::Vector2;
|
|
||||||
|
|
||||||
use crate::client::camera::Camera;
|
use crate::client::camera::Camera;
|
||||||
|
|
||||||
use super::output::WindowView;
|
use super::output::WindowView;
|
||||||
|
|
||||||
|
// TODO: move this out; this is not needed rn
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ChunkView {
|
pub struct ChunkView {
|
||||||
pub render: WindowView,
|
pub render: WindowView,
|
||||||
@@ -17,11 +14,11 @@ impl ChunkView {
|
|||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, camera: &Camera, size: &Vector2<u32>, snapshot: bool) {
|
pub fn update(&mut self, camera: &Camera, snapshot: bool) {
|
||||||
if snapshot {
|
if snapshot {
|
||||||
self.snapshot = Some(camera.clone());
|
self.snapshot = Some(camera.clone());
|
||||||
}
|
}
|
||||||
let render = WindowView::from_camera_size(camera, self.snapshot.as_ref(), size, snapshot);
|
let render = WindowView::from_camera(camera, self.snapshot.as_ref(), snapshot);
|
||||||
|
|
||||||
if self.render == render {
|
if self.render == render {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user