diff --git a/shaders/compiled/rt_compute.spv b/shaders/compiled/rt_compute.spv
index 39f83f3..c0e451b 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 7ec8245..13f9361 100644
--- a/shaders/rt_compute.comp
+++ b/shaders/rt_compute.comp
@@ -200,6 +200,19 @@ void main() {
             uint component_type = compounds[component_index];
             vec3 component_pos = vec3(uintBitsToFloat(compounds[component_index + 1]), uintBitsToFloat(compounds[component_index + 2]), uintBitsToFloat(compounds[component_index + 3]));
             vec3 component_rot = vec3(uintBitsToFloat(compounds[component_index + 4]), uintBitsToFloat(compounds[component_index + 5]), uintBitsToFloat(compounds[component_index + 6]));
+            mat3 component_rot_mat = mat3(
+                    vec3(1.0, 0.0, 0.0),
+                    vec3(0.0, cos(component_rot.x), sin(component_rot.x)),
+                    vec3(0.0, -sin(component_rot.x), cos(component_rot.x))
+                ) * mat3(
+                    vec3(cos(component_rot.y), 0.0, sin(component_rot.y)),
+                    vec3(0.0, 1.0, 0.0),
+                    vec3(-sin(component_rot.y), 0.0, cos(component_rot.y))
+                ) * mat3(
+                    vec3(cos(component_rot.z), sin(component_rot.z), 0.0),
+                    vec3(-sin(component_rot.z), cos(component_rot.y), 0.0),
+                    vec3(0.0, 0.0, 1.0)
+                );
 
             uvec4 component_color = unpack_color(compounds[component_index + 7]);
 
@@ -214,6 +227,27 @@ void main() {
                     color = vec3(float(component_color.x) / 255.0, float(component_color.y) / 255.0, float(component_color.z) / 255.0);
                     break;
                 }
+                continue;
+            }
+
+            if (component_type == 1) {
+                // handle cone
+                float radius1 = uintBitsToFloat(compounds[component_index + 9]);
+                float radius2 = uintBitsToFloat(compounds[component_index + 10]);
+                vec3 direction = component_rot_mat * vec3(uintBitsToFloat(compounds[component_index + 11]), uintBitsToFloat(compounds[component_index + 12]), uintBitsToFloat(compounds[component_index + 13]));
+
+                vec3 diff = check_pos - component_pos;
+                float factor = dot(direction, diff) / dot(direction, direction);
+                
+                vec3 n = diff - factor * direction;
+                float radius = radius1 * (1.0 - factor) + radius2 * factor;
+
+                render = length(n) <= radius && 0 <= factor && factor <= 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;
             }
 
             
@@ -224,7 +258,19 @@ void main() {
             uint component_type = compounds[component_index];
             vec3 component_pos = vec3(uintBitsToFloat(compounds[component_index + 1]), uintBitsToFloat(compounds[component_index + 2]), uintBitsToFloat(compounds[component_index + 3]));
             vec3 component_rot = vec3(uintBitsToFloat(compounds[component_index + 4]), uintBitsToFloat(compounds[component_index + 5]), uintBitsToFloat(compounds[component_index + 6]));
-
+            mat3 component_rot_mat = mat3(
+                    vec3(1.0, 0.0, 0.0),
+                    vec3(0.0, cos(component_rot.x), sin(component_rot.x)),
+                    vec3(0.0, -sin(component_rot.x), cos(component_rot.x))
+                ) * mat3(
+                    vec3(cos(component_rot.y), 0.0, sin(component_rot.y)),
+                    vec3(0.0, 1.0, 0.0),
+                    vec3(-sin(component_rot.y), 0.0, cos(component_rot.y))
+                ) * mat3(
+                    vec3(cos(component_rot.z), sin(component_rot.z), 0.0),
+                    vec3(-sin(component_rot.z), cos(component_rot.y), 0.0),
+                    vec3(0.0, 0.0, 1.0)
+                );
             uvec4 color = unpack_color(compounds[component_index + 7]);
 
             uint transparent = compounds[component_index + 8];
@@ -237,6 +283,26 @@ void main() {
                 if (!render) {
                     break;
                 }
+                continue;
+            }
+
+            if (component_type == 1) {
+                // handle cone
+                float radius1 = uintBitsToFloat(compounds[component_index + 9]);
+                float radius2 = uintBitsToFloat(compounds[component_index + 10]);
+                vec3 direction = component_rot_mat * vec3(uintBitsToFloat(compounds[component_index + 11]), uintBitsToFloat(compounds[component_index + 12]), uintBitsToFloat(compounds[component_index + 13]));
+
+                vec3 diff = check_pos - component_pos;
+                float factor = dot(direction, diff) / dot(direction, direction);
+                
+                vec3 n = diff - factor * direction;
+                float radius = radius1 * (1.0 - factor) + radius2 * factor;
+
+                render = render && !(length(n) <= radius && 0 <= factor && factor <= 1.0);
+                if (!render) {
+                    break;
+                }
+                continue;
             }
         }
 
