From 5e3b97ed614239a942c4b817cb53d8b1724f7894 Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Fri, 22 Nov 2024 21:42:37 -0400 Subject: [PATCH] Load DEM BVH into texture --- src/app/dem_renderer.rs | 77 ++++++++++++++++++++++++++++++++++++++- src/app/dem_renderer.wgsl | 12 ++++-- src/app/raster/dem.rs | 2 +- src/app/raster/mod.rs | 2 +- 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/app/dem_renderer.rs b/src/app/dem_renderer.rs index 60962b7..2ce5c3c 100644 --- a/src/app/dem_renderer.rs +++ b/src/app/dem_renderer.rs @@ -1,4 +1,4 @@ -use super::raster::Dem; +use super::raster::{Dem, DemBvh}; use { bytemuck::{Pod, Zeroable}, std::{borrow::Cow, num::NonZero, rc::Rc}, @@ -70,6 +70,7 @@ impl Camera { struct UniformBufferContents { camera_matrix: [f32; 16], dem_texture_size: [u32; 2], + dembvh_texture_size: [u32; 2], } // This struct is 72 bytes but WGSL expects the buffer size to be be a multiple // of the alignment of the member with the largest alignment. The mat4x4 @@ -107,6 +108,12 @@ impl UniformBufferManager { .clone_from_slice(&dem_texture_size.to_array()); } + fn set_dembvh_texture_size(&mut self, dembvh_texture_size: glam::UVec2) { + self.cpu_buffer + .dembvh_texture_size + .clone_from_slice(&dembvh_texture_size.to_array()); + } + fn get_binding(&self) -> wgpu::BindingResource<'_> { wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &self.gpu_buffer, @@ -144,11 +151,14 @@ impl DemRenderer { let index_count = index_data.len(); let (dem_texture_view, dem_texture_size) = load_dem_texture(&source, device, queue); + let (dembvh_texture_view, dembvh_texture_size) = + create_dembvh_texture(&source, device, queue); let camera = Camera::new(surface_config.width as f32 / surface_config.height as f32); let mut uniforms = UniformBufferManager::new(device); uniforms.set_dem_texture_size(dem_texture_size); + uniforms.set_dembvh_texture_size(dembvh_texture_size); let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, @@ -173,6 +183,16 @@ impl DemRenderer { }, count: None, }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + sample_type: wgpu::TextureSampleType::Uint, + view_dimension: wgpu::TextureViewDimension::D2, + }, + count: None, + }, ], }); @@ -187,6 +207,10 @@ impl DemRenderer { binding: 1, resource: wgpu::BindingResource::TextureView(&dem_texture_view), }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(&dembvh_texture_view), + }, ], label: Some("DemRendererBindGroup"), }); @@ -397,6 +421,57 @@ fn load_dem_texture( ) } +fn create_dembvh_texture( + dem: &Dem, + device: &wgpu::Device, + queue: &wgpu::Queue, +) -> (wgpu::TextureView, glam::UVec2) { + let source = DemBvh::new(dem); + let dembvh_size = source.layers.first().expect("DEM BVH contains layers").size; + + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("Dem Texture"), + size: wgpu::Extent3d { + width: dembvh_size, + height: dembvh_size, + depth_or_array_layers: 1, + }, + mip_level_count: source.layers.len() as u32, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rg16Uint, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + view_formats: &[], + }); + + for (level, grid) in source.layers.iter().enumerate() { + queue.write_texture( + wgpu::ImageCopyTexture { + texture: &texture, + mip_level: level as u32, + origin: wgpu::Origin3d::ZERO, + aspect: wgpu::TextureAspect::All, + }, + bytemuck::cast_slice(&grid.data[..]), + wgpu::ImageDataLayout { + offset: 0, + bytes_per_row: Some(std::mem::size_of::() as u32 * 2 * grid.size), + rows_per_image: Some(grid.size), + }, + wgpu::Extent3d { + width: grid.size, + height: grid.size, + depth_or_array_layers: 1, + }, + ); + } + + ( + texture.create_view(&wgpu::TextureViewDescriptor::default()), + glam::UVec2::new(dembvh_size, dembvh_size), + ) +} + fn get_animated_camera_position(animation_time: std::time::Duration, dem_size: f32) -> glam::Vec3 { let animation_phase = 2.0 * std::f32::consts::PI * (animation_time.as_secs_f32() % 10.0) / 10.0; glam::Vec3::new( diff --git a/src/app/dem_renderer.wgsl b/src/app/dem_renderer.wgsl index 3849d8e..7d25f91 100644 --- a/src/app/dem_renderer.wgsl +++ b/src/app/dem_renderer.wgsl @@ -5,7 +5,8 @@ struct VertexOutput { struct Uniforms { transform: mat4x4, - dem_texture_size: vec2 + dem_texture_size: vec2, + dembvh_texture_size: vec2 } @group(0) @binding(0) @@ -14,6 +15,9 @@ var uniforms: Uniforms; @group(0) @binding(1) var dem_texture: texture_2d; +@group(0) @binding(2) +var dembvh_texture: texture_2d; + @vertex fn vs_main( @@ -28,7 +32,7 @@ fn vs_main( @fragment fn fs_solid(vertex: VertexOutput) -> @location(0) vec4 { let texture_index = vec2(fract(abs(vertex.test)/500.0)*vec2(uniforms.dem_texture_size)); - let v_i = textureLoad(dem_texture, texture_index, 0).r; - let v = f32(v_i) / 65535.0; - return vec4(v, v, 1.0, 1.0); + let v_i = vec3(textureLoad(dem_texture, texture_index, 0).r, textureLoad(dembvh_texture, texture_index, 0).rg); + let v = vec3(v_i) / 65535.0; + return vec4(v, 1.0); } \ No newline at end of file diff --git a/src/app/raster/dem.rs b/src/app/raster/dem.rs index e161ee6..2f729eb 100644 --- a/src/app/raster/dem.rs +++ b/src/app/raster/dem.rs @@ -59,7 +59,7 @@ fn round_bound(v: u32) -> u32 { } impl DemBvh { - fn new(dem: &Dem) -> DemBvh { + pub fn new(dem: &Dem) -> DemBvh { let mut layers = vec![create_first_dembvh_layer(dem)]; while layers.last().unwrap().size > 1 { layers.push(create_next_dembvh_layer(layers.last().unwrap())); diff --git a/src/app/raster/mod.rs b/src/app/raster/mod.rs index 75f3701..ba49379 100644 --- a/src/app/raster/mod.rs +++ b/src/app/raster/mod.rs @@ -1,3 +1,3 @@ mod dem; -pub use dem::Dem; +pub use dem::{Dem, DemBvh};