From 91a66e3bb4333c57fa6876e6291469cbf13249cb Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Mon, 6 Jan 2025 11:18:43 -0400 Subject: [PATCH] Add antialiasing --- src/app/dem_renderer/dem_renderer.wgsl | 91 ++++++++++++++++---------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/src/app/dem_renderer/dem_renderer.wgsl b/src/app/dem_renderer/dem_renderer.wgsl index 7d1a5f3..cf864b4 100644 --- a/src/app/dem_renderer/dem_renderer.wgsl +++ b/src/app/dem_renderer/dem_renderer.wgsl @@ -38,44 +38,63 @@ fn fs_solid(vertex: VertexOutput) -> @location(0) vec4 { var ray: Ray; ray.origin = vertex.world_space_position.xyz; ray.direction = normalize(vertex.world_space_position.xyz - uniforms.camera_position.xyz); + // Spread rays into RGSS antialiasing pattern. + let ray_dx = dpdy(ray.direction); + let ray_dy = dpdy(ray.direction); + var ray_directions: array,4>; + ray_directions[0] = ray.direction + 0.125*ray_dx + 0.375*ray_dy; + ray_directions[1] = ray.direction - 0.125*ray_dx - 0.375*ray_dy; + ray_directions[2] = ray.direction + 0.375*ray_dx + 0.125*ray_dy; + ray_directions[3] = ray.direction - 0.375*ray_dx - 0.125*ray_dy; - var root_node: BoundingNode; - root_node.index = vec2(0); - root_node.level = textureNumLevels(dembvh_texture) - 1; + // Possibly these ray directions could be stored in a matrix and we could + // evaluate them all at once instead of looping. - var hit_index = vec2(0); - var hit_location: vec3; - var hit_normal: vec3; - if intersect_ray_with_node(dembvh_texture, - uniforms.dem_min_corner, - uniforms.dem_cell_size, - uniforms.dem_z_range, - ray, - root_node, - &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); - 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)); - return vec4(vec3(l)*shadow_value, 1.0); - } else { + var color_accumulator = vec4(0); + for(var i=0; i<4; i++) { + ray.direction = ray_directions[i]; + + var root_node: BoundingNode; + root_node.index = vec2(0); + root_node.level = textureNumLevels(dembvh_texture) - 1; + + var hit_index = vec2(0); + var hit_location: vec3; + var hit_normal: vec3; + if intersect_ray_with_node(dembvh_texture, + uniforms.dem_min_corner, + uniforms.dem_cell_size, + uniforms.dem_z_range, + ray, + root_node, + &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); + 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); + } + } + if color_accumulator.w == 0.0 { discard; } + return color_accumulator * 0.25; }