diff --git a/src/scene/generators.rs b/src/scene/generators.rs
index 32f107e..3aa7c64 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::{ShapeComposition, Sphere};
+use super::volumetrics::{Cone, ShapeComposition, Sphere};
 
 extern crate rand;
 use rand::Rng;
@@ -125,9 +125,8 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi
     scene.volumetrics.push(Rc::new(RefCell::new(comp)));
 
     let mut comp = ShapeComposition::new(64);
-    comp.included_shapes.push(Rc::new(RefCell::new(Sphere::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 }, 2.0, Vector3 { x: 0, y: 255, z: 0 }, 64, false))));
-    comp.included_shapes.push(Rc::new(RefCell::new(Sphere::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 }, 2.5, Vector3 { x: 255, y: 0, z: 0 }, 64, false))));
-    comp.excluded_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 20.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))));    
+    comp.included_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, 2.5, Vector3 { x: 0.0, y: 10.0, z: 0.0 },Vector3 { x: 0, y: 255, z: 0 }, 64, false))));
+    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)));
 
     Ok((cgmath::point3(5.0, 5.0, 10.0)))
diff --git a/src/scene/volumetrics/mod.rs b/src/scene/volumetrics/mod.rs
index e28dbf9..7fbdf0b 100644
--- a/src/scene/volumetrics/mod.rs
+++ b/src/scene/volumetrics/mod.rs
@@ -1,7 +1,7 @@
 use crate::app_data::AppData;
 
 use super::{memorizable::Memorizable, Scene, memorizable::CompoundMemorizable};
-use cgmath::Vector3;
+use cgmath::{InnerSpace, Vector3};
 use winit::dpi::Size;
 
 use std::cell::RefCell;
@@ -22,6 +22,7 @@ pub trait Volumetrics: Memorizable {
 
 enum ShapeTypes {
     SPHERE,
+    CONE,
 }
 
 
@@ -221,6 +222,131 @@ impl Volumetrics for Sphere {
         self.transparent
     }
     
+    fn set_transparency(&mut self, transparent: bool) {
+        self.transparent = transparent;
+    }
+}
+
+
+#[derive(Clone, Debug, PartialEq)]
+pub struct Cone {
+    pos: Vector3<f32>,
+    rot: Vector3<f32>,
+    color: Vector3<u8>, // color, either as pure color or texture modifier
+    transparent: bool,
+    radius1: f32,
+    radius2: f32,
+    direction: Vector3<f32>,
+    roughness: u8,
+    memory_start: usize,
+    dirty: bool
+}
+
+impl Cone {
+    pub fn new(
+        pos: Vector3<f32>,
+        rot: Vector3<f32>, 
+        radius1: f32,
+        radius2: f32,
+        direction: Vector3<f32>,
+        color: Vector3<u8>,
+        roughness: u8,
+        transparent: bool) -> Self {
+        Self { pos: pos, rot: rot, radius1, radius2, color: color, roughness: roughness, memory_start: 0, dirty: true, transparent: transparent, direction }
+    }
+}
+
+impl Memorizable for Cone {
+    fn get_buffer_mem_size(&self, data: &AppData) -> u32 {
+        // type, pos, rot, (color + roughness), transparent, radius1, radius2, direction
+        1 + 3 + 3 + 1 + 1 + 1 + 1 + 3
+    }
+
+    fn get_prev_buffer_mem_size(&self) -> u32 {
+        // constant memory size
+        1 + 3 + 3 + 1 + 1 + 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::CONE 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.radius1.to_ne_bytes());
+        v[self.memory_start + 10] = u32::from_ne_bytes(self.radius2.to_ne_bytes());
+
+        v[self.memory_start + 11] = u32::from_ne_bytes(self.direction.x.to_ne_bytes());
+        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());
+
+        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 Cone {
+    fn get_pos(&self) -> Vector3<f32> {
+        self.pos
+    }
+
+    fn set_pos(&mut self, p: Vector3<f32>) {
+        self.pos = p;
+    }
+
+    fn get_rot(&self) -> Vector3<f32> {
+        self.rot
+    }
+
+    fn set_rot(&mut self, p: Vector3<f32>) {
+        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;
+        let vec_two;
+        if dir.x != 0.0 || dir.z != 0.0 {
+            vec_one = dir.cross(Vector3 { x: 0.0, y: 1.0, z: 0.0 }).normalize();
+        } else {
+            vec_one = dir.cross(Vector3 { x: 1.0, y: 0.0, z: 0.0 }).normalize();
+        }
+        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_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 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)))};
+
+        (min, max)
+    }
+    
+    fn is_transparent(&self) -> bool {
+        self.transparent
+    }
+    
     fn set_transparency(&mut self, transparent: bool) {
         self.transparent = transparent;
     }