diff --git a/Cargo.toml b/Cargo.toml
index d8c162f..09a9242 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,7 @@ chrono = { version = "0.4.35", features = ["serde"] }
 anyhow = { version = "1.0.86", features = ["backtrace"] }
 indexmap = { version = "2.2.6", features = ["rayon"] }
 shaderc = { version = "0.8.3", features = ["build-from-source"] }
-rusqlite = { version = "0.32.0", features = ["bundled"] }
+rusqlite = { version = "0.33.0", features = ["bundled"] }
 cgmath = "0.18.0"
 http = "1.1.0"
 iterchunks = "0.5.0"
diff --git a/context/src/core/context.rs b/context/src/core/context.rs
index 1a22959..fae29df 100644
--- a/context/src/core/context.rs
+++ b/context/src/core/context.rs
@@ -60,7 +60,7 @@ impl Context {
     pub fn next_frame<C, F>(&mut self, world: &mut World, mut f: F) -> Result<bool>
     where
         C: Send + Sync + 'static,
-        F: FnMut(&mut World, &mut C, Event) -> Result<()> + Send + Sync + 'static,
+        F: FnMut(&mut World, &mut C, Event<'_>) -> Result<()> + Send + Sync + 'static,
     {
         let render_core = self.render_core.clone();
         let consumer = world.resources.get_mut_unchecked::<C>();
@@ -72,6 +72,7 @@ impl Context {
         ) {
             Ok(res) => {
                 if !res {
+                    self.device().wait_idle()?;
                     return Ok(false);
                 }
             }
@@ -116,18 +117,12 @@ impl Context {
         self.core.queue()
     }
 
-    pub fn controllers(&self) -> &[Arc<RwLock<Controller>>] {
+    pub fn controllers(&self) -> impl Iterator<Item = &Controller> {
         self.presentation.event_system().controllers()
     }
 
-    pub fn active_controller(&self) -> &Option<Arc<RwLock<Controller>>> {
-        self.presentation.event_system().active_controller()
-    }
-
-    pub fn set_active_controller(&mut self, controller: &Arc<RwLock<Controller>>) {
-        self.presentation
-            .event_system_mut()
-            .set_active_controller(controller)
+    pub fn joysticks(&self) -> impl Iterator<Item = &Joystick> {
+        self.presentation.event_system().joysticks()
     }
 }
 
diff --git a/ecs/src/type_map.rs b/ecs/src/type_map.rs
index d0aa76d..3dfb1a1 100644
--- a/ecs/src/type_map.rs
+++ b/ecs/src/type_map.rs
@@ -229,7 +229,7 @@ pub enum ComponentRequestType {
 
 #[derive(Debug)]
 pub struct ComponentNotFoundError {
-    request_type: ComponentRequestType,
+    pub request_type: ComponentRequestType,
 }
 
 impl ComponentNotFoundError {
diff --git a/ecs/src/updates.rs b/ecs/src/updates.rs
index 7b80fc4..638b324 100644
--- a/ecs/src/updates.rs
+++ b/ecs/src/updates.rs
@@ -341,7 +341,7 @@ pub struct ArchetypeInfo {
 }
 
 impl ArchetypeInfo {
-    pub(crate) fn new(entities: Vec<(Entity, Option<String>)>) -> Self {
+    pub fn new(entities: Vec<(Entity, Option<String>)>) -> Self {
         Self { entities }
     }
 
@@ -388,7 +388,7 @@ impl Archetype {
         Ok(())
     }
 
-    pub(crate) fn entities(
+    pub fn entities(
         &self,
     ) -> &IndexMap<Entity, Box<dyn Fn(Entity, &mut World) -> Result<()> + Send + Sync>> {
         &self.entities
@@ -572,12 +572,12 @@ impl Updates {
         }
     }
 
-    pub(crate) fn clear(&mut self) {
-        self.updates.clear();
+    // pub(crate) fn clear(&mut self) {
+    //     self.updates.clear();
 
-        #[cfg(feature = "timings")]
-        self.timings.clear();
-    }
+    //     #[cfg(feature = "timings")]
+    //     self.timings.clear();
+    // }
 
     pub(crate) fn add(&mut self, name: &str, priority: u32, update: Update) -> Result<()> {
         #[cfg(feature = "timings")]
diff --git a/engine/src/engine/engine.rs b/engine/src/engine/engine.rs
index 5060d30..6ad4a52 100644
--- a/engine/src/engine/engine.rs
+++ b/engine/src/engine/engine.rs
@@ -13,9 +13,7 @@ use crate::prelude::*;
 use std::collections::HashMap;
 use std::sync::Arc;
 
-pub struct GuiHandlerRenderer {
-    pub gui_handler: Arc<GuiHandler>,
-}
+pub struct GuiHandlerRenderer;
 
 impl TScene for GuiHandlerRenderer {
     fn process(
@@ -23,9 +21,12 @@ impl TScene for GuiHandlerRenderer {
         buffer_recorder: &mut CommandBufferRecorder<'_>,
         _images: &TargetMode<Vec<Arc<Image>>>,
         indices: &TargetMode<usize>,
-        _world: &World,
+        world: &World,
     ) -> Result<()> {
-        self.gui_handler.process(buffer_recorder, indices)
+        world
+            .resources
+            .get::<Arc<GuiHandler>>()
+            .process(buffer_recorder, indices)
     }
 
     fn resize(
@@ -33,16 +34,17 @@ impl TScene for GuiHandlerRenderer {
         window_width: f32,
         window_height: f32,
         images: &TargetMode<Vec<Arc<Image>>>,
+        world: &World,
     ) -> Result<()> {
-        self.gui_handler
-            .resize(window_width as u32, window_height as u32, images)
+        world.resources.get::<Arc<GuiHandler>>().resize(
+            window_width as u32,
+            window_height as u32,
+            images,
+        )
     }
 }
 
 pub struct Engine {
-    // loads and keeps track of raw data
-    asset_manager: AssetManager,
-
     pub(crate) resource_base_path: String,
 }
 
@@ -171,16 +173,7 @@ impl Engine {
         )?;
 
         let asset_manager = AssetManager::new(&engine_settings)?;
-
-        let gui_handler = GuiHandlerRenderer {
-            gui_handler: GuiHandler::new(create_info.gui_info, &context)?,
-        };
-
-        let engine = Engine {
-            asset_manager,
-
-            resource_base_path: create_info.resource_base_path,
-        };
+        let gui_handler = GuiHandler::new(create_info.gui_info, &context)?;
 
         context
             .render_core_mut()
@@ -189,7 +182,7 @@ impl Engine {
 
         world.resources.insert(context);
 
-        let scene = Scene::new(
+        Scene::new(
             create_info.rasterizer_info,
             create_info.raytracing_info,
             create_info.graphics_info,
@@ -204,11 +197,13 @@ impl Engine {
         direction_mapping.insert(Keycode::Down, GuiDirection::Down);
 
         world.resources.insert(gui_handler);
+        world.resources.insert(GuiHandlerRenderer);
         world.resources.insert(InputMap { direction_mapping });
-
-        world.resources.insert(engine);
+        world.resources.insert(asset_manager);
+        world.resources.insert(Engine {
+            resource_base_path: create_info.resource_base_path,
+        });
         world.resources.insert(engine_settings);
-        world.resources.insert(scene);
 
         world.add_system(Self::main_system::<T>);
 
@@ -254,25 +249,18 @@ impl Engine {
 
 impl Engine {
     fn main_system<T: EventConsumer>(world: &mut World) -> Result<bool> {
-        let gui_handler = world.resources.get_unchecked::<GuiHandlerRenderer>();
+        let gui_handler = world.resources.get_unchecked::<Arc<GuiHandler>>();
         let input_map = world.resources.get_unchecked::<InputMap>();
         let context = world.resources.get_unchecked::<Context>();
 
         let res = world.resources.get_mut_unchecked::<Context>().next_frame(
             world,
             |world, consumer: &mut T, event| {
-                Self::event(
-                    world,
-                    context,
-                    &gui_handler.gui_handler,
-                    input_map,
-                    consumer,
-                    event,
-                )
+                Self::event(world, context, gui_handler, input_map, consumer, event)
             },
         )?;
 
-        gui_handler.gui_handler.process_callbacks()?;
+        gui_handler.process_callbacks()?;
 
         Ok(res)
     }
diff --git a/engine/src/engine/engine_event_handling.rs b/engine/src/engine/engine_event_handling.rs
index cecc6d3..a0b79fb 100644
--- a/engine/src/engine/engine_event_handling.rs
+++ b/engine/src/engine/engine_event_handling.rs
@@ -1,14 +1,9 @@
 use crate::prelude::*;
-
 use anyhow::Result;
-
 use std::collections::HashMap;
-use std::sync::{Arc, RwLock};
-
-// use super::engine_object_data::{EngineObjectAccess, EngineObjectDataHandle};
 
 #[derive(Debug)]
-pub enum EngineEvent {
+pub enum EngineEvent<'a> {
     MouseMotion(u32, u32),
     MouseButtonDown(MouseButton),
     MouseButtonUp(MouseButton),
@@ -17,18 +12,23 @@ pub enum EngineEvent {
     KeyDown(Keycode),
     KeyUp(Keycode),
 
-    ButtonDown(ControllerButton),
-    ButtonUp(ControllerButton),
-    ControllerAxis(ControllerAxis),
+    ControllerButtonDown(&'a Controller, ControllerButton),
+    ControllerButtonUp(&'a Controller, ControllerButton),
+    ControllerAxis(&'a Controller, ControllerAxis),
+    ControllerAdded(&'a Controller),
+    ControllerRemoved(&'a Controller),
 
-    ControllerAdded(Arc<RwLock<Controller>>),
-    ControllerRemoved(Arc<RwLock<Controller>>),
+    JoystickButtonDown(&'a Joystick),
+    JoystickButtonUp(&'a Joystick),
+    JoystickAxis(&'a Joystick),
+    JoystickAdded(&'a Joystick),
+    JoystickRemoved(&'a Joystick),
 
     FileDrop(String),
 }
 
 pub trait EventConsumer: Send + Sync + 'static {
-    fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()>;
+    fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()>;
 }
 
 pub struct InputMap {
@@ -42,7 +42,7 @@ impl Engine {
         gui_handler: &GuiHandler,
         input: &InputMap,
         consumer: &mut T,
-        event: Event,
+        event: Event<'_>,
     ) -> anyhow::Result<()> {
         match event {
             Event::MouseMotion(x, y) => {
@@ -71,15 +71,13 @@ impl Engine {
             Event::TextInput(text) => {
                 Self::text_input(gui_handler, text)?;
             }
-            Event::ControllerButtonDown(button) => {
-                Self::button_down_event(world, gui_handler, consumer, button)?;
+            Event::ControllerButtonDown(controller, button) => {
+                Self::button_down_event(world, gui_handler, consumer, controller, button)?;
             }
-            Event::ControllerButtonUp(button) => {
-                Self::button_up_event(world, consumer, button)?;
+            Event::ControllerButtonUp(controller, button) => {
+                Self::button_up_event(world, consumer, controller, button)?;
             }
             Event::ControllerAxis(controller) => {
-                let controller = controller.read().unwrap();
-
                 if !gui_handler.check_navigatable()? {
                     Self::axis_event(world, consumer, &controller)?
                 } else {
@@ -92,6 +90,23 @@ impl Engine {
             Event::ControllerRemoved(controller) => {
                 Self::controller_removed(world, consumer, controller)?
             }
+
+            Event::JoystickAxis(joystick) => {
+                consumer.event(world, EngineEvent::JoystickAxis(joystick))?
+            }
+            Event::JoystickButtonDown(joystick) => {
+                consumer.event(world, EngineEvent::JoystickButtonDown(joystick))?
+            }
+            Event::JoystickButtonUp(joystick) => {
+                consumer.event(world, EngineEvent::JoystickButtonUp(joystick))?
+            }
+            Event::JoystickAdded(joystick) => {
+                consumer.event(world, EngineEvent::JoystickAdded(joystick))?
+            }
+            Event::JoystickRemoved(joystick) => {
+                consumer.event(world, EngineEvent::JoystickRemoved(joystick))?
+            }
+
             Event::FileDrop(filename) => consumer.event(world, EngineEvent::FileDrop(filename))?,
         }
 
@@ -104,7 +119,7 @@ impl Engine {
     fn controller_added<T: EventConsumer>(
         world: &mut World,
         consumer: &mut T,
-        controller: Arc<RwLock<Controller>>,
+        controller: &Controller,
     ) -> Result<()> {
         consumer.event(world, EngineEvent::ControllerAdded(controller))?;
 
@@ -115,7 +130,7 @@ impl Engine {
     fn controller_removed<T: EventConsumer>(
         world: &mut World,
         consumer: &mut T,
-        controller: Arc<RwLock<Controller>>,
+        controller: &Controller,
     ) -> Result<()> {
         consumer.event(world, EngineEvent::ControllerRemoved(controller))?;
 
@@ -192,9 +207,10 @@ impl Engine {
     fn button_up_event<T: EventConsumer>(
         world: &mut World,
         consumer: &mut T,
+        controller: &Controller,
         button: ControllerButton,
     ) -> Result<()> {
-        consumer.event(world, EngineEvent::ButtonUp(button))?;
+        consumer.event(world, EngineEvent::ControllerButtonUp(controller, button))?;
 
         Ok(())
     }
@@ -204,12 +220,13 @@ impl Engine {
         world: &mut World,
         gui_handler: &GuiHandler,
         consumer: &mut T,
+        controller: &Controller,
         button: ControllerButton,
     ) -> Result<()> {
         if gui_handler.check_navigatable()? {
-            Self::check_button_down(world, gui_handler, consumer, button)?;
+            Self::check_button_down(world, gui_handler, consumer, controller, button)?;
         } else {
-            consumer.event(world, EngineEvent::ButtonDown(button))?;
+            consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?;
         }
 
         Ok(())
@@ -223,7 +240,7 @@ impl Engine {
     ) -> Result<()> {
         consumer.event(
             world,
-            EngineEvent::ControllerAxis(controller.controller_axis()),
+            EngineEvent::ControllerAxis(controller, controller.controller_axis()),
         )?;
 
         Ok(())
@@ -234,6 +251,7 @@ impl Engine {
         world: &mut World,
         gui_handler: &GuiHandler,
         consumer: &mut T,
+        controller: &Controller,
         button: ControllerButton,
     ) -> Result<()> {
         match button {
@@ -313,7 +331,7 @@ impl Engine {
         }
 
         if !gui_handler.accept_custom_selection(button)? {
-            consumer.event(world, EngineEvent::ButtonDown(button))?;
+            consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?;
         }
 
         Ok(())
diff --git a/engine/src/engine/engine_settings.rs b/engine/src/engine/engine_settings.rs
index 34f632e..ec2b9c7 100644
--- a/engine/src/engine/engine_settings.rs
+++ b/engine/src/engine/engine_settings.rs
@@ -205,7 +205,7 @@ impl EngineSettings {
         button: ControllerButton,
     ) -> Result<Option<Arc<Image>>> {
         // TODO: don't check it every time we request a button
-        self.check_controller(context)?;
+        // self.check_controller(context)?;
 
         match self.current_controller_type.read().unwrap().as_ref() {
             Some(controller_type) => Ok(Some(self.controller_button_for(
@@ -347,61 +347,61 @@ impl EngineSettings {
         }
     }
 
-    fn check_controller(&self, context: &Context) -> Result<()> {
-        let active_controller = context.active_controller();
+    // fn check_controller(&self, context: &Context) -> Result<()> {
+    //     let active_controller = context.active_controller();
 
-        match &active_controller {
-            // there is an controller connected
-            Some(controller) => {
-                let controller_name = controller.read().unwrap().name().clone();
+    //     match &active_controller {
+    //         // there is an controller connected
+    //         Some(controller) => {
+    //             let controller_name = controller.read().unwrap().name().clone();
 
-                // predict controller type from name
-                let controller_type = if controller_name.contains("PS4") {
-                    ControllerType::PS4
-                } else if controller_name.contains("Steam") {
-                    ControllerType::Steam
-                } else {
-                    ControllerType::XBox
-                };
+    //             // predict controller type from name
+    //             let controller_type = if controller_name.contains("PS4") {
+    //                 ControllerType::PS4
+    //             } else if controller_name.contains("Steam") {
+    //                 ControllerType::Steam
+    //             } else {
+    //                 ControllerType::XBox
+    //             };
 
-                let mut current_controller_type = self.current_controller_type.write().unwrap();
+    //             let mut current_controller_type = self.current_controller_type.write().unwrap();
 
-                // check if current controller type is set
+    //             // check if current controller type is set
 
-                if current_controller_type.is_some() {
-                    // if controller type is set, check if it is different
-                    if *current_controller_type.as_ref().unwrap() != controller_type {
-                        *current_controller_type = Some(controller_type);
+    //             if current_controller_type.is_some() {
+    //                 // if controller type is set, check if it is different
+    //                 if *current_controller_type.as_ref().unwrap() != controller_type {
+    //                     *current_controller_type = Some(controller_type);
 
-                        let mut map = self.controller_buttons.write().unwrap();
+    //                     let mut map = self.controller_buttons.write().unwrap();
 
-                        // clear map if filled
-                        if !map.is_empty() {
-                            map.clear();
-                        }
-                    }
-                } else {
-                    // set the controller type
-                    *current_controller_type = Some(controller_type);
-                }
-            }
-            // there is no controller connected
-            None => {
-                let mut current_controller_type = self.current_controller_type.write().unwrap();
-                let mut map = self.controller_buttons.write().unwrap();
+    //                     // clear map if filled
+    //                     if !map.is_empty() {
+    //                         map.clear();
+    //                     }
+    //                 }
+    //             } else {
+    //                 // set the controller type
+    //                 *current_controller_type = Some(controller_type);
+    //             }
+    //         }
+    //         // there is no controller connected
+    //         None => {
+    //             let mut current_controller_type = self.current_controller_type.write().unwrap();
+    //             let mut map = self.controller_buttons.write().unwrap();
 
-                // clear current type if set
-                if current_controller_type.is_some() {
-                    *current_controller_type = None;
-                }
+    //             // clear current type if set
+    //             if current_controller_type.is_some() {
+    //                 *current_controller_type = None;
+    //             }
 
-                // clear map if filled
-                if !map.is_empty() {
-                    map.clear();
-                }
-            }
-        }
+    //             // clear map if filled
+    //             if !map.is_empty() {
+    //                 map.clear();
+    //             }
+    //         }
+    //     }
 
-        Ok(())
-    }
+    //     Ok(())
+    // }
 }
diff --git a/engine/src/scene/general/light.rs b/engine/src/scene/general/light.rs
index 2f9ac57..bb89d1c 100644
--- a/engine/src/scene/general/light.rs
+++ b/engine/src/scene/general/light.rs
@@ -5,7 +5,7 @@ use crate::prelude::*;
 use anyhow::Result;
 use utilities::{
     impl_reprc,
-    prelude::cgmath::{vec3, InnerSpace, Rad, Vector3, Zero},
+    prelude::cgmath::{InnerSpace, Rad, Vector3, Zero, vec3},
 };
 
 use utilities::prelude::cgmath::{Matrix4, SquareMatrix};
@@ -127,15 +127,15 @@ pub struct Light {
 }
 
 impl Light {
-    pub(crate) fn point_light(device: &Arc<Device>) -> Result<Light> {
+    pub fn point_light(device: &Arc<Device>) -> Result<Light> {
         Self::new(LightType::Point, device)
     }
 
-    pub(crate) fn directional_light(device: &Arc<Device>) -> Result<Light> {
+    pub fn directional_light(device: &Arc<Device>) -> Result<Light> {
         Self::new(LightType::Direction, device)
     }
 
-    pub(crate) fn spot_light(device: &Arc<Device>) -> Result<Light> {
+    pub fn spot_light(device: &Arc<Device>) -> Result<Light> {
         Self::new(LightType::Spot, device)
     }
 
diff --git a/engine/src/scene/rendering/rasterizer/traditional/mod.rs b/engine/src/scene/rendering/rasterizer/traditional/mod.rs
index 7dcb59e..975d607 100644
--- a/engine/src/scene/rendering/rasterizer/traditional/mod.rs
+++ b/engine/src/scene/rendering/rasterizer/traditional/mod.rs
@@ -205,7 +205,7 @@ impl TraditionalRasterizer {
                             .add_target_info(depth_target)
                             .set_sample_count(sample_count)
                             // swapchain resolve targets
-                            .add_resolve_targets((images, true))
+                            .add_resolve_targets((images, false))
                             // resolved position target
                             .add_resolve_targets(CustomTarget {
                                 usage: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
diff --git a/engine/src/scene/scene/scene_base.rs b/engine/src/scene/scene/scene_base.rs
index 82c7b29..960f798 100644
--- a/engine/src/scene/scene/scene_base.rs
+++ b/engine/src/scene/scene/scene_base.rs
@@ -14,7 +14,6 @@ use super::super::timings::Timings;
 
 use anyhow::Result;
 use ecs::*;
-use rayon::prelude::*;
 use utilities::prelude::cgmath::{Matrix4, Vector3, vec3};
 
 use std::sync::Mutex;
@@ -28,9 +27,6 @@ pub struct Scene {
     screen_width: f32,
     screen_height: f32,
 
-    device: Arc<Device>,
-    queue: Arc<Mutex<Queue>>,
-
     render_type: SceneType,
 
     last_frame: Duration,
@@ -92,9 +88,6 @@ impl Scene {
 
             render_type,
 
-            device: device.clone(),
-            queue: queue.clone(),
-
             frustum_check: None,
 
             renderer,
@@ -486,6 +479,7 @@ impl TScene for Scene {
         window_width: f32,
         window_height: f32,
         images: &TargetMode<Vec<Arc<Image>>>,
+        _world: &World,
     ) -> anyhow::Result<()> {
         self.screen_width = window_width;
         self.screen_height = window_height;
diff --git a/examples/simple_window/src/main.rs b/examples/simple_window/src/main.rs
index 2fbebe9..911ed58 100644
--- a/examples/simple_window/src/main.rs
+++ b/examples/simple_window/src/main.rs
@@ -3,7 +3,7 @@ use std::path::Path;
 use anyhow::Result;
 
 use ecs::*;
-use engine::prelude::*;
+use engine::prelude::{cgmath::vec3, *};
 use skybox::SkyBox;
 
 fn main() -> Result<()> {
@@ -14,6 +14,7 @@ fn main() -> Result<()> {
     world_builder.add_system(GameState::update);
     world_builder.resources.insert(GameState::Startup);
 
+    // let dir = Path::new("C:/Users/M.Huebner/Downloads/Space Skybox Generator/Export");
     let dir = Path::new("/home/michaelh/Sync/skybox");
     SkyBox::new(
         &mut world_builder,
@@ -28,6 +29,12 @@ fn main() -> Result<()> {
         .into_iter(),
     )?;
 
+    let view = world_builder.resources.get_mut::<Scene>().view_mut();
+    let camera = view.camera_mut();
+
+    camera.set_eye_offset(vec3(0.0, 1.0, 0.0));
+    view.update_buffer()?;
+
     world_builder.build().run()
 }
 
@@ -52,7 +59,7 @@ impl GameState {
 }
 
 impl EventConsumer for GameState {
-    fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()> {
+    fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
         match self {
             GameState::Startup => (),
             GameState::Loading => (),
@@ -71,7 +78,7 @@ impl Game {
         Ok(())
     }
 
-    fn event(&mut self, world: &mut World, event: EngineEvent) -> Result<()> {
+    fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
         Ok(())
     }
 }
diff --git a/loading-screen/src/loadingscreen.rs b/loading-screen/src/loadingscreen.rs
index 25e3f4d..3bb3e46 100644
--- a/loading-screen/src/loadingscreen.rs
+++ b/loading-screen/src/loadingscreen.rs
@@ -1,40 +1,60 @@
 use context::prelude::*;
 
-use std::{sync::Arc, thread};
+use std::{
+    sync::{
+        Arc,
+        mpsc::{Receiver, channel},
+    },
+    thread,
+};
 
 use anyhow::Result;
 
-pub struct LoadingScreen;
+pub struct LoadingScreen<T: Send + Sync + 'static> {
+    result: Option<T>,
+    receiver: Receiver<T>,
+}
 
-impl LoadingScreen {
-    pub fn load<T, R, L, G>(
-        context: &Arc<Context>,
-        gui: Option<Arc<G>>,
-        loader: L,
-        on_ready: R,
-    ) -> Result<()>
+impl<T: Send + Sync + 'static> LoadingScreen<T> {
+    pub fn load<R, L, G>(gui: Arc<G>, loader: L) -> Result<Self>
     where
         R: Fn(T) -> Result<()> + Send + Sync + 'static,
         T: Send + Sync + 'static,
         L: FnOnce() -> T + Send + Sync + 'static,
         G: TopLevelGui + TopGui + Send + Sync + 'static,
     {
-        if let Some(gui) = &gui {
-            gui.enable()?;
-        }
+        gui.enable()?;
 
-        let context = context.clone();
+        let (sender, receiver) = channel();
 
         thread::spawn(move || {
-            let result = loader();
-            if let Some(gui) = &gui {
-                gui.disable().unwrap();
-            }
-
-            todo!();
-            // context.push_event(move || (on_ready)(result));
+            let _ = sender.send(loader());
+            let _ = gui.disable();
         });
 
-        Ok(())
+        Ok(Self {
+            result: None,
+            receiver,
+        })
+    }
+
+    pub fn check_ready(&mut self) -> bool {
+        if self.result.is_some() {
+            return true;
+        }
+
+        match self.receiver.try_recv() {
+            Ok(result) => {
+                self.result = Some(result);
+                true
+            }
+            Err(_) => false,
+        }
+    }
+
+    /// Will panic if there is no result.
+    /// Use `check_ready` before calling this.
+    pub fn take_result(mut self) -> T {
+        self.result.take().unwrap()
     }
 }
diff --git a/presentation/src/input/controller.rs b/presentation/src/input/controller.rs
index f212f1f..3c9e196 100644
--- a/presentation/src/input/controller.rs
+++ b/presentation/src/input/controller.rs
@@ -3,7 +3,7 @@ use ui::prelude::*;
 
 use super::controlleraxis::ControllerAxis;
 
-use sdl2;
+use sdl2::{self, GameControllerSubsystem};
 
 #[derive(PartialEq)]
 enum State {
@@ -51,7 +51,7 @@ pub struct Controller {
 
 impl Controller {
     pub fn new(
-        controller_subsystem: &sdl2::GameControllerSubsystem,
+        controller_subsystem: &GameControllerSubsystem,
         id: u32,
         deadzones: ControllerDeadzones,
     ) -> Result<Controller> {
@@ -199,7 +199,7 @@ impl Controller {
         }
     }
 
-    pub fn set_left_x(&mut self, x: f32) {
+    pub(crate) fn set_left_x(&mut self, x: f32) {
         self.controller_axis.left_stick.x = x;
 
         let direction = self.check_direction(
@@ -212,7 +212,7 @@ impl Controller {
         }
     }
 
-    pub fn set_left_y(&mut self, y: f32) {
+    pub(crate) fn set_left_y(&mut self, y: f32) {
         self.controller_axis.left_stick.y = y;
 
         let direction = self.check_direction(
@@ -225,15 +225,15 @@ impl Controller {
         }
     }
 
-    pub fn set_right_x(&mut self, x: f32) {
+    pub(crate) fn set_right_x(&mut self, x: f32) {
         self.controller_axis.right_stick.x = x;
     }
 
-    pub fn set_right_y(&mut self, y: f32) {
+    pub(crate) fn set_right_y(&mut self, y: f32) {
         self.controller_axis.right_stick.y = y;
     }
 
-    pub fn set_left_trigger(&mut self, trigger: f32) {
+    pub(crate) fn set_left_trigger(&mut self, trigger: f32) {
         self.controller_axis.left_trigger = trigger;
 
         let left_trigger = self.check_trigger(trigger, self.last_left_trigger);
@@ -244,7 +244,7 @@ impl Controller {
         }
     }
 
-    pub fn set_right_trigger(&mut self, trigger: f32) {
+    pub(crate) fn set_right_trigger(&mut self, trigger: f32) {
         self.controller_axis.right_trigger = trigger;
 
         let right_trigger = self.check_trigger(trigger, self.last_right_trigger);
diff --git a/presentation/src/input/eventsystem.rs b/presentation/src/input/eventsystem.rs
index 803c554..9ab2187 100644
--- a/presentation/src/input/eventsystem.rs
+++ b/presentation/src/input/eventsystem.rs
@@ -2,7 +2,9 @@ use sdl2;
 use sdl2::EventPump;
 use sdl2::EventSubsystem;
 use sdl2::GameControllerSubsystem;
+use sdl2::JoystickSubsystem;
 use sdl2::Sdl;
+use sdl2::controller::Axis;
 use sdl2::controller::Button;
 use sdl2::event::{Event as SdlEvent, EventType as SdlEventType, WindowEvent};
 use sdl2::keyboard::Keycode;
@@ -10,11 +12,12 @@ use sdl2::mouse::{MouseButton as SdlMouseButton, MouseUtil, MouseWheelDirection}
 
 use ui::prelude::*;
 
-use std::sync::{Arc, RwLock};
+use std::collections::HashMap;
 
 use crate::Result;
 
 use super::controller::{Controller, ControllerDeadzones};
+use super::joystick::Joystick;
 
 fn convert_button(button: Button) -> ControllerButton {
     match button {
@@ -51,7 +54,7 @@ fn convert_button(button: Button) -> ControllerButton {
 }
 
 #[derive(Debug)]
-pub enum Event {
+pub enum Event<'a> {
     // mouse events
     MouseMotion(u32, u32),
     MouseButtonDown(MouseButton),
@@ -64,11 +67,18 @@ pub enum Event {
     TextInput(String),
 
     // controller events
-    ControllerAxis(Arc<RwLock<Controller>>),
-    ControllerButtonDown(ControllerButton),
-    ControllerButtonUp(ControllerButton),
-    ControllerAdded(Arc<RwLock<Controller>>),
-    ControllerRemoved(Arc<RwLock<Controller>>),
+    ControllerAxis(&'a Controller),
+    ControllerButtonDown(&'a Controller, ControllerButton),
+    ControllerButtonUp(&'a Controller, ControllerButton),
+    ControllerAdded(&'a Controller),
+    ControllerRemoved(&'a Controller),
+
+    // joystick events
+    JoystickAxis(&'a Joystick),
+    JoystickButtonDown(&'a Joystick),
+    JoystickButtonUp(&'a Joystick),
+    JoystickAdded(&'a Joystick),
+    JoystickRemoved(&'a Joystick),
 
     // drag'n'drop
     FileDrop(String),
@@ -78,12 +88,13 @@ pub struct EventSystem {
     event_pump: EventPump,
     mouse: MouseUtil,
     controller_subsystem: GameControllerSubsystem,
+    joystick_subsystem: JoystickSubsystem,
     event_subsystem: EventSubsystem,
 
     controller_deadzones: ControllerDeadzones,
 
-    selected_controller: Option<Arc<RwLock<Controller>>>,
-    connected_controllers: Vec<Arc<RwLock<Controller>>>,
+    connected_controllers: HashMap<u32, Controller>,
+    connected_joysticks: HashMap<u32, Joystick>,
 }
 
 impl EventSystem {
@@ -96,12 +107,13 @@ impl EventSystem {
             controller_subsystem: sdl2_context
                 .game_controller()
                 .map_err(|s| anyhow::Error::msg(s))?,
+            joystick_subsystem: sdl2_context.joystick().map_err(|s| anyhow::Error::msg(s))?,
             event_subsystem: sdl2_context.event().map_err(|s| anyhow::Error::msg(s))?,
 
             controller_deadzones: ControllerDeadzones::default(),
 
-            selected_controller: None,
-            connected_controllers: Vec::new(),
+            connected_controllers: HashMap::new(),
+            connected_joysticks: HashMap::new(),
         };
 
         event_system.disable_mouse();
@@ -180,11 +192,9 @@ impl EventSystem {
 
     pub fn poll_events<F, R>(&mut self, mut event_callback: F, mut resize: R) -> Result<bool>
     where
-        F: FnMut(Event) -> Result<()>,
+        F: FnMut(Event<'_>) -> Result<()>,
         R: FnMut(u32, u32) -> Result<()>,
     {
-        let mut controller_axis_changed = false;
-
         for event in self.event_pump.poll_iter() {
             match event {
                 SdlEvent::Window { win_event, .. } => match win_event {
@@ -266,184 +276,78 @@ impl EventSystem {
                         which as u32,
                         self.controller_deadzones.clone(),
                     ) {
-                        let controller = {
-                            if cfg!(debug_assertions) {
-                                println!(
-                                    "Controller added: {}({})",
-                                    controller.name(),
-                                    controller.id()
-                                );
-                            }
+                        if cfg!(debug_assertions) {
+                            println!(
+                                "Controller added: {}({})",
+                                controller.name(),
+                                controller.id()
+                            );
+                        }
 
-                            let arc_controller = Arc::new(RwLock::new(controller));
-                            self.connected_controllers.push(arc_controller.clone());
-
-                            if self.selected_controller.is_none() {
-                                if cfg!(debug_assertions) {
-                                    let contr = arc_controller.read().unwrap();
-
-                                    println!(
-                                        "New active controller: {}({})",
-                                        contr.name(),
-                                        contr.id()
-                                    );
-                                }
-
-                                self.selected_controller = Some(arc_controller.clone());
-                            }
-
-                            arc_controller
-                        };
-
-                        event_callback(Event::ControllerAdded(controller))?;
+                        event_callback(Event::ControllerAdded(&controller))?;
+                        self.connected_controllers
+                            .insert(controller.id(), controller);
                     }
                 }
                 SdlEvent::ControllerDeviceRemoved { which, .. } => {
-                    let removed_controller = {
-                        if self.selected_controller.is_some() {
-                            if cfg!(debug_assertions) {
-                                let contr =
-                                    self.selected_controller.as_ref().unwrap().read().unwrap();
-
-                                println!(
-                                    "Remove active controller: {}({})",
-                                    contr.name(),
-                                    contr.id()
-                                );
-                            }
-
-                            // unwrap is save since we just tested for `is_some()`
-                            if self
-                                .selected_controller
-                                .as_ref()
-                                .unwrap()
-                                .read()
-                                .unwrap()
-                                .id()
-                                == which
-                            {
-                                self.selected_controller = None;
-                            }
+                    if let Some(controller) = self.connected_controllers.remove(&which) {
+                        if cfg!(debug_assertions) {
+                            println!(
+                                "Controller removed: {}({})",
+                                controller.name(),
+                                controller.id()
+                            );
                         }
 
-                        self.connected_controllers
-                            .iter()
-                            .position(|controller_cell| {
-                                let controller = controller_cell.read().unwrap();
-                                controller.id() == which
-                            })
-                            .map(|remove_index| {
-                                let removed_controller =
-                                    self.connected_controllers.swap_remove(remove_index);
-
-                                if cfg!(debug_assertions) {
-                                    let contr = removed_controller.read().unwrap();
-                                    println!(
-                                        "Controller removed: {}({})",
-                                        contr.name(),
-                                        contr.id()
-                                    );
-                                }
-
-                                // if we removed the selected controller, take the controller at the first position if possible
-                                if self.selected_controller.is_none()
-                                    && !self.connected_controllers.is_empty()
-                                {
-                                    if cfg!(debug_assertions) {
-                                        println!(
-                                            "Set active controller: {}",
-                                            self.connected_controllers[0].read().unwrap().name()
-                                        );
-                                    }
-
-                                    self.selected_controller =
-                                        Some(self.connected_controllers[0].clone());
-                                }
-
-                                removed_controller
-                            })
-                    };
-
-                    if let Some(removed_controller) = removed_controller {
-                        event_callback(Event::ControllerRemoved(removed_controller))?;
+                        event_callback(Event::ControllerRemoved(&controller))?;
                     }
                 }
-                // maybe make use of `which`, for support of multiple controllers
-                SdlEvent::ControllerButtonDown {
-                    button,
-                    // which,
-                    ..
-                } => {
-                    // // only call back if the selected controller pressed a button
-                    // match self.selected_controller.read().unwrap().as_ref() {
-                    //     Some(selected_controller) => {
-                    //         if selected_controller.read().unwrap().id() != which {
-                    //             continue;
-                    //         }
-                    //     }
-                    //     None => continue,
-                    // }
-
-                    event_callback(Event::ControllerButtonDown(convert_button(button)))?;
+                SdlEvent::ControllerButtonDown { button, which, .. } => {
+                    event_callback(Event::ControllerButtonDown(
+                        self.connected_controllers.get(&which).unwrap(),
+                        convert_button(button),
+                    ))?;
                 }
-                // maybe make use of `which`, for support of multiple controllers
-                SdlEvent::ControllerButtonUp {
-                    button,
-                    // which,
-                    ..
-                } => {
-                    // // only call back if the selected controller released a button
-                    // match self.selected_controller.read().unwrap().as_ref() {
-                    //     Some(selected_controller) => {
-                    //         if selected_controller.read().unwrap().id() != which {
-                    //             continue;
-                    //         }
-                    //     }
-                    //     None => continue,
-                    // }
-
-                    event_callback(Event::ControllerButtonUp(convert_button(button)))?;
+                SdlEvent::ControllerButtonUp { button, which, .. } => {
+                    event_callback(Event::ControllerButtonUp(
+                        self.connected_controllers.get(&which).unwrap(),
+                        convert_button(button),
+                    ))?;
                 }
                 SdlEvent::ControllerAxisMotion {
-                    axis,
-                    value,
-                    // which,
-                    ..
+                    axis, value, which, ..
                 } => {
-                    if let Some(controller) = self.selected_controller.as_mut() {
-                        let mut controller = controller.write().unwrap();
+                    let controller = self.connected_controllers.get_mut(&which).unwrap();
+                    let normalized = value as f32 * 0.000_030_518;
 
-                        // // only update axis, when selected controller made the change
-                        // if controller.id() != which {
-                        //     continue;
-                        // }
-
-                        // 1 / 32768 = 0,000030518
-                        let normalized = value as f32 * 0.000_030_518;
-
-                        match axis {
-                            sdl2::controller::Axis::LeftX => {
-                                controller.set_left_x(normalized);
-                            }
-                            sdl2::controller::Axis::RightX => {
-                                controller.set_right_x(normalized);
-                            }
-                            sdl2::controller::Axis::LeftY => {
-                                controller.set_left_y(-normalized);
-                            }
-                            sdl2::controller::Axis::RightY => {
-                                controller.set_right_y(normalized);
-                            }
-                            sdl2::controller::Axis::TriggerLeft => {
-                                controller.set_left_trigger(normalized);
-                            }
-                            sdl2::controller::Axis::TriggerRight => {
-                                controller.set_right_trigger(normalized);
-                            }
+                    match axis {
+                        Axis::LeftX => {
+                            controller.set_left_x(normalized);
+                        }
+                        Axis::RightX => {
+                            controller.set_right_x(normalized);
+                        }
+                        Axis::LeftY => {
+                            controller.set_left_y(-normalized);
+                        }
+                        Axis::RightY => {
+                            controller.set_right_y(normalized);
+                        }
+                        Axis::TriggerLeft => {
+                            controller.set_left_trigger(normalized);
+                        }
+                        Axis::TriggerRight => {
+                            controller.set_right_trigger(normalized);
                         }
-
-                        controller_axis_changed = true;
                     }
+
+                    event_callback(Event::ControllerAxis(&*controller))?;
+                }
+                SdlEvent::JoyDeviceAdded { which, .. } => {
+                    let joystick = Joystick::new(&self.joystick_subsystem, which)?;
+
+                    event_callback(Event::JoystickAdded(&joystick))?;
+                    self.connected_joysticks.insert(joystick.id(), joystick);
                 }
                 SdlEvent::DropFile { filename, .. } => {
                     event_callback(Event::FileDrop(filename))?;
@@ -452,58 +356,15 @@ impl EventSystem {
             }
         }
 
-        if controller_axis_changed {
-            if let Some(controller) = &self.selected_controller {
-                let (left_trigger, right_trigger) = {
-                    let mut controller_lock = controller.write().unwrap();
-
-                    (
-                        controller_lock.left_trigger(),
-                        controller_lock.right_trigger(),
-                    )
-                };
-
-                if let Some(right_trigger) = right_trigger {
-                    if right_trigger {
-                        event_callback(Event::ControllerButtonDown(
-                            ControllerButton::RightTrigger,
-                        ))?;
-                    } else {
-                        event_callback(Event::ControllerButtonUp(ControllerButton::RightTrigger))?;
-                    }
-                }
-
-                if let Some(left_trigger) = left_trigger {
-                    if left_trigger {
-                        event_callback(Event::ControllerButtonDown(ControllerButton::LeftTrigger))?;
-                    } else {
-                        event_callback(Event::ControllerButtonUp(ControllerButton::LeftTrigger))?;
-                    }
-                }
-
-                event_callback(Event::ControllerAxis(controller.clone()))?;
-            }
-        }
-
         Ok(true)
     }
 
-    pub fn controllers(&self) -> &[Arc<RwLock<Controller>>] {
-        &self.connected_controllers
+    pub fn controllers(&self) -> impl Iterator<Item = &Controller> {
+        self.connected_controllers.values()
     }
 
-    pub fn active_controller(&self) -> &Option<Arc<RwLock<Controller>>> {
-        &self.selected_controller
-    }
-
-    pub fn set_active_controller(&mut self, controller: &Arc<RwLock<Controller>>) {
-        if let Some(res) = self
-            .connected_controllers
-            .iter()
-            .find(|c| Arc::ptr_eq(c, controller))
-        {
-            self.selected_controller = Some(res.clone());
-        }
+    pub fn joysticks(&self) -> impl Iterator<Item = &Joystick> {
+        self.connected_joysticks.values()
     }
 }
 
diff --git a/presentation/src/input/joystick.rs b/presentation/src/input/joystick.rs
new file mode 100644
index 0000000..592c822
--- /dev/null
+++ b/presentation/src/input/joystick.rs
@@ -0,0 +1,40 @@
+use anyhow::Result;
+use sdl2::JoystickSubsystem;
+
+pub struct Joystick {
+    _sdl2_joystick: sdl2::joystick::Joystick,
+    id: u32,
+    name: String,
+}
+
+impl Joystick {
+    pub fn new(joystick_subsystem: &JoystickSubsystem, id: u32) -> Result<Self> {
+        let sdl2_joystick = joystick_subsystem.open(id)?;
+
+        Ok(Self {
+            name: sdl2_joystick.name(),
+            id,
+            _sdl2_joystick: sdl2_joystick,
+        })
+    }
+
+    pub fn id(&self) -> u32 {
+        self.id
+    }
+
+    pub fn name(&self) -> &str {
+        &self.name
+    }
+}
+
+impl std::fmt::Debug for Joystick {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("Joystick")
+            .field("id", &self.id)
+            .field("name", &self.name)
+            .finish()
+    }
+}
+
+unsafe impl Send for Joystick {}
+unsafe impl Sync for Joystick {}
diff --git a/presentation/src/input/mod.rs b/presentation/src/input/mod.rs
index 72bb1a9..c0f7c5f 100644
--- a/presentation/src/input/mod.rs
+++ b/presentation/src/input/mod.rs
@@ -3,3 +3,4 @@
 pub mod controller;
 pub mod controlleraxis;
 pub mod eventsystem;
+pub mod joystick;
diff --git a/presentation/src/prelude.rs b/presentation/src/prelude.rs
index 5374ff4..4291c32 100644
--- a/presentation/src/prelude.rs
+++ b/presentation/src/prelude.rs
@@ -1,6 +1,6 @@
 pub use crate::traits::*;
 
-pub use crate::{create_render_core, RenderCoreCreateInfo};
+pub use crate::{RenderCoreCreateInfo, create_render_core};
 
 pub use crate::presentationcore::{ApplicationInfo, PresentationBackend, PresentationCore, VRMode};
 
@@ -10,6 +10,7 @@ pub use crate::renderbackend::{Eye, VRTransformations};
 pub use crate::input::{
     controller::{Controller, ControllerDeadzones},
     controlleraxis::ControllerAxis,
+    joystick::Joystick,
 };
 
 // wsi
diff --git a/presentation/src/presentationcore.rs b/presentation/src/presentationcore.rs
index 2f86797..b8e87e5 100644
--- a/presentation/src/presentationcore.rs
+++ b/presentation/src/presentationcore.rs
@@ -113,7 +113,7 @@ impl PresentationCore {
 
     pub fn poll_events<F, R>(&mut self, event_callback: F, resize_event: R) -> Result<bool>
     where
-        F: FnMut(Event) -> Result<()>,
+        F: FnMut(Event<'_>) -> Result<()>,
         R: FnMut(u32, u32) -> Result<()>,
     {
         self.event_system.poll_events(event_callback, resize_event)
diff --git a/presentation/src/renderbackend.rs b/presentation/src/renderbackend.rs
index 74f525a..669335f 100644
--- a/presentation/src/renderbackend.rs
+++ b/presentation/src/renderbackend.rs
@@ -89,7 +89,7 @@ impl SceneHandle {
                 world
                     .resources
                     .get_mut_unchecked::<T>()
-                    .resize(width, height, images)
+                    .resize(width, height, images, world)
             }),
         }
     }
diff --git a/presentation/src/traits.rs b/presentation/src/traits.rs
index ab01f9d..9c66da6 100644
--- a/presentation/src/traits.rs
+++ b/presentation/src/traits.rs
@@ -25,6 +25,7 @@ pub trait TScene: Send + Sync + 'static {
         window_width: f32,
         window_height: f32,
         images: &TargetMode<Vec<Arc<Image>>>,
+        world: &World,
     ) -> Result<()>;
 }
 
diff --git a/skybox/src/lib.rs b/skybox/src/lib.rs
index 09c93e8..ba022e7 100644
--- a/skybox/src/lib.rs
+++ b/skybox/src/lib.rs
@@ -1,6 +1,6 @@
 mod vertex;
 
-use std::{path::PathBuf, sync::Arc};
+use std::{path::PathBuf, sync::Arc, time::Duration};
 
 use anyhow::Result;
 use ecs::*;
@@ -37,6 +37,8 @@ impl<T: ExactSizeIterator<Item = PathBuf>> From<T> for SkyBoxImages {
 }
 
 pub struct SkyBox {
+    enabled: bool,
+
     _cube_map: Arc<Image>,
     cube_buffer: Arc<Buffer<VertexPoint>>,
 
@@ -94,8 +96,24 @@ impl SkyBox {
             .add_descriptor_set_layout(&descriptor_set_layout)
             .build(context.device().clone())?;
 
-        let pipeline =
-            Self::create_pipeline(context, sample_count, &render_target, &pipeline_layout)?;
+        let vertex_shader = ShaderModule::from_slice(
+            context.device().clone(),
+            include_bytes!("../shader/skybox.vert.spv"),
+        )?;
+
+        let fragment_shader = ShaderModule::from_slice(
+            context.device().clone(),
+            include_bytes!("../shader/skybox.frag.spv"),
+        )?;
+
+        let pipeline = Self::create_pipeline(
+            context,
+            sample_count,
+            &render_target,
+            &pipeline_layout,
+            &vertex_shader,
+            &fragment_shader,
+        )?;
 
         let descriptor_pool = DescriptorPool::builder()
             .set_layout(descriptor_set_layout)
@@ -124,17 +142,34 @@ impl SkyBox {
             .map(|t| VertexPoint::new(t[0] as f32, t[1] as f32, t[2] as f32))
             .collect::<Vec<_>>();
 
-        let cube_buffer = Buffer::builder()
-            .set_memory_usage(MemoryUsage::GpuOnly)
-            .set_sharing_mode(VK_SHARING_MODE_EXCLUSIVE)
-            .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
-            .set_data(&cube_mesh)
-            .build(context.device().clone())?;
+        let command_buffer = CommandBuffer::new_primary()
+            .build(context.device().clone(), context.queue().clone())?;
+
+        let cube_buffer = SingleSubmit::builder(&command_buffer, context.queue(), |recorder| {
+            Buffer::builder()
+                .set_memory_usage(MemoryUsage::CpuToGpu)
+                .set_usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)
+                .set_data(&cube_mesh)
+                .build(context.device().clone())?
+                .into_device_local(
+                    recorder,
+                    VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
+                    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
+                    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+                )
+        })
+        .wait_for_timeout(Duration::from_secs(2))
+        .submit()?;
 
         let me = Self {
+            enabled: true,
+
             _cube_map: cube_map,
             cube_buffer,
 
+            vertex_shader,
+            fragment_shader,
+
             render_target,
             pipeline,
             descriptor_set,
@@ -144,6 +179,14 @@ impl SkyBox {
         Ok(())
     }
 
+    pub fn enable(&mut self) {
+        self.enabled = true;
+    }
+
+    pub fn disable(&mut self) {
+        self.enabled = false;
+    }
+
     fn create_render_target(
         context: &Context,
         sample_count: VkSampleCountFlags,
@@ -195,11 +238,18 @@ impl SkyBox {
         sample_count: VkSampleCountFlags,
         render_target: &TargetMode<RenderTarget>,
         pipeline_layout: &Arc<PipelineLayout>,
+        vertex_shader: &Arc<ShaderModule<Vertex>>,
+        fragment_shader: &Arc<ShaderModule<Fragment>>,
     ) -> Result<TargetMode<Arc<Pipeline>>> {
         render_target.execute(|render_target| {
             Pipeline::new_graphics()
+                .set_vertex_shader::<VertexPoint>(vertex_shader.clone())
+                .set_fragment_shader(fragment_shader.clone())
+                .input_assembly(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false)
                 .default_multisample(sample_count)
+                .default_color_blend(vec![VkPipelineColorBlendAttachmentState::default()])
                 .default_rasterization(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE)
+                .whole_area(render_target.width(), render_target.height())
                 .build(
                     context.device().clone(),
                     pipeline_layout,
@@ -218,6 +268,10 @@ impl TScene for SkyBox {
         indices: &TargetMode<usize>,
         _world: &World,
     ) -> Result<()> {
+        if !self.enabled {
+            return Ok(());
+        }
+
         self.render_target
             .chain(indices)
             .chain(&self.pipeline)
@@ -241,10 +295,34 @@ impl TScene for SkyBox {
 
     fn resize(
         &mut self,
-        window_width: f32,
-        window_height: f32,
-        images: &TargetMode<Vec<Arc<Image>>>,
+        _window_width: f32,
+        _window_height: f32,
+        _images: &TargetMode<Vec<Arc<Image>>>,
+        world: &World,
     ) -> Result<()> {
-        todo!()
+        let sample_count = world
+            .resources
+            .get::<EngineSettings>()
+            .graphics_info()?
+            .sample_count;
+
+        let context = world.resources.get::<Context>();
+
+        let pipeline_layout = match &self.pipeline {
+            TargetMode::Mono(p) => p.pipeline_layout().clone(),
+            TargetMode::Stereo(p, _) => p.pipeline_layout().clone(),
+        };
+
+        self.render_target = Self::create_render_target(context, sample_count)?;
+        self.pipeline = Self::create_pipeline(
+            context,
+            sample_count,
+            &self.render_target,
+            &pipeline_layout,
+            &self.vertex_shader,
+            &self.fragment_shader,
+        )?;
+
+        Ok(())
     }
 }