diff --git a/shaders/compiled/frag_rt_quad.spv b/shaders/compiled/frag_rt_quad.spv index 70c2c6a..c161614 100644 Binary files a/shaders/compiled/frag_rt_quad.spv and b/shaders/compiled/frag_rt_quad.spv differ diff --git a/shaders/rt_quad.frag b/shaders/rt_quad.frag index d075f61..bac8002 100644 --- a/shaders/rt_quad.frag +++ b/shaders/rt_quad.frag @@ -127,68 +127,71 @@ uvec4 sample_color_from_scene_info(uint volume_start, uvec2 raster_pos, uint f) } vec3 get_light_position(uint light_index) { - return vec3(float(scene_info.infos[light_index]), float(scene_info.infos[light_index + 1]), float(scene_info.infos[light_index + 2])); + return vec3(uintBitsToFloat(scene_info.infos[light_index]), uintBitsToFloat(scene_info.infos[light_index + 1]), uintBitsToFloat(scene_info.infos[light_index + 2])); } 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 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sample) { - uint max_light_num = scene_info.infos[0]; - uint light_num = 0; +struct Tracing { + vec3 end_pos; + uvec4 end_color; + uint end_volume; + uint end_facing; + float end_factor; + uint end_cycle; + bool has_hit; +}; +Tracing trace_ray(uint volume_start, vec3 starting_pos, vec3 direction, float max_factor, uint start_cycle, uint max_cycle) { + uint cycle = start_cycle; // setup volume info uint volume_index = volume_start; uint volume_pos_x = scene_info.infos[volume_index + 0]; uint volume_pos_y = scene_info.infos[volume_index + 1]; uint volume_pos_z = scene_info.infos[volume_index + 2]; - - // setup light info - uint light_index = scene_info.infos[volume_start + 6 + light_num]; - vec3 light_direction = get_light_position(light_index) - starting_pos; - vec3 light_color = get_light_color(light_index); - - bool x_pos = light_direction.x > 0.0; - bool x_null = (light_direction.x == 0.0); - - bool y_pos = light_direction.y > 0.0; - bool y_null = (light_direction.y == 0.0); - bool z_pos = light_direction.z > 0.0; - bool z_null = (light_direction.z == 0.0); + bool x_pos = direction.x > 0.0; + bool x_null = (direction.x == 0.0); + + bool y_pos = direction.y > 0.0; + bool y_null = (direction.y == 0.0); - // initialize color - vec3 color_sum = vec3(0.0, 0.0, 0.0) + (orig_color_sample.xyz * 0.01); + bool z_pos = direction.z > 0.0; + bool z_null = (direction.z == 0.0); - uint max_iterations = max_light_num * scene_info.infos[1]; - for (int i = 0; i < max_iterations; i++) { + // default is max factor, that way we avoid collision when going parallel to an axis. The other directions will score a hit + float x_factor = max_factor; + float y_factor = max_factor; + float z_factor = max_factor; + + Tracing result; + + while (cycle < max_cycle) { + cycle ++; float x_border = float(volume_pos_x + (scene_info.infos[volume_index + 3]) * uint(x_pos)) - 0.5; float y_border = float(volume_pos_y + (scene_info.infos[volume_index + 4]) * uint(y_pos)) - 0.5; float z_border = float(volume_pos_z + (scene_info.infos[volume_index + 5]) * uint(z_pos)) - 0.5; bool needs_next_light = false; - // 2 is way behind the light position and should result in no collision being detected - float x_factor = 2.0; - float y_factor = 2.0; - float z_factor = 2.0; if (!x_null) { - x_factor = (x_border - starting_pos.x) / light_direction.x; + x_factor = (x_border - starting_pos.x) / direction.x; } if (!y_null) { - y_factor = (y_border - starting_pos.y) / light_direction.y; + y_factor = (y_border - starting_pos.y) / direction.y; } if (!z_null) { - z_factor = (z_border - starting_pos.z) / light_direction.z; + z_factor = (z_border - starting_pos.z) / direction.z; } - if ((x_factor >= 1.0) && (y_factor >= 1.0) && (z_factor >= 1.0)) { - // no hit, add light color result - color_sum += (orig_color_sample.xyz * light_color) / ((0.01 * length(light_direction) * length(light_direction)) + 1.0); - needs_next_light = true; + 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 light + // if there is a border hit before reaching the end // change to the relevant next volume // Todo: look into removing ifs from this uint hit_facing = 0; @@ -200,9 +203,11 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa } else { hit_facing = 2; } - vec3 intersection_pos = starting_pos + x_factor * light_direction; + 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) { @@ -211,9 +216,11 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa } else { hit_facing = 4; } - vec3 intersection_pos = starting_pos + y_factor * light_direction; + 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; } if (z_factor <= x_factor && z_factor <= y_factor) { @@ -222,9 +229,11 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa } else { hit_facing = 1; } - vec3 intersection_pos = starting_pos + z_factor * light_direction; + 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); @@ -237,43 +246,56 @@ vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sa volume_pos_y = scene_info.infos[volume_index + 1]; volume_pos_z = scene_info.infos[volume_index + 2]; } else { - // neightbor miss, shouldn't happen with a light inside of a volume. Might happen with ambient light. For now move on to next light. - needs_next_light = true; + // neightbor miss + break; } } else { - // color hit, move on to next light (may change once transparents are implemnted) - needs_next_light = true; - } - } - if (needs_next_light) { - light_num += 1; - if (light_num >= max_light_num) { + // color hit, move on + result.end_color = color_sample; + result.has_hit = true; break; } - // set up the new light - light_index = scene_info.infos[volume_start + 6 + light_num]; - if (light_index == 0) { - // abort if there is no new light - break; - } - light_direction = get_light_position(light_index) - starting_pos; - light_color = get_light_color(light_index); - - x_pos = light_direction.x > 0.0; - x_null = (light_direction.x == 0.0); - - y_pos = light_direction.y > 0.0; - y_null = (light_direction.y == 0.0); - - z_pos = light_direction.z > 0.0; - z_null = (light_direction.z == 0.0); - // reset volume info - volume_index = volume_start; - 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.end_volume = volume_index; + result.end_factor = min(min(x_factor, y_factor), z_factor); + result.end_cycle = cycle; + + return result; +} + +vec3 get_lighting_color(uint volume_start, vec3 starting_pos, vec4 orig_color_sample) { + 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 iteration = 0; + while (iteration < max_iterations) { + // setup light info + uint light_index = scene_info.infos[volume_start + 6 + light_num]; + if (light_index == 0) { + // abort if there is no new light + break; + } + 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 += (orig_color_sample.xyz * light_color) / ((0.01 * length(light_direction) * length(light_direction)) + 1.0); + } + iteration = result.end_cycle; + + light_num += 1; + if (light_num >= max_light_num) { + break; + } + } + return color_sum; } diff --git a/src/scene/light.rs b/src/scene/light.rs index 4893dd3..20a33ef 100644 --- a/src/scene/light.rs +++ b/src/scene/light.rs @@ -15,9 +15,9 @@ impl PointLight { } pub fn insert_into_memory(&self, mut v: Vec) -> Vec { - v[self.memory_start] = self.pos.x as u32; - v[self.memory_start + 1] = self.pos.y as u32; - v[self.memory_start + 2] = self.pos.z as u32; + v[self.memory_start] = u32::from_ne_bytes(self.pos.x.to_ne_bytes()); + v[self.memory_start + 1] = u32::from_ne_bytes(self.pos.y.to_ne_bytes()); + v[self.memory_start + 2] = u32::from_ne_bytes(self.pos.z.to_ne_bytes()); v[self.memory_start + 3] = (self.color.x * 255.0) as u32; v[self.memory_start + 4] = (self.color.y * 255.0) as u32;