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;
     }