Consideration of aspect ratio

This commit is contained in:
Verox001 2025-05-04 13:48:21 +02:00
parent e709e2dd3f
commit 2f7f521051
2 changed files with 66 additions and 5 deletions

View File

@ -22,6 +22,12 @@ pub async fn run() {
let _ = event_loop.run_app(&mut window_state); let _ = event_loop.run_app(&mut window_state);
} }
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct Globals {
aspect_ratio: f32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Shape { enum Shape {
Polygon, Polygon,
@ -64,7 +70,7 @@ struct InstanceRaw {
impl InstanceRaw { impl InstanceRaw {
fn desc() -> wgpu::VertexBufferLayout<'static> { fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout { wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<InstanceRaw>() as wgpu::BufferAddress, array_stride: size_of::<InstanceRaw>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Instance, step_mode: wgpu::VertexStepMode::Instance,
attributes: &[ attributes: &[
wgpu::VertexAttribute { offset: 0, shader_location: 5, format: wgpu::VertexFormat::Float32x4 }, wgpu::VertexAttribute { offset: 0, shader_location: 5, format: wgpu::VertexFormat::Float32x4 },
@ -183,6 +189,8 @@ struct State<'a> {
instance_buffer: wgpu::Buffer, instance_buffer: wgpu::Buffer,
geometries: HashMap<Shape, Geometry>, geometries: HashMap<Shape, Geometry>,
global_bind_group: wgpu::BindGroup,
global_buffer: wgpu::Buffer,
simulator: Arc<RwLock<Simulator>>, simulator: Arc<RwLock<Simulator>>,
} }
@ -199,7 +207,37 @@ impl<'a> State<'a> {
let config = Self::create_surface_config(size, surface_caps); let config = Self::create_surface_config(size, surface_caps);
surface.configure(&device, &config); surface.configure(&device, &config);
let render_pipeline = Self::create_render_pipeline(&device, &config); let globals = Globals {
aspect_ratio: config.width as f32 / config.height as f32,
};
let global_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Global Uniform Buffer"),
contents: bytemuck::cast_slice(&[globals]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let global_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("Global Bind Group Layout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
});
let global_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &global_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: global_buffer.as_entire_binding(),
}],
label: Some("Global Bind Group"),
});
let render_pipeline = Self::create_render_pipeline(&device, &config, &global_bind_group_layout);
let mut geometries = HashMap::new(); let mut geometries = HashMap::new();
let polygon_vertices = vec![ let polygon_vertices = vec![
@ -307,6 +345,9 @@ impl<'a> State<'a> {
size, size,
window: window_arc, window: window_arc,
global_bind_group,
global_buffer,
render_pipeline, render_pipeline,
geometries, geometries,
@ -342,7 +383,7 @@ impl<'a> State<'a> {
self.instances = updated_instances; self.instances = updated_instances;
} }
fn create_render_pipeline(device: &Device, config: &wgpu::SurfaceConfiguration) -> wgpu::RenderPipeline { fn create_render_pipeline(device: &Device, config: &wgpu::SurfaceConfiguration, global_bind_group_layout: &wgpu::BindGroupLayout) -> wgpu::RenderPipeline {
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Shader"), label: Some("Shader"),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
@ -351,7 +392,7 @@ impl<'a> State<'a> {
let render_pipeline_layout = let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"), label: Some("Render Pipeline Layout"),
bind_group_layouts: &[], bind_group_layouts: &[&global_bind_group_layout],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
@ -451,6 +492,11 @@ impl<'a> State<'a> {
self.surface.configure(&self.device, &self.config); self.surface.configure(&self.device, &self.config);
let new_globals = Globals {
aspect_ratio: self.config.width as f32 / self.config.height as f32,
};
self.queue.write_buffer(&self.global_buffer, 0, bytemuck::cast_slice(&[new_globals]));
println!("Resized to {:?} from state!", new_size); println!("Resized to {:?} from state!", new_size);
} }
@ -484,6 +530,7 @@ impl<'a> State<'a> {
}); });
render_pass.set_pipeline(&self.render_pipeline); render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, &self.global_bind_group, &[]);
for shape in [Shape::Polygon, Shape::Circle] { for shape in [Shape::Polygon, Shape::Circle] {
let geometry = &self.geometries[&shape]; let geometry = &self.geometries[&shape];

View File

@ -16,6 +16,13 @@ struct VSOutput {
@location(0) color: vec3<f32>, @location(0) color: vec3<f32>,
}; };
struct Globals {
aspect_ratio: f32,
}
@group(0) @binding(0)
var<uniform> globals: Globals;
@vertex @vertex
fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VSOutput { fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VSOutput {
var out: VSOutput; var out: VSOutput;
@ -25,7 +32,14 @@ fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VSOutput {
instance.model_row2, instance.model_row2,
instance.model_row3 instance.model_row3
); );
out.position = model * vec4<f32>(vertex.position, 1.0);
let projection = mat4x4<f32>(
vec4<f32>(1.0 / globals.aspect_ratio, 0.0, 0.0, 0.0),
vec4<f32>(0.0, 1.0, 0.0, 0.0),
vec4<f32>(0.0, 0.0, 1.0, 0.0),
vec4<f32>(0.0, 0.0, 0.0, 1.0),
);
out.position = projection * model * vec4<f32>(vertex.position, 1.0);
out.color = instance.color; out.color = instance.color;
return out; return out;
} }