diff --git a/shaders/compiled/frag_rt_quad.spv b/shaders/compiled/frag_rt_quad.spv index e1575e8..2c447ea 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 e9baaa8..82944b5 100644 --- a/shaders/rt_quad.frag +++ b/shaders/rt_quad.frag @@ -16,6 +16,10 @@ layout(binding = 0) uniform UniformBufferObject { bool[16] use_geom_shader; } ubo; +// 0 - location for the maximum number of lights referenced per chunk (also will be the invalid memory allocation for pointing to a nonexistant neighbor) +// 1 - location for the max iterations per light +// 2 - diffuse raster samples (2*n + 1) * (2*n + 1) so as to always have at least the central fragment covered +// 3 - diffuse raster size (float, needs to be decoded) layout(binding = 2) buffer SceneInfoBuffer{ uint infos[]; } scene_info; @@ -350,8 +354,8 @@ vec3 diffuse_tracing(uint volume_start, uvec2 raster_pos, vec3 pos, uint f) { vec3 normal = normal_for_facing(f); // diffuse raytracing using a quadratic raster of rays - int raster_half_steps = 0; - float raster_distance = 0.01; + 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); @@ -389,18 +393,21 @@ vec3 clamp_to_volume(uint volume_start, vec3 position) { void main() { vec3 clamped_pos = clamp_to_volume(fragVolumeStart, origPosition); + uvec4 color_roughness = sample_color_from_scene_info(fragVolumeStart, fragRasterPos, facing); + vec3 orig_color_sample = vec3(float(color_roughness.x) / 255.0, float(color_roughness.y) / 255.0, float(color_roughness.z) / 255.0); vec3 color_sum = diffuse_tracing(fragVolumeStart, fragRasterPos, clamped_pos, facing); uint orig_neighbor = sample_neighbor_from_scene_info(fragVolumeStart, fragRasterPos, facing); 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); + float opacity = float(color_roughness.w) / 255.0; if (t.has_hit) { - color_sum += diffuse_tracing(t.end_volume, t.end_raster, t.end_pos, t.end_facing); + color_sum = opacity * color_sum + (1.0 - opacity) * diffuse_tracing(t.end_volume, t.end_raster, t.end_pos, t.end_facing) * orig_color_sample; } else { // Todo: hit sky box - color_sum += vec3(0.0, 0.0, 0.0); + color_sum = opacity * color_sum + (1.0 - opacity) * vec3(0.0, 0.0, 0.0); } } diff --git a/src/app_data.rs b/src/app_data.rs index 91d507a..2464a26 100644 --- a/src/app_data.rs +++ b/src/app_data.rs @@ -60,6 +60,9 @@ pub struct AppData { pub topology: vk::PrimitiveTopology, pub scene_rt_memory_size: u64, + // values passed to shader pub num_lights_per_volume: u32, pub max_iterations_per_light: u32, + pub diffuse_raster_steps: u32, + pub diffuse_raster_size: f32, } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 2e8d209..2ac22ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -180,6 +180,8 @@ 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_size = 0.01; let mut scene_handler = scene::Scene::default(); //load_model::load_model(&mut data)?; diff --git a/src/primitives/cube.rs b/src/primitives/cube.rs index 31a760e..6f7371d 100644 --- a/src/primitives/cube.rs +++ b/src/primitives/cube.rs @@ -10,6 +10,7 @@ pub struct Cube{ pub color: vertex::Vec3, pub tex_coord: vertex::Vec2, pub transparent: bool, + pub roughness: u8, } const CUBE_SIZE: f32 = 0.5; diff --git a/src/scene/empty_volume.rs b/src/scene/empty_volume.rs index 7581195..1357e0a 100644 --- a/src/scene/empty_volume.rs +++ b/src/scene/empty_volume.rs @@ -50,9 +50,9 @@ impl EmptyVolume { self.position[2] + self.size_z > pos[2] && pos[2] >= self.position[2] } - fn check_transparent(cube_result: Option<Cube>, transparent_color: &Vector3<f32>) -> bool { + fn check_transparent(cube_result: Option<Cube>, transparent_color: &Vector3<f32>, transparent_roughness: &u8) -> bool { if let Some(c) = cube_result { - return c.transparent && &c.color == transparent_color + return c.transparent && &c.color == transparent_color && &c.roughness == transparent_roughness } false } @@ -73,9 +73,11 @@ impl EmptyVolume { let query_result = tree.test_element(x_index, y_index, z_index); let mut transparent = false; let mut transparent_color = Vector3 {x: 0.0, y: 0.0, z: 0.0}; + let mut tranparent_roughness = 0; if let Some(c) = query_result.3 { transparent = c.transparent; transparent_color = c.color; + tranparent_roughness = c.roughness; } if !query_result.0 || transparent { @@ -112,7 +114,7 @@ impl EmptyVolume { while z < z_size.max(1) && y < y_size.max(1) { let query_result = tree.test_element(x_index + x_size + 1, y_index + y, z_index + z); check_its += 1; - grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color))) && + grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) && neighbors.get_element(x_index + x_size + 1, y_index + y, z_index + z).is_none(); if query_result.1 > 1 { @@ -159,7 +161,7 @@ impl EmptyVolume { while z < z_size.max(1) && x < x_size.max(1) { let query_result = tree.test_element(x_index + x, y_index + y_size + 1, z_index + z); check_its += 1; - grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color))) && + grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) && neighbors.get_element(x_index + x, y_index + y_size + 1, z_index + z).is_none(); if query_result.1 > 1 { @@ -207,7 +209,7 @@ impl EmptyVolume { while y < y_size.max(1) && x < x_size.max(1) { let query_result = tree.test_element(x_index + x, y_index + y, z_index + z_size + 1); check_its += 1; - grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color))) && + grow &= ((!query_result.0 && !transparent) || (transparent && EmptyVolume::check_transparent(query_result.3, &transparent_color, &tranparent_roughness))) && neighbors.get_element(x_index + x, y_index + y, z_index + z_size + 1).is_none(); if query_result.1 > 1 { @@ -323,7 +325,7 @@ impl EmptyVolume { bottom_elements_num += 1; let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; bottom_colors.push(u8_color); - bottom_roughness.push(128); + bottom_roughness.push(c.roughness); } else { bottom_colors.push(Vector3 { x: 0, y: 0, z: 0 }); @@ -349,7 +351,7 @@ impl EmptyVolume { top_elements_num += 1; let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; top_colors.push(u8_color); - top_roughness.push(128); + top_roughness.push(c.roughness); } else { top_colors.push(Vector3 { x: 0, y: 0, z: 0 }); @@ -376,7 +378,7 @@ impl EmptyVolume { back_elements_num += 1; let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; back_colors.push(u8_color); - back_roughness.push(128); + back_roughness.push(c.roughness); } else { back_colors.push(Vector3 { x: 0, y: 0, z: 0 }); @@ -403,7 +405,7 @@ impl EmptyVolume { front_elements_num += 1; let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; front_colors.push(u8_color); - front_roughness.push(128); + front_roughness.push(c.roughness); } else { front_colors.push(Vector3 { x: 0, y: 0, z: 0 }); @@ -430,7 +432,7 @@ impl EmptyVolume { left_elements_num += 1; let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; left_colors.push(u8_color); - left_roughness.push(128); + left_roughness.push(c.roughness); } else { left_colors.push(Vector3 { x: 0, y: 0, z: 0 }); @@ -457,7 +459,7 @@ impl EmptyVolume { right_elements_num += 1; let u8_color = Vector3 {x: (c.color * 255.0).x.min(255.0).max(0.0) as u8, y: (c.color * 255.0).y.min(255.0).max(0.0) as u8, z: (c.color * 255.0).z.min(255.0).max(0.0) as u8}; right_colors.push(u8_color); - right_roughness.push(128); + right_roughness.push(c.roughness); } else { right_colors.push(Vector3 { x: 0, y: 0, z: 0 }); diff --git a/src/scene/mod.rs b/src/scene/mod.rs index c5703a7..0ed0efb 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -73,6 +73,7 @@ impl Scene { color: vec3(shade, 1.0, shade), tex_coord: vec2(0.0, 0.0), transparent: false, + roughness: 128, }; oct_tree.set_cube(cube.clone()); @@ -85,6 +86,7 @@ impl Scene { color: vec3(1.0, 0.0, 0.0), tex_coord: vec2(0.0, 0.0), transparent: true, + roughness: 32, }; oct_tree.set_cube(cube.clone()); @@ -93,10 +95,11 @@ impl Scene { color: vec3(1.0, 0.0, 0.0), tex_coord: vec2(0.0, 0.0), transparent: true, + roughness: 32, }; oct_tree.set_cube(cube.clone()); - self.point_lights.push(PointLight { pos: vec3(11.0, 11.0, 11.0), color: vec3(0.5, 0.5, 0.5), memory_start: 0 }); + self.point_lights.push(PointLight { pos: vec3(11.0, 11.0, 11.0), color: vec3(1.0, 1.0, 1.0), memory_start: 0 }); self.point_lights.push(PointLight { pos: vec3(9.0, 9.0, 11.0), color: vec3(0.5, 0.5, 0.5), memory_start: 0 }); let empty_volumes: Vec<Rc<RefCell<EmptyVolume>>>; @@ -146,9 +149,11 @@ impl Scene { let index = self.sized_vertices.len(); cube.draw(&data.topology, index, self); - let mut memory_index = 2; + let mut memory_index = 4; // 0 - location for the maximum number of lights referenced per chunk (also will be the invalid memory allocation for pointing to a nonexistant neighbor) // 1 - location for the max iterations per light + // 2 - diffuse raster samples (2*n + 1) * (2*n + 1) so as to always have at least the central fragment covered + // 3 - diffuse raster size for light in &mut self.point_lights { light.memory_start = memory_index; memory_index += light.get_buffer_mem_size() as usize; @@ -168,6 +173,8 @@ impl Scene { println!("Memory size is {} kB, max indes is {}", memory_index * 32 / 8 /1024 + 1, memory_index); let mut volume_vec = vec![data.num_lights_per_volume; memory_index]; volume_vec[1] = data.max_iterations_per_light; + volume_vec[2] = data.diffuse_raster_steps; + volume_vec[3] = u32::from_ne_bytes(data.diffuse_raster_size.to_ne_bytes()); for volume in &empty_volumes { volume_vec = volume.borrow().insert_into_memory(volume_vec, data.num_lights_per_volume, &self.point_lights);