diff --git a/shaders/compiled/rt_compute.spv b/shaders/compiled/rt_compute.spv index 1cbfcfe..289f343 100644 Binary files a/shaders/compiled/rt_compute.spv and b/shaders/compiled/rt_compute.spv differ diff --git a/shaders/rt_compute.comp b/shaders/rt_compute.comp index f1854b4..f0ec353 100644 --- a/shaders/rt_compute.comp +++ b/shaders/rt_compute.comp @@ -250,6 +250,25 @@ void main() { continue; } + if (component_type == 2) { + // handle cone + vec3 size = vec3(uintBitsToFloat(compounds[component_index + 9]), uintBitsToFloat(compounds[component_index + 10]), uintBitsToFloat(compounds[component_index + 11])); + vec3 direction1 = component_rot_mat * vec3(size.x, 0.0, 0.0) / 2.0; + vec3 direction2 = component_rot_mat * vec3(0.0, size.y, 0.0) / 2.0; + vec3 direction3 = component_rot_mat * vec3(0.0, 0.0, size.z) / 2.0; + + vec3 diff = check_pos - component_pos; + float factor1 = dot(direction1, diff) / dot(direction1, direction1); + float factor2 = dot(direction2, diff) / dot(direction2, direction2); + float factor3 = dot(direction3, diff) / dot(direction3, direction3); + render = (-1.0 <= factor1 && factor1 <= 1.0) && (-1.0 <= factor2 && factor2 <= 1.0) && (-1.0 <= factor3 && factor3 <= 1.0); + if (render) { + color = vec3(float(component_color.x) / 255.0, float(component_color.y) / 255.0, float(component_color.z) / 255.0); + break; + } + continue; + } + } //handle excluded shapes @@ -304,6 +323,24 @@ void main() { } continue; } + + if (component_type == 2) { + // handle cone + vec3 size = vec3(uintBitsToFloat(compounds[component_index + 9]), uintBitsToFloat(compounds[component_index + 10]), uintBitsToFloat(compounds[component_index + 11])); + vec3 direction1 = component_rot_mat * vec3(size.x, 0.0, 0.0) / 2.0; + vec3 direction2 = component_rot_mat * vec3(0.0, size.y, 0.0) / 2.0; + vec3 direction3 = component_rot_mat * vec3(0.0, 0.0, size.z) / 2.0; + + vec3 diff = check_pos - component_pos; + float factor1 = dot(direction1, diff) / dot(direction1, direction1); + float factor2 = dot(direction2, diff) / dot(direction2, direction2); + float factor3 = dot(direction3, diff) / dot(direction3, direction3); + render = render && !((-1.0 <= factor1 && factor1 <= 1.0) && (-1.0 <= factor2 && factor2 <= 1.0) && (-1.0 <= factor3 && factor3 <= 1.0)); + if (!render) { + break; + } + continue; + } } if (render) { diff --git a/src/buffer.rs b/src/buffer.rs index f8ee31d..61ce46d 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -313,7 +313,7 @@ pub unsafe fn create_storage_buffers( instance, device, data, - data.compute_task_one_out_buffer_size.max(1), + (size_of::<u32>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1), vk::BufferUsageFlags::STORAGE_BUFFER, vk::MemoryPropertyFlags::DEVICE_LOCAL, )?; @@ -325,7 +325,7 @@ pub unsafe fn create_storage_buffers( instance, device, data, - (size_of::<vertex::SizedVertex>() * 8) as u64 * data.compute_task_one_out_size, + ((size_of::<vertex::SizedVertex>() * 8) as u64 * data.compute_task_one_out_size).max(1), vk::BufferUsageFlags::STORAGE_BUFFER | vk::BufferUsageFlags::VERTEX_BUFFER, vk::MemoryPropertyFlags::DEVICE_LOCAL, )?; @@ -337,7 +337,7 @@ pub unsafe fn create_storage_buffers( instance, device, data, - (size_of::<u32>() * 36) as u64 * data.compute_task_one_out_size, + ((size_of::<u32>() * 36) as u64 * data.compute_task_one_out_size).max(1), vk::BufferUsageFlags::STORAGE_BUFFER | vk::BufferUsageFlags::INDEX_BUFFER, vk::MemoryPropertyFlags::DEVICE_LOCAL, )?; @@ -551,7 +551,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_storage_buffers[i]) .offset(0) - .range(data.compute_task_one_out_buffer_size); + .range((size_of::<u32>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1)); let storage_info = &[info]; let storage_write_compute_out = vk::WriteDescriptorSet::builder() @@ -564,7 +564,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_cuboid_buffers[i]) .offset(0) - .range((size_of::<vertex::SizedVertex>() * 8) as u64 * data.compute_task_one_out_size); + .range(((size_of::<vertex::SizedVertex>() * 8) as u64 * data.compute_task_one_out_size).max(1)); let storage_info = &[info]; let storage_write_compute_cuboid_out = vk::WriteDescriptorSet::builder() @@ -577,7 +577,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_cuboid_index_buffers[i]) .offset(0) - .range((size_of::<u32>() * 36) as u64 * data.compute_task_one_out_size); + .range(((size_of::<u32>() * 36) as u64 * data.compute_task_one_out_size).max(1)); let storage_info = &[info]; let storage_write_compute_cuboid_index_out = vk::WriteDescriptorSet::builder() diff --git a/src/scene/generators.rs b/src/scene/generators.rs index b86a385..3b7f372 100644 --- a/src/scene/generators.rs +++ b/src/scene/generators.rs @@ -4,7 +4,7 @@ use crate::primitives::cube::Cube; use crate::primitives::rec_cuboid::Cuboid; use crate::primitives::drawable::Drawable; use crate::app_data::AppData; -use super::volumetrics::{Cone, ShapeComposition, Sphere}; +use super::volumetrics::{Cone, Rect, ShapeComposition, Sphere}; extern crate rand; use rand::Rng; @@ -118,7 +118,7 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi let tree_ref_two = Rc::new(RefCell::new(oct_tree2.clone())); scene.oct_trees = vec![vec![vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_one.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()]], vec![vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_one.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()]]]; - let mut comp = ShapeComposition::new(128); + let mut comp = ShapeComposition::new(64); comp.included_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 2.0, Vector3 { x: 0, y: 255, z: 0 }, 64, false)))); comp.included_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 2.5, Vector3 { x: 255, y: 0, z: 0 }, 64, false)))); comp.excluded_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 11.5 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 1.5, Vector3 { x: 0, y: 255, z: 0 }, 64, false)))); @@ -129,6 +129,11 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi comp.excluded_shapes.push(Rc::new(RefCell::new(Cone::new(Vector3 { x: 20.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 0.0, 1.5, Vector3 { x: 0.0, y: 10.0, z: 0.0 },Vector3 { x: 0, y: 255, z: 0 }, 64, false)))); scene.volumetrics.push(Rc::new(RefCell::new(comp))); + let mut comp = ShapeComposition::new(64); + comp.included_shapes.push(Rc::new(RefCell::new(Rect::new(Vector3 { x: -5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, Vector3 { x: 5.0, y: 10.0, z: 2.0 },Vector3 { x: 0, y: 0, z: 255 }, 64, false)))); + comp.excluded_shapes.push(Rc::new(RefCell::new(Rect::new(Vector3 { x: -5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, Vector3 { x: 3.0, y: 8.0, z: 2.0 },Vector3 { x: 0, y: 0, z: 255 }, 64, false)))); + scene.volumetrics.push(Rc::new(RefCell::new(comp))); + Ok((cgmath::point3(5.0, 5.0, 10.0))) } diff --git a/src/scene/volumetrics/mod.rs b/src/scene/volumetrics/mod.rs index 7fbdf0b..8e7ade9 100644 --- a/src/scene/volumetrics/mod.rs +++ b/src/scene/volumetrics/mod.rs @@ -1,9 +1,10 @@ use crate::app_data::AppData; -use super::{memorizable::Memorizable, Scene, memorizable::CompoundMemorizable}; +use super::{Scene, memorizable::CompoundMemorizable}; use cgmath::{InnerSpace, Vector3}; use winit::dpi::Size; +use super::memorizable::Memorizable; use std::cell::RefCell; use std::rc::Rc; @@ -23,6 +24,7 @@ pub trait Volumetrics: Memorizable { enum ShapeTypes { SPHERE, CONE, + CUBOID, } @@ -67,7 +69,15 @@ impl Memorizable for ShapeComposition { } fn is_dirty(&self) -> bool { - self.dirty + let mut dirty = self.dirty; + for volumetric in &self.included_shapes { + dirty = dirty || volumetric.borrow().is_dirty(); + } + + for volumetric in &self.excluded_shapes { + dirty = dirty || volumetric.borrow().is_dirty(); + } + dirty } fn insert_into_memory(&mut self, mut v: Vec<u32>, data: &AppData, scene: &Scene) -> Vec<u32> { @@ -185,6 +195,8 @@ impl Memorizable for Sphere { v[self.memory_start + 9] = u32::from_ne_bytes(self.radius.to_ne_bytes()); + self.dirty = false; + v } @@ -202,6 +214,7 @@ impl Volumetrics for Sphere { } fn set_pos(&mut self, p: Vector3<f32>) { + self.dirty = true; self.pos = p; } @@ -210,6 +223,7 @@ impl Volumetrics for Sphere { } fn set_rot(&mut self, p: Vector3<f32>) { + self.dirty = true; self.rot = p; } @@ -290,6 +304,8 @@ impl Memorizable for Cone { v[self.memory_start + 12] = u32::from_ne_bytes(self.direction.y.to_ne_bytes()); v[self.memory_start + 13] = u32::from_ne_bytes(self.direction.z.to_ne_bytes()); + self.dirty = false; + v } @@ -307,6 +323,7 @@ impl Volumetrics for Cone { } fn set_pos(&mut self, p: Vector3<f32>) { + self.dirty = true; self.pos = p; } @@ -315,11 +332,11 @@ impl Volumetrics for Cone { } fn set_rot(&mut self, p: Vector3<f32>) { + self.dirty = true; self.rot = p; } fn get_bbox(&self) -> (Vector3<f32>, Vector3<f32>) { - let max_rad = self.radius1.max(self.radius2); let rot = cgmath::Matrix3::from_angle_x(cgmath::Rad(self.rot.x)) * cgmath::Matrix3::from_angle_y(cgmath::Rad(self.rot.y)) * cgmath::Matrix3::from_angle_z(cgmath::Rad(self.rot.z)); let dir = rot * self.direction; let vec_one; @@ -331,11 +348,11 @@ impl Volumetrics for Cone { } vec_two = dir.cross(vec_one).normalize(); - let pos_1_1 = self.pos + vec_one * max_rad + vec_two * max_rad; - let pos_1_2 = self.pos - vec_one * max_rad - vec_two * max_rad; + let pos_1_1 = self.pos + vec_one * self.radius1 + vec_two * self.radius1; + let pos_1_2 = self.pos - vec_one * self.radius1 - vec_two * self.radius1; - let pos_2_1 = self.pos + vec_one * max_rad + vec_two * max_rad + dir; - let pos_2_2 = self.pos - vec_one * max_rad - vec_two * max_rad + dir; + let pos_2_1 = self.pos + vec_one * self.radius2 + vec_two * self.radius2 + dir; + let pos_2_2 = self.pos - vec_one * self.radius2 - vec_two * self.radius2 + dir; let min = Vector3 {x: pos_1_1.x.min(pos_1_2.x.min(pos_2_1.x.min(pos_2_2.x))), y: pos_1_1.y.min(pos_1_2.y.min(pos_2_1.y.min(pos_2_2.y))), z: pos_1_1.z.min(pos_1_2.z.min(pos_2_1.z.min(pos_2_2.z)))}; let max = Vector3 {x: pos_1_1.x.max(pos_1_2.x.max(pos_2_1.x.max(pos_2_2.x))), y: pos_1_1.y.max(pos_1_2.y.max(pos_2_1.y.max(pos_2_2.y))), z: pos_1_1.z.max(pos_1_2.z.max(pos_2_1.z.max(pos_2_2.z)))}; @@ -347,6 +364,132 @@ impl Volumetrics for Cone { self.transparent } + fn set_transparency(&mut self, transparent: bool) { + self.transparent = transparent; + } +} + + +#[derive(Clone, Debug, PartialEq)] +pub struct Rect { + pos: Vector3<f32>, + rot: Vector3<f32>, + color: Vector3<u8>, // color, either as pure color or texture modifier + transparent: bool, + size: Vector3<f32>, + roughness: u8, + memory_start: usize, + dirty: bool +} + +impl Rect { + pub fn new( + pos: Vector3<f32>, + rot: Vector3<f32>, + size: Vector3<f32>, + color: Vector3<u8>, + roughness: u8, + transparent: bool) -> Self { + Self { pos: pos, rot: rot, color: color, roughness: roughness, memory_start: 0, dirty: true, transparent: transparent, size } + } +} + +impl Memorizable for Rect { + fn get_buffer_mem_size(&self, data: &AppData) -> u32 { + // type, pos, rot, (color + roughness), transparent, radius1, radius2, direction + 1 + 3 + 3 + 1 + 1 + 3 + } + + fn get_prev_buffer_mem_size(&self) -> u32 { + // constant memory size + 1 + 3 + 3 + 1 + 1 + 3 + } + fn is_dirty(&self) -> bool { + self.dirty + } + fn insert_into_memory(&mut self, mut v: Vec<u32>, data: &AppData, scene: &Scene) -> Vec<u32> { + v[self.memory_start] = ShapeTypes::CUBOID as u32; + v[self.memory_start + 1] = u32::from_ne_bytes(self.pos.x.to_ne_bytes()); + v[self.memory_start + 2] = u32::from_ne_bytes(self.pos.y.to_ne_bytes()); + v[self.memory_start + 3] = u32::from_ne_bytes(self.pos.z.to_ne_bytes()); + + v[self.memory_start + 4] = u32::from_ne_bytes(self.rot.x.to_ne_bytes()); + v[self.memory_start + 5] = u32::from_ne_bytes(self.rot.y.to_ne_bytes()); + v[self.memory_start + 6] = u32::from_ne_bytes(self.rot.z.to_ne_bytes()); + + v[self.memory_start + 7] = u32::from_ne_bytes([self.color.x, self.color.y, self.color.z, self.roughness]); + + v[self.memory_start + 8] = self.transparent as u32; + + v[self.memory_start + 9] = u32::from_ne_bytes(self.size.x.to_ne_bytes()); + v[self.memory_start + 10] = u32::from_ne_bytes(self.size.y.to_ne_bytes()); + v[self.memory_start + 11] = u32::from_ne_bytes(self.size.z.to_ne_bytes()); + + self.dirty = false; + + v + } + + fn get_memory_start(&self) -> usize { + self.memory_start + } + fn set_memory_start(&mut self, memory_start: usize) { + self.memory_start = memory_start; + } +} + +impl Volumetrics for Rect { + fn get_pos(&self) -> Vector3<f32> { + self.pos + } + + fn set_pos(&mut self, p: Vector3<f32>) { + self.dirty = true; + self.pos = p; + } + + fn get_rot(&self) -> Vector3<f32> { + self.rot + } + + fn set_rot(&mut self, p: Vector3<f32>) { + self.dirty = true; + self.rot = p; + } + + fn get_bbox(&self) -> (Vector3<f32>, Vector3<f32>) { + let rot = cgmath::Matrix3::from_angle_x(cgmath::Rad(self.rot.x)) * cgmath::Matrix3::from_angle_y(cgmath::Rad(self.rot.y)) * cgmath::Matrix3::from_angle_z(cgmath::Rad(self.rot.z)); + let dir1 = rot * Vector3 { x: self.size.x / 2.0, y: 0.0, z: 0.0 }; + let dir2 = rot * Vector3 { x: 0.0, y: self.size.y / 2.0, z: 0.0 }; + let dir3 = rot * Vector3 { x: 0.0, y: 0.0, z: self.size.z / 2.0 }; + + let pos1 = self.pos - dir1 - dir2 - dir3; + let pos2 = self.pos - dir1 - dir2 + dir3; + let pos3 = self.pos - dir1 + dir2 - dir3; + let pos4 = self.pos - dir1 + dir2 + dir3; + let pos5 = self.pos + dir1 - dir2 - dir3; + let pos6 = self.pos + dir1 - dir2 + dir3; + let pos7 = self.pos + dir1 + dir2 - dir3; + let pos8 = self.pos + dir1 + dir2 + dir3; + + let min = Vector3 { + x: pos1.x.min(pos2.x.min(pos3.x.min(pos4.x.min(pos5.x.min(pos6.x.min(pos7.x.min(pos8.x))))))), + y: pos1.y.min(pos2.y.min(pos3.y.min(pos4.y.min(pos5.y.min(pos6.y.min(pos7.y.min(pos8.y))))))), + z: pos1.z.min(pos2.z.min(pos3.z.min(pos4.z.min(pos5.z.min(pos6.z.min(pos7.z.min(pos8.z))))))) + }; + let max = Vector3 { + x: pos1.x.max(pos2.x.max(pos3.x.max(pos4.x.max(pos5.x.max(pos6.x.max(pos7.x.max(pos8.x))))))), + y: pos1.y.max(pos2.y.max(pos3.y.max(pos4.y.max(pos5.y.max(pos6.y.max(pos7.y.max(pos8.y))))))), + z: pos1.z.max(pos2.z.max(pos3.z.max(pos4.z.max(pos5.z.max(pos6.z.max(pos7.z.max(pos8.z))))))) + }; + + (min, max) + } + + fn is_transparent(&self) -> bool { + self.transparent + } + fn set_transparency(&mut self, transparent: bool) { self.transparent = transparent; }