Add non-working raycasting code
Implemented basic raycasting but it doesn't work; I'll check this in and then add GPU unit tests.
This commit is contained in:
parent
5e3b97ed61
commit
f7603661c1
|
|
@ -69,13 +69,16 @@ impl Camera {
|
||||||
#[derive(Clone, Copy, Pod, Zeroable)]
|
#[derive(Clone, Copy, Pod, Zeroable)]
|
||||||
struct UniformBufferContents {
|
struct UniformBufferContents {
|
||||||
camera_matrix: [f32; 16],
|
camera_matrix: [f32; 16],
|
||||||
dem_texture_size: [u32; 2],
|
camera_position: [f32; 4],
|
||||||
dembvh_texture_size: [u32; 2],
|
dem_min_corner: [f32; 2],
|
||||||
|
dem_cell_size: [f32; 2],
|
||||||
|
dem_z_range: [f32; 2],
|
||||||
}
|
}
|
||||||
// This struct is 72 bytes but WGSL expects the buffer size to be be a multiple
|
// WGSL expects the buffer size to be be a multiple of the alignment of the
|
||||||
// of the alignment of the member with the largest alignment. The mat4x4<f32>
|
// member with the largest alignment. (The mat4x4<f32> type has a 16-byte
|
||||||
// type has a 16-byte alignment, so we round up to 16 * 5 = 80.
|
// alignment.) So this value may be rounded up from the actual size of
|
||||||
const UNIFORM_BUFFER_SIZE: u64 = 80;
|
// UniformBufferContents.
|
||||||
|
const UNIFORM_BUFFER_SIZE: u64 = 112;
|
||||||
|
|
||||||
struct UniformBufferManager {
|
struct UniformBufferManager {
|
||||||
cpu_buffer: UniformBufferContents,
|
cpu_buffer: UniformBufferContents,
|
||||||
|
|
@ -102,16 +105,28 @@ impl UniformBufferManager {
|
||||||
.clone_from_slice(&camera_matrix.to_cols_array())
|
.clone_from_slice(&camera_matrix.to_cols_array())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_dem_texture_size(&mut self, dem_texture_size: glam::UVec2) {
|
fn set_camera_position(&mut self, camera_position: glam::Vec4) {
|
||||||
self.cpu_buffer
|
self.cpu_buffer
|
||||||
.dem_texture_size
|
.camera_position
|
||||||
.clone_from_slice(&dem_texture_size.to_array());
|
.clone_from_slice(&camera_position.to_array())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_dembvh_texture_size(&mut self, dembvh_texture_size: glam::UVec2) {
|
fn set_dem_min_corner(&mut self, value: glam::Vec2) {
|
||||||
self.cpu_buffer
|
self.cpu_buffer
|
||||||
.dembvh_texture_size
|
.dem_min_corner
|
||||||
.clone_from_slice(&dembvh_texture_size.to_array());
|
.clone_from_slice(&value.to_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dem_cell_size(&mut self, value: glam::Vec2) {
|
||||||
|
self.cpu_buffer
|
||||||
|
.dem_cell_size
|
||||||
|
.clone_from_slice(&value.to_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_dem_z_range(&mut self, value: glam::Vec2) {
|
||||||
|
self.cpu_buffer
|
||||||
|
.dem_z_range
|
||||||
|
.clone_from_slice(&value.to_array());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_binding(&self) -> wgpu::BindingResource<'_> {
|
fn get_binding(&self) -> wgpu::BindingResource<'_> {
|
||||||
|
|
@ -150,15 +165,19 @@ impl DemRenderer {
|
||||||
|
|
||||||
let index_count = index_data.len();
|
let index_count = index_data.len();
|
||||||
|
|
||||||
let (dem_texture_view, dem_texture_size) = load_dem_texture(&source, device, queue);
|
let dem_texture_view = load_dem_texture(&source, device, queue);
|
||||||
let (dembvh_texture_view, dembvh_texture_size) =
|
let dembvh_texture_view = create_dembvh_texture(&source, device, queue);
|
||||||
create_dembvh_texture(&source, device, queue);
|
|
||||||
|
|
||||||
let camera = Camera::new(surface_config.width as f32 / surface_config.height as f32);
|
let camera = Camera::new(surface_config.width as f32 / surface_config.height as f32);
|
||||||
|
|
||||||
let mut uniforms = UniformBufferManager::new(device);
|
let mut uniforms = UniformBufferManager::new(device);
|
||||||
uniforms.set_dem_texture_size(dem_texture_size);
|
uniforms.set_dem_min_corner(glam::Vec2::new(source.x_min, source.y_min));
|
||||||
uniforms.set_dembvh_texture_size(dembvh_texture_size);
|
uniforms.set_dem_cell_size(
|
||||||
|
glam::Vec2::new(source.x_max, source.y_max)
|
||||||
|
- glam::Vec2::new(source.x_min, source.y_min)
|
||||||
|
/ glam::Vec2::new(source.num_cells_x as f32, source.num_cells_y as f32),
|
||||||
|
);
|
||||||
|
uniforms.set_dem_z_range(glam::Vec2::new(source.z_min, source.z_max));
|
||||||
|
|
||||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
|
|
@ -277,14 +296,15 @@ impl DemRenderer {
|
||||||
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||||
label: Some("DemRendererCommandEncoder"),
|
label: Some("DemRendererCommandEncoder"),
|
||||||
});
|
});
|
||||||
self.camera.set_position(
|
let camera_position = get_animated_camera_position(
|
||||||
get_animated_camera_position(
|
|
||||||
self.animation_start.elapsed(),
|
self.animation_start.elapsed(),
|
||||||
self.get_max_dem_dimension(),
|
self.get_max_dem_dimension(),
|
||||||
),
|
|
||||||
self.get_dem_centre(),
|
|
||||||
);
|
);
|
||||||
|
self.camera
|
||||||
|
.set_position(camera_position, self.get_dem_centre());
|
||||||
self.uniforms.set_camera_matrix(self.camera.get_matrix());
|
self.uniforms.set_camera_matrix(self.camera.get_matrix());
|
||||||
|
self.uniforms
|
||||||
|
.set_camera_position(camera_position.extend(1.0));
|
||||||
self.uniforms.update_buffer(queue);
|
self.uniforms.update_buffer(queue);
|
||||||
{
|
{
|
||||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
|
@ -378,11 +398,7 @@ fn create_vertices(dem: &Rc<Dem>) -> (Vec<Vertex>, Vec<u16>) {
|
||||||
(vertex_data.to_vec(), index_data.to_vec())
|
(vertex_data.to_vec(), index_data.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_dem_texture(
|
fn load_dem_texture(source: &Dem, device: &wgpu::Device, queue: &wgpu::Queue) -> wgpu::TextureView {
|
||||||
source: &Dem,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
queue: &wgpu::Queue,
|
|
||||||
) -> (wgpu::TextureView, glam::UVec2) {
|
|
||||||
let texture_size = wgpu::Extent3d {
|
let texture_size = wgpu::Extent3d {
|
||||||
width: source.num_cells_x,
|
width: source.num_cells_x,
|
||||||
height: source.num_cells_y,
|
height: source.num_cells_y,
|
||||||
|
|
@ -415,17 +431,14 @@ fn load_dem_texture(
|
||||||
texture_size,
|
texture_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
(
|
texture.create_view(&wgpu::TextureViewDescriptor::default())
|
||||||
texture.create_view(&wgpu::TextureViewDescriptor::default()),
|
|
||||||
glam::UVec2::new(source.num_cells_x, source.num_cells_y),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_dembvh_texture(
|
fn create_dembvh_texture(
|
||||||
dem: &Dem,
|
dem: &Dem,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
queue: &wgpu::Queue,
|
||||||
) -> (wgpu::TextureView, glam::UVec2) {
|
) -> wgpu::TextureView {
|
||||||
let source = DemBvh::new(dem);
|
let source = DemBvh::new(dem);
|
||||||
let dembvh_size = source.layers.first().expect("DEM BVH contains layers").size;
|
let dembvh_size = source.layers.first().expect("DEM BVH contains layers").size;
|
||||||
|
|
||||||
|
|
@ -466,10 +479,7 @@ fn create_dembvh_texture(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
texture.create_view(&wgpu::TextureViewDescriptor::default())
|
||||||
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 {
|
fn get_animated_camera_position(animation_time: std::time::Duration, dem_size: f32) -> glam::Vec3 {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
struct VertexOutput {
|
struct VertexOutput {
|
||||||
@location(0) test: vec2<f32>,
|
@location(0) world_space_position: vec4<f32>,
|
||||||
@builtin(position) position: vec4<f32>,
|
@builtin(position) position: vec4<f32>,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Uniforms {
|
struct Uniforms {
|
||||||
transform: mat4x4<f32>,
|
transform: mat4x4<f32>,
|
||||||
dem_texture_size: vec2<u32>,
|
camera_position: vec4<f32>,
|
||||||
dembvh_texture_size: vec2<u32>
|
dem_min_corner: vec2<f32>,
|
||||||
|
dem_cell_size: vec2<f32>,
|
||||||
|
dem_z_range: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
|
|
@ -18,6 +20,90 @@ var dem_texture: texture_2d<u32>;
|
||||||
@group(0) @binding(2)
|
@group(0) @binding(2)
|
||||||
var dembvh_texture: texture_2d<u32>;
|
var dembvh_texture: texture_2d<u32>;
|
||||||
|
|
||||||
|
struct BoundingNode {
|
||||||
|
index: vec2<u32>,
|
||||||
|
level: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AABB {
|
||||||
|
min_corner: vec3<f32>,
|
||||||
|
max_corner: vec3<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Ray { origin: vec3<f32>, direction: vec3<f32> };
|
||||||
|
|
||||||
|
fn intersect_ray_with_aabb(ray: Ray, aabb: AABB) -> bool {
|
||||||
|
let t1 = (aabb.min_corner - ray.origin) / ray.direction;
|
||||||
|
let t2 = (aabb.max_corner - ray.origin) / ray.direction;
|
||||||
|
let t_mins = min(t1, t2);
|
||||||
|
let t_min = min(t_mins.x, min(t_mins.y, t_mins.z));
|
||||||
|
let t_maxs = max(t1, t2);
|
||||||
|
let t_max = max(t_maxs.x, max(t_maxs.y, t_maxs.z));
|
||||||
|
return t_min <= t_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale_u16(value: u32, range: vec2<f32>) -> f32 {
|
||||||
|
return range.x + (f32(value - 1) / 65534.0) * (range.y - range.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_xy_min_for_node(node: BoundingNode) -> vec2<f32> {
|
||||||
|
return uniforms.dem_min_corner.xy + uniforms.dem_cell_size * vec2<f32>(node.index) * exp2(f32(node.level));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_xy_max_for_node(node: BoundingNode) -> vec2<f32> {
|
||||||
|
return uniforms.dem_min_corner.xy + uniforms.dem_cell_size * vec2<f32>(node.index + 1) * exp2(f32(node.level));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NodeStack {
|
||||||
|
stack: array<BoundingNode,64>,
|
||||||
|
count: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_node_stack(stack: ptr<function,NodeStack>, node: BoundingNode) {
|
||||||
|
(*stack).stack[(*stack).count] = node;
|
||||||
|
(*stack).count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_node_stack(stack: ptr<function,NodeStack>) -> BoundingNode {
|
||||||
|
(*stack).count--;
|
||||||
|
return (*stack).stack[(*stack).count];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intersect_ray_with_node(ray: Ray, root_node: BoundingNode) -> bool {
|
||||||
|
var node_stack: NodeStack;
|
||||||
|
node_stack.count = 0u;
|
||||||
|
push_node_stack(&node_stack, root_node);
|
||||||
|
while node_stack.count > 0 {
|
||||||
|
let node = pop_node_stack(&node_stack);
|
||||||
|
let minmax_z = textureLoad(dembvh_texture, node.index, i32(node.level)).rg;
|
||||||
|
if minmax_z.r == 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let min_z = scale_u16(minmax_z.r, uniforms.dem_z_range);
|
||||||
|
let max_z = scale_u16(minmax_z.g, uniforms.dem_z_range);
|
||||||
|
var aabb: AABB ;
|
||||||
|
aabb.min_corner = vec3<f32>(get_xy_min_for_node(node), min_z);
|
||||||
|
aabb.max_corner = vec3<f32>(get_xy_max_for_node(node), min_z);
|
||||||
|
if intersect_ray_with_aabb(ray, aabb) {
|
||||||
|
if node.level == 0 {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
let next_index = node.index * 2;
|
||||||
|
var next_node: BoundingNode;
|
||||||
|
next_node.index = next_index;
|
||||||
|
next_node.level = node.level - 1;
|
||||||
|
push_node_stack(&node_stack, next_node);
|
||||||
|
next_node.index = next_index + vec2<u32>(1, 0);
|
||||||
|
push_node_stack(&node_stack, next_node);
|
||||||
|
next_node.index = next_index + vec2<u32>(0, 1);
|
||||||
|
push_node_stack(&node_stack, next_node);
|
||||||
|
next_node.index = next_index + vec2<u32>(1, 1);
|
||||||
|
push_node_stack(&node_stack, next_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(
|
fn vs_main(
|
||||||
|
|
@ -25,14 +111,23 @@ fn vs_main(
|
||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
var result: VertexOutput;
|
var result: VertexOutput;
|
||||||
result.position = uniforms.transform * position;
|
result.position = uniforms.transform * position;
|
||||||
result.test = position.xy;
|
result.world_space_position = position;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_solid(vertex: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_solid(vertex: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let texture_index = vec2<i32>(fract(abs(vertex.test)/500.0)*vec2<f32>(uniforms.dem_texture_size));
|
var ray: Ray;
|
||||||
let v_i = vec3<u32>(textureLoad(dem_texture, texture_index, 0).r, textureLoad(dembvh_texture, texture_index, 0).rg);
|
ray.origin = vertex.world_space_position.xyz;
|
||||||
let v = vec3<f32>(v_i) / 65535.0;
|
ray.direction = normalize(vertex.world_space_position.xyz - uniforms.camera_position.xyz);
|
||||||
return vec4<f32>(v, 1.0);
|
|
||||||
|
var root_node: BoundingNode;
|
||||||
|
root_node.index = vec2<u32>(0);
|
||||||
|
root_node.level = textureNumLevels(dembvh_texture) - 1;
|
||||||
|
|
||||||
|
if intersect_ray_with_node(ray, root_node) {
|
||||||
|
return vec4<f32>(1.0);
|
||||||
|
} else {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue