From 103cd1bdc28e4f3e735aef971daefc712be50aa0 Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Fri, 10 Jan 2025 14:33:57 -0400 Subject: [PATCH] It's a mess but it works. --- src/app/dem_renderer/dem_renderer.wgsl | 66 ++++++++++++++-------- src/app/dem_renderer/mod.rs | 2 +- src/app/dem_renderer/ray_intersection.wgsl | 40 +++++++------ src/app/dem_renderer/tests.rs | 10 ++-- src/app/dem_renderer/tests.wgsl | 7 ++- 5 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/app/dem_renderer/dem_renderer.wgsl b/src/app/dem_renderer/dem_renderer.wgsl index cf864b4..8182d60 100644 --- a/src/app/dem_renderer/dem_renderer.wgsl +++ b/src/app/dem_renderer/dem_renderer.wgsl @@ -51,8 +51,8 @@ fn fs_solid(vertex: VertexOutput) -> @location(0) vec4 { // evaluate them all at once instead of looping. var color_accumulator = vec4(0); - for(var i=0; i<4; i++) { - ray.direction = ray_directions[i]; + for(var i=0; i<1; i++) { + //ray.direction = ray_directions[i]; var root_node: BoundingNode; root_node.index = vec2(0); @@ -61,7 +61,8 @@ fn fs_solid(vertex: VertexOutput) -> @location(0) vec4 { var hit_index = vec2(0); var hit_location: vec3; var hit_normal: vec3; - if intersect_ray_with_node(dembvh_texture, + if intersect_ray_with_node(dem_texture, + dembvh_texture, uniforms.dem_min_corner, uniforms.dem_cell_size, uniforms.dem_z_range, @@ -70,31 +71,48 @@ fn fs_solid(vertex: VertexOutput) -> @location(0) vec4 { &hit_index, &hit_location, &hit_normal) { - // Calculate light - let sun_direction = - (uniforms.camera_to_world_matrix - * vec4(normalize(vec3(1.0, 1.0, 1.0)), 0.0)).xyz; - let l = dot(hit_normal, sun_direction); + let sun_direction_samples = array,7>(vec3(1.0, 0.5, 0.25), + vec3(1.0, 0.33, 0.25), + vec3(1.1, 0.3, 0.25), + vec3(1.1, 0.33, 0.25), + vec3(1.0, 0.27, 0.25), + vec3(0.9, 0.3, 0.25), + vec3(0.9, 0.27, 0.25)); + var shadow_value = 0.0f; var shadow_ray :Ray; shadow_ray.origin = hit_location + hit_normal * 0.1; - shadow_ray.direction = sun_direction; - var dummy0: vec3; - var dummy1: vec3; - let shadow_value = - select(1.0, 0.0, intersect_ray_with_node(dembvh_texture, - uniforms.dem_min_corner, - uniforms.dem_cell_size, - uniforms.dem_z_range, - shadow_ray, - root_node, - &hit_index, - &dummy0, - &dummy1)); - color_accumulator += vec4(vec3(l)*shadow_value, 1.0); + for(var i=0; i<1; i++) { + // Calculate light + let sun_direction = + (uniforms.camera_to_world_matrix + * vec4(normalize(sun_direction_samples[i]), 0.0)).xyz; + shadow_ray.direction = sun_direction; + var dummy0: vec2; + var dummy1: vec3; + var dummy2: vec3; + shadow_value += + select(1.0, 0.0, intersect_ray_with_node(dem_texture, + dembvh_texture, + uniforms.dem_min_corner, + uniforms.dem_cell_size, + uniforms.dem_z_range, + shadow_ray, + root_node, + &dummy0, + &dummy1, + &dummy2)); + } + let sun_direction = + (uniforms.camera_to_world_matrix + * vec4(normalize(sun_direction_samples[0]), 0.0)).xyz; + let lambertian_value = dot(hit_normal, sun_direction); + let ambient_strength = 0.25; + let l = ambient_strength + (1.0 - ambient_strength) * lambertian_value * shadow_value; + color_accumulator += vec4(vec3(l), 1.0); } } - if color_accumulator.w == 0.0 { + if color_accumulator.a == 0.0 { discard; } - return color_accumulator * 0.25; + return color_accumulator; } diff --git a/src/app/dem_renderer/mod.rs b/src/app/dem_renderer/mod.rs index 3d05fad..4c6e3c1 100644 --- a/src/app/dem_renderer/mod.rs +++ b/src/app/dem_renderer/mod.rs @@ -494,7 +494,7 @@ fn create_dembvh_texture( } 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() % 25.0) / 25.0; + let animation_phase = 2.0 * std::f32::consts::PI * (animation_time.as_secs_f32() % 100.0) / 100.0; glam::Vec3::new( dem_size * f32::sin(animation_phase), dem_size * f32::cos(animation_phase), diff --git a/src/app/dem_renderer/ray_intersection.wgsl b/src/app/dem_renderer/ray_intersection.wgsl index 51c3893..f31c5e3 100644 --- a/src/app/dem_renderer/ray_intersection.wgsl +++ b/src/app/dem_renderer/ray_intersection.wgsl @@ -13,7 +13,7 @@ struct AABB { struct Ray { origin: vec3, direction: vec3 }; fn invert_ray_direction(v: vec3 ) -> vec3 { - return select(vec3(1.0e+30), + return select(vec3(1.0e+30), vec3(1.0) / v, vec3(v)); } @@ -61,7 +61,8 @@ fn pop_node_stack(stack: ptr) -> BoundingNode { return (*stack).stack[(*stack).count]; } -fn intersect_ray_with_node(tree_texture: texture_2d, +fn intersect_ray_with_node(dem_texture: texture_2d, + tree_texture: texture_2d, dem_min_corner: vec2, dem_cell_size: vec2, dem_z_range: vec2, @@ -107,12 +108,12 @@ fn intersect_ray_with_node(tree_texture: texture_2d, &location, &normal) { - // Node bounding boxes are non-overlapping, so we don't need - // to calculate a more precise hit_distance - closest_hit_distance = hit_distance; - *hit_cell = node.index; - *hit_location = location; - *hit_normal = normal; + // Node bounding boxes are non-overlapping, so we don't need + // to calculate a more precise hit_distance + closest_hit_distance = hit_distance; + *hit_cell = node.index; + *hit_location = location; + *hit_normal = normal; } } } else { @@ -154,17 +155,19 @@ fn intersect_ray_with_grid_cell(ray: Ray, // Calculate xyz of cell corners let xy00 = dem_min_corner.xy + dem_cell_size * vec2(cell_index); let p00 = vec3(xy00, z00); - let p01 = vec3(xy00 + vec2(0, 1), z01); - let p10 = vec3(xy00 + vec2(1, 0), z10); - let p11 = vec3(xy00 + vec2(1, 1), z11); + let p01 = vec3(xy00 + vec2(0, 1) * dem_cell_size, z01); + let p10 = vec3(xy00 + vec2(1, 0) * dem_cell_size, z10); + let p11 = vec3(xy00 + vec2(1, 1) * dem_cell_size, z11); // Intersect ray with the plane of each triangle and then take the // point that's inside it's triangle. // p is the point and p0, p1 and p2 are the triangle corners. - let p_t0 = intersect_ray_with_triangle_plane(ray, p00, p01, p11); - let p_t1 = intersect_ray_with_triangle_plane(ray, p00, p10, p11); - let point_is_in_triangle_0 = point_is_in_triangle(p_t0, p00, p01, p11); - let point_is_in_triangle_1 = point_is_in_triangle(p_t0, p00, p10, p11); + var hit_t0: bool; + let p_t0 = intersect_ray_with_triangle_plane(ray, p00, p01, p11, &hit_t0); + var hit_t1: bool; + let p_t1 = intersect_ray_with_triangle_plane(ray, p00, p10, p11, &hit_t1); + let point_is_in_triangle_0 = hit_t0 && point_is_in_triangle(p_t0, p00, p01, p11); + let point_is_in_triangle_1 = hit_t1 && point_is_in_triangle(p_t1, p00, p10, p11); // Always calculate location and normal, even if ray doesn't intersect // either triangle. It might be better to do an early return if there's @@ -183,9 +186,12 @@ fn intersect_ray_with_grid_cell(ray: Ray, fn intersect_ray_with_triangle_plane(ray: Ray, p0: vec3, p1: vec3, - p2: vec3) -> vec3 { + p2: vec3, + hit: ptr) -> vec3 { let n = cross(p1-p0, p2-p0); - return ray.origin + ray.direction * dot(p0 - ray.origin, n) / dot(ray.direction, n); + let t = dot(p0 - ray.origin, n) / dot(ray.direction, n); + *hit = t >= 0.0; + return ray.origin + ray.direction * t; } diff --git a/src/app/dem_renderer/tests.rs b/src/app/dem_renderer/tests.rs index e2876b2..b5498de 100644 --- a/src/app/dem_renderer/tests.rs +++ b/src/app/dem_renderer/tests.rs @@ -140,14 +140,14 @@ fn test_shaders() { aabb_max_corner: vec3(1.0, 1.0, 1.0), }, ]; - let output_buffer: Vec = bytemuck::cast_slice(&block_on(run_compute_shader_test( + let output_buffer: Vec = bytemuck::cast_slice(&block_on(run_compute_shader_test( wgsl_module!("tests.wgsl"), "test_intersect_ray_with_aabb", bytemuck::cast_slice(&input_buffer), input_buffer.len() * 4, ))) - .to_vec(); - assert_eq!(output_buffer[0], 1); - assert_eq!(output_buffer[1], 0); - assert_eq!(output_buffer[2], 1); + .to_vec(); + assert!(dbg!(output_buffer[0]) >= 0.0); + assert!(dbg!(output_buffer[1]) < 0.0); + assert!(dbg!(output_buffer[2]) >= 0.0); } diff --git a/src/app/dem_renderer/tests.wgsl b/src/app/dem_renderer/tests.wgsl index de0cf5d..7136f60 100644 --- a/src/app/dem_renderer/tests.wgsl +++ b/src/app/dem_renderer/tests.wgsl @@ -3,7 +3,7 @@ var input_data: array; @group(0) @binding(1) -var output_data: array; +var output_data: array; //#include ray_intersection.wgsl @@ -24,10 +24,11 @@ fn test_intersect_ray_with_aabb() { var aabb: AABB; aabb.min_corner = input_data[i].aabb_min_corner; aabb.max_corner = input_data[i].aabb_max_corner; - if intersect_ray_with_aabb(ray, aabb) >= 0.0 { + output_data[i] = intersect_ray_with_aabb(ray, aabb); + /*if intersect_ray_with_aabb(ray, aabb) >= 0.0 { output_data[i] = 1u; }else { output_data[i] = 0u; - } + }*/ } }