From dc66ae4b3d4bd53291efc7443325e2075369fbdd Mon Sep 17 00:00:00 2001
From: zomseffen <steffen@tom.bi>
Date: Wed, 5 Feb 2025 16:50:57 +0100
Subject: [PATCH] recursive reflection for nontransparnt elements

---
 shaders/compiled/frag_rt_quad.spv | Bin 36496 -> 41856 bytes
 shaders/rt_quad.frag              | 232 ++++++++++++++++++------------
 src/main.rs                       |   2 +-
 src/scene/empty_volume.rs         |  15 +-
 src/scene/mod.rs                  |  14 +-
 5 files changed, 162 insertions(+), 101 deletions(-)

diff --git a/shaders/compiled/frag_rt_quad.spv b/shaders/compiled/frag_rt_quad.spv
index e1015268fbc4f88176fbdddd7c9e90d5e680638d..af2c27e9d9c348bc26a28660a63c8c01940739ef 100644
GIT binary patch
literal 41856
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

literal 36496
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
b@3+8d+c@pH@9hM3UhJQKe&3|#J>dTUfWJJ9

diff --git a/shaders/rt_quad.frag b/shaders/rt_quad.frag
index 806c1d3..9199c8f 100644
--- a/shaders/rt_quad.frag
+++ b/shaders/rt_quad.frag
@@ -25,6 +25,12 @@ layout(binding = 0) uniform UniformBufferObject {
 layout(binding = 2) buffer SceneInfoBuffer{
      uint infos[]; 
 } scene_info;
+uint max_num_lights = scene_info.infos[0];
+uint max_iterations_per_light = scene_info.infos[1];
+// diffuse raytracing using a quadratic raster of rays
+int half_diffuse_raster_steps = int(scene_info.infos[2]);
+float raster_distance = uintBitsToFloat(scene_info.infos[3]);
+int raster_points = (2 * half_diffuse_raster_steps + 1) * (2 * half_diffuse_raster_steps + 1);
 
 uvec4 unpack_color(uint val) {
     // left most 8 bits first
@@ -37,7 +43,7 @@ uvec4 unpack_color(uint val) {
 }
 
 uint sample_neighbor_from_scene_info(uint volume_start, uvec2 raster_pos, uint f) {
-    uint array_descr_start = volume_start + 6 + scene_info.infos[0];
+    uint array_descr_start = volume_start + 6 + max_num_lights;
     uint color_array_start = array_descr_start + 24;
 
     uint top_color_size_u = scene_info.infos[array_descr_start];
@@ -103,7 +109,7 @@ uint sample_neighbor_from_scene_info(uint volume_start, uvec2 raster_pos, uint f
 }
 
 uvec4 sample_color_from_scene_info(uint volume_start, uvec2 raster_pos, uint f) {
-    uint array_descr_start = volume_start + 6 + scene_info.infos[0];
+    uint array_descr_start = volume_start + 6 + max_num_lights;
     uint color_array_start = array_descr_start + 24;
 
     uint top_color_size_u = scene_info.infos[array_descr_start];
@@ -149,6 +155,34 @@ vec3 get_light_color(uint light_index) {
     return vec3(float(scene_info.infos[light_index + 3]) / 255.0, float(scene_info.infos[light_index + 4]) / 255.0, float(scene_info.infos[light_index + 5]) / 255.0);
 }
 
+vec3 normal_for_facing(uint facing) {
+    if (facing == 0) {
+        return vec3(0.0, 0.0, -1.0);
+    }
+    if (facing == 1) {
+        return vec3(0.0, 0.0, 1.0);
+    }
+    if (facing == 2) {
+        return vec3(1.0, 0.0, 0.0);
+    }
+    if (facing == 3) {
+        return vec3(-1.0, 0.0, 0.0);
+    }
+    if (facing == 4) {
+        return vec3(0.0, 1.0, 0.0);
+    }
+    if (facing == 5) {
+        return vec3(0.0, -1.0, 0.0);
+    }
+
+    return vec3(0.0, 0.0, 0.0);
+}
+
+vec3 reflect_vector(vec3 direction, uint facing) {
+    vec3 normal = normal_for_facing(facing);
+    return direction - 2.0 * dot(direction, normal) * normal;
+}
+
 struct Tracing {
     vec3 end_pos;
     uvec4 end_color;
@@ -159,9 +193,14 @@ struct Tracing {
     bool has_hit;
     vec3 color_mul;
     uvec2 end_raster;
+
+    bool has_transparent_hit;
 };
 
-Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 direction, float max_factor, uint start_cycle, uint max_cycle) {
+Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 start_direction, float start_max_factor, uint start_cycle, uint max_cycle, bool allow_reflect) {
+    vec3 direction = start_direction;
+    float max_factor = start_max_factor;
+    vec3 pos = starting_pos;
     uint cycle = start_cycle;
     // setup volume info
     uint volume_index = volume_start;
@@ -184,8 +223,18 @@ Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 direction, float ma
     float z_factor = max_factor;
 
     Tracing result;
+    result.has_hit = false;
+    result.has_transparent_hit = false;
     result.color_mul = vec3(1.0, 1.0, 1.0);
 
+    // intermediate storage for transparent hit values
+    vec3 end_pos_transparent;
+    uvec4 end_color_transparent;
+    uint end_volume_transparent;
+    uint end_facing_transparent;
+    uvec2 end_raster_transparent;
+    vec3 color_mul_transparent;
+
     while (cycle < max_cycle) {
         cycle ++;
         float x_border = float(volume_pos_x + (scene_info.infos[volume_index + 3]) * uint(x_pos)) - 0.5;
@@ -195,18 +244,17 @@ Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 direction, float ma
         bool needs_next_light = false;
 
         if (!x_null) {
-            x_factor = (x_border - starting_pos.x) / direction.x;
+            x_factor = (x_border - pos.x) / direction.x;
         }
         if (!y_null) {
-            y_factor = (y_border - starting_pos.y) / direction.y;
+            y_factor = (y_border - pos.y) / direction.y;
         }
         if (!z_null) {
-            z_factor = (z_border - starting_pos.z) / direction.z;
+            z_factor = (z_border - pos.z) / direction.z;
         }
 
         if ((x_factor >= max_factor) && (y_factor >= max_factor) && (z_factor >= max_factor)) {
             // no hit, finish tracking
-            result.has_hit = false;
             break;
         } else {
             // if there is a border hit before reaching the end
@@ -215,44 +263,19 @@ Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 direction, float ma
             uint hit_facing = 0;
             uint u = 0;
             uint v = 0;
-            if (x_factor <= y_factor && x_factor <= z_factor) {
-                if (x_pos) {
-                    hit_facing = 3;
-                } else {
-                    hit_facing = 2;
-                }
-                vec3 intersection_pos = starting_pos + x_factor * direction;
-                u = uint(round(intersection_pos.y)) - volume_pos_y;
-                v = uint(round(intersection_pos.z)) - volume_pos_z;
-                result.end_pos = intersection_pos;
-                result.end_facing = hit_facing;
-            }
 
-            if (y_factor <= x_factor && y_factor <= z_factor) {
-                if (y_pos) {
-                    hit_facing = 5;
-                } else {
-                    hit_facing = 4;
-                }
-                vec3 intersection_pos = starting_pos + y_factor * direction;
-                u = uint(round(intersection_pos.x)) - volume_pos_x;
-                v = uint(round(intersection_pos.z)) - volume_pos_z;
-                result.end_pos = intersection_pos;
-                result.end_facing = hit_facing;
-            }
+            bool is_x_smallest = x_factor < y_factor && x_factor < z_factor;
+            bool is_y_smallest = y_factor < x_factor && y_factor < z_factor;
+            bool is_z_smallest = z_factor <= x_factor && z_factor <= y_factor;
+
+            hit_facing = uint(is_x_smallest) * (2 + uint(x_pos)) + uint(is_y_smallest) * (4 + uint(y_pos)) + uint(is_z_smallest && !z_pos);
+            float smallest_factor = min(min(x_factor, y_factor), z_factor); // maybe use multiplication instead?
+            vec3 intersection_pos = pos + smallest_factor * direction;
+            u = uint(is_x_smallest) * (uint(round(intersection_pos.y)) - volume_pos_y) + 
+                uint(is_y_smallest || is_z_smallest) * (uint(round(intersection_pos.x)) - volume_pos_x);
+            v = uint(is_x_smallest || is_y_smallest) * (uint(round(intersection_pos.z)) - volume_pos_z) +
+                uint(is_z_smallest) * (uint(round(intersection_pos.y)) - volume_pos_y);
 
-            if (z_factor <= x_factor && z_factor <= y_factor) {
-                if (z_pos) {
-                    hit_facing = 0;
-                } else {
-                    hit_facing = 1;
-                }
-                vec3 intersection_pos = starting_pos + z_factor * direction;
-                u = uint(round(intersection_pos.x)) - volume_pos_x;
-                v = uint(round(intersection_pos.y)) - volume_pos_y;
-                result.end_pos = intersection_pos;
-                result.end_facing = hit_facing;
-            }
             uint next_neighbor = sample_neighbor_from_scene_info(volume_index, uvec2(u, v), hit_facing);
             uvec4 color_sample = sample_color_from_scene_info(volume_index, uvec2(u, v), hit_facing);
 
@@ -264,42 +287,95 @@ Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 direction, float ma
                     volume_pos_y = scene_info.infos[volume_index + 1]; 
                     volume_pos_z = scene_info.infos[volume_index + 2];
                 } else {
-                    // neightbor miss
+                    // neighbor miss
                     break;
                 }
             } else {
                 if (next_neighbor != 0) {
                     // transparent hit, move on but change the color
+                    end_volume_transparent = volume_index;
+                    color_mul_transparent = result.color_mul;
+
                     volume_index = next_neighbor;
                     volume_pos_x = scene_info.infos[volume_index + 0]; 
                     volume_pos_y = scene_info.infos[volume_index + 1]; 
                     volume_pos_z = scene_info.infos[volume_index + 2];
                     result.color_mul = result.color_mul * vec3(float(color_sample.x) / 255.0, float(color_sample.y) / 255.0, float(color_sample.z) / 255.0);
+                    result.has_transparent_hit = true;
+                    result.end_volume = volume_index;
+
+                    end_color_transparent = color_sample;
+                    end_raster_transparent = uvec2(u, v);
+                    end_pos_transparent = intersection_pos;
+                    end_facing_transparent = hit_facing;
+
+                    // stop iterating if there is barely anything left to see
+                    if (max(result.color_mul.x, max(result.color_mul.y, result.color_mul.z)) < 0.1) {
+                        break;
+                    }                    
                 } else {
-                    // color hit, move on
+                    // color hit, either reflect or move on
+                    result.end_pos = intersection_pos;
+                    result.end_facing = hit_facing;
                     result.end_color = color_sample;
                     result.end_raster = uvec2(u, v);
                     result.has_hit = true;
-                    break;
+                    result.end_volume = volume_index;
+
+                    float reflectivity = 1.0 - float(color_sample.w) / 255.0;
+                    vec3 refltective_color_mul = result.color_mul * vec3(float(color_sample.x) / 255.0, float(color_sample.y) / 255.0, float(color_sample.z) / 255.0);
+                    vec3 visibility_after_reflection = refltective_color_mul * reflectivity;
+                    //break;
+                    //max(visibility_after_reflection.x, max(visibility_after_reflection.y, visibility_after_reflection.z)) >= 0.1 && 
+                    if (allow_reflect) {
+                        // do reflect
+                        direction = reflect_vector(direction, hit_facing);
+                        pos = intersection_pos;
+                        //max_factor -= smallest_factor;
+
+                        x_pos = direction.x > 0.0;
+                        x_null = (direction.x == 0.0);
+                        
+                        y_pos = direction.y > 0.0;
+                        y_null = (direction.y == 0.0);
+
+                        z_pos = direction.z > 0.0;
+                        z_null = (direction.z == 0.0);
+                    } else {
+                        break;
+                    }
                 }
             }
         }
     }
-    result.end_volume = volume_index;
     result.end_factor = min(min(x_factor, y_factor), z_factor);
     result.end_cycle = cycle;
 
+    // in case we have a transparent hit but no hit afterwards
+    if (!result.has_hit && result.has_transparent_hit) {
+        // did we stop because nothing could be seen through the object?
+        if (max(result.color_mul.x, max(result.color_mul.y, result.color_mul.z)) < 0.1) {
+            // if so count it as a hit
+            result.has_hit = true;
+        }  
+        result.end_pos = end_pos_transparent;
+        result.end_color = end_color_transparent;
+        result.end_volume = end_volume_transparent;
+        result.end_facing = end_facing_transparent;
+        result.end_raster = end_raster_transparent;
+        result.color_mul = color_mul_transparent;
+    }
+
     return result;
 }
 
 vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sample, vec3 normal) {
-    uint max_light_num = scene_info.infos[0];
     uint light_num = 0;
 
     // initialize color
     vec3 color_sum = vec3(0.0, 0.0, 0.0) + (orig_color_sample.xyz * 0.01);
 
-    uint max_iterations = max_light_num * scene_info.infos[1];
+    uint max_iterations = max_num_lights * max_iterations_per_light;
     uint iteration = 0;
     while (iteration < max_iterations) {
         // setup light info
@@ -311,15 +387,14 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa
         vec3 light_direction = get_light_position(light_index) - starting_pos;
         vec3 light_color = get_light_color(light_index);
 
-        Tracing result = trace_ray(volume_start, starting_pos, light_direction, 1.0, iteration, max_iterations);
-        if (!result.has_hit) {
-            // no hit, add light color result
-            color_sum += result.color_mul * max(dot(normal, normalize(light_direction)), 0.0) * (orig_color_sample.xyz * light_color) / (length(light_direction) * length(light_direction));
-        }
+        Tracing result = trace_ray(volume_start, starting_pos, light_direction, 1.0, iteration, max_iterations, false);
+        // add result, if there is a hit the null vector will be added
+        color_sum += float(!result.has_hit) * result.color_mul * max(dot(normal, normalize(light_direction)), 0.0) * (orig_color_sample.xyz * light_color) / (length(light_direction) * length(light_direction));
+        
         iteration = result.end_cycle;
 
         light_num += 1;
-        if (light_num >= max_light_num) {
+        if (light_num >= max_num_lights) {
             break;
         }
     }
@@ -327,42 +402,14 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa
     return color_sum;
 }
 
-vec3 normal_for_facing(uint facing) {
-    if (facing == 0) {
-        return vec3(0.0, 0.0, -1.0);
-    }
-    if (facing == 1) {
-        return vec3(0.0, 0.0, 1.0);
-    }
-    if (facing == 2) {
-        return vec3(0.0, 1.0, 0.0);
-    }
-    if (facing == 3) {
-        return vec3(0.0, -1.0, 0.0);
-    }
-    if (facing == 4) {
-        return vec3(1.0, 0.0, 0.0);
-    }
-    if (facing == 5) {
-        return vec3(-1.0, 0.0, 0.0);
-    }
-
-    return vec3(0.0, 0.0, 0.0);
-}
-
 vec3 diffuse_tracing(uint volume_start, uvec2 raster_pos, vec3 pos, uint f) {
     uvec4 color_roughness = sample_color_from_scene_info(volume_start, raster_pos, f);
     vec4 orig_color_sample = vec4(float(color_roughness.x) / 255.0, float(color_roughness.y) / 255.0, float(color_roughness.z) / 255.0, 1);
     vec3 normal = normal_for_facing(f);
 
-    // diffuse raytracing using a quadratic raster of rays
-    int raster_half_steps = int(scene_info.infos[2]);
-    float raster_distance = uintBitsToFloat(scene_info.infos[3]);
-    int raster_points = (2 * raster_half_steps + 1) * (2 * raster_half_steps + 1);
-
     vec3 color_sum = vec3(0.0, 0.0, 0.0);
-    for (int u_offset = -raster_half_steps; u_offset <= raster_half_steps; u_offset++) {
-        for (int v_offset = -raster_half_steps; v_offset <= raster_half_steps; v_offset++) {
+    for (int u_offset = -half_diffuse_raster_steps; u_offset <= half_diffuse_raster_steps; u_offset++) {
+        for (int v_offset = -half_diffuse_raster_steps; v_offset <= half_diffuse_raster_steps; v_offset++) {
             float x_offset = raster_distance * float(u_offset) * float(f == 0 || f == 1 || f == 4 || f == 5);
             float y_offset = raster_distance * float(u_offset) * float(f == 2 || f == 3);
             y_offset += raster_distance * float(v_offset) * float(f == 0 || f == 1);
@@ -400,12 +447,12 @@ void main() {
     vec3 color_sum;
 
     uint orig_neighbor = sample_neighbor_from_scene_info(fragVolumeStart, fragRasterPos, facing);
+    float pos_infinity = uintBitsToFloat(0x7F800000);
     if (orig_neighbor != 0) {
-        float pos_infinity = uintBitsToFloat(0x7F800000);
-        Tracing t = trace_ray(fragVolumeStart, ubo.camera_pos, clamped_pos - ubo.camera_pos, 100.0, 0, 20);
+        Tracing t = trace_ray(fragVolumeStart, ubo.camera_pos, clamped_pos - ubo.camera_pos, pos_infinity, 0, max_iterations_per_light, false);
         float opacity = float(color_roughness.w) / 255.0;
         if (t.has_hit) {
-            vec3 color_seen_through = diffuse_tracing(t.end_volume, t.end_raster, t.end_pos, t.end_facing) * orig_color_sample;
+            vec3 color_seen_through = diffuse_tracing(t.end_volume, t.end_raster, t.end_pos, t.end_facing) * orig_color_sample * t.color_mul;
             vec3 color_direct = diffuse_tracing(fragVolumeStart, fragRasterPos, clamped_pos, facing);
             color_sum = opacity * color_direct + (1.0 - opacity) * color_seen_through;
         }
@@ -417,8 +464,15 @@ void main() {
     }
     else {
         color_sum = diffuse_tracing(fragVolumeStart, fragRasterPos, clamped_pos, facing);
-    }
 
+        vec3 reflection_direction = reflect_vector(normalize(clamped_pos - ubo.camera_pos), facing);
+        Tracing reflection_tracing = trace_ray(fragVolumeStart, clamped_pos, reflection_direction, pos_infinity, 0, max_iterations_per_light, true);
+        float reflectivity = 1.0 - float(color_roughness.w) / 255.0;
+        if (reflection_tracing.has_hit || reflection_tracing.has_transparent_hit) {
+            vec3 color_from_reflection = diffuse_tracing(reflection_tracing.end_volume, reflection_tracing.end_raster, reflection_tracing.end_pos, reflection_tracing.end_facing) * orig_color_sample;
+            color_sum = color_sum * (1.0 - reflectivity) + color_from_reflection * reflectivity;
+        }
+    }
 
     outColor = vec4(color_sum, 1.0);
 }
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 8da19cf..b5a7931 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -180,7 +180,7 @@ impl App {
         data.use_geometry_shader = false;
         data.num_lights_per_volume = 2;
         data.max_iterations_per_light = 20;
-        data.diffuse_raster_steps = 2;
+        data.diffuse_raster_steps = 0;
         data.diffuse_raster_size = 0.01;
         data.max_recursive_rays = 10;
         data.diffuse_rays_per_hit = 1;
diff --git a/src/scene/empty_volume.rs b/src/scene/empty_volume.rs
index 1357e0a..4c36e55 100644
--- a/src/scene/empty_volume.rs
+++ b/src/scene/empty_volume.rs
@@ -66,9 +66,12 @@ impl EmptyVolume {
         let start_time = Instant::now();
         // iterate over all block positions in the oct tree
         let mut check_its = 0;
-        for x_index in 0..tree.size {
-            for y_index in 0..tree.size {
-                for z_index in 0..tree.size {
+        let mut x_index = 0;
+        while x_index < tree.size {
+            let mut y_index = 0;
+            while y_index < tree.size {
+                let mut z_index = 0;
+                while z_index < tree.size {
                     // check if there is a block at that position
                     let query_result = tree.test_element(x_index, y_index, z_index);
                     let mut transparent = false;
@@ -86,6 +89,7 @@ impl EmptyVolume {
                         for volume in &volumes {
                             if volume.borrow().contains(&Vector3{x: x_index, y: y_index, z: z_index}) {
                                 contained = true;
+                                z_index = volume.borrow().size_z + volume.borrow().position.z;
                                 break;
                             }
                         }
@@ -479,9 +483,12 @@ impl EmptyVolume {
                         println!("new volume done");
                         //push to the list
                         volumes.push(reference);
-                    }                    
+                    }
+                    z_index += 1
                 }
+                y_index += 1;
             }
+            x_index += 1;
         }
         println!("Did {} oct tree checks!", check_its);
         println!("add the neighbor linkage for all the volumes of the oct tree");
diff --git a/src/scene/mod.rs b/src/scene/mod.rs
index 1927171..f5a70da 100644
--- a/src/scene/mod.rs
+++ b/src/scene/mod.rs
@@ -73,7 +73,7 @@ impl Scene {
                     color: vec3(shade, 1.0, shade),
                     tex_coord: vec2(0.0, 0.0),
                     transparent: false,
-                    roughness: 128,
+                    roughness: 0,
                 };
 
                 oct_tree.set_cube(cube.clone());
@@ -83,19 +83,19 @@ impl Scene {
         let shade = (rng.gen_range(0..25) as f32) / 100.0;
         let cube = Cube {
             pos: vec3(10.0, 10.0, 10.0),
-            color: vec3(1.0, 0.0, 0.0),
+            color: vec3(1.0, 1.0, 1.0),
             tex_coord: vec2(0.0, 0.0),
-            transparent: true,
-            roughness: 32,
+            transparent: false,
+            roughness: 0,
         };
         oct_tree.set_cube(cube.clone());
 
         let cube = Cube {
             pos: vec3(10.0, 10.0, 9.0),
-            color: vec3(1.0, 0.0, 0.0),
+            color: vec3(1.0, 1.0, 1.0),
             tex_coord: vec2(0.0, 0.0),
-            transparent: true,
-            roughness: 32,
+            transparent: false,
+            roughness: 0,
         };
         oct_tree.set_cube(cube.clone());