diff --git a/res/dpr/utility/light_library.glsl b/res/dpr/utility/light_library.glsl
index 1e5e64604110602ed7b41cb79494027149dc4d3e..4e40506eafc62c74c711d14ae669959ef5fa1184 100644
--- a/res/dpr/utility/light_library.glsl
+++ b/res/dpr/utility/light_library.glsl
@@ -282,7 +282,8 @@ vec3 compute_tone_mapping(vec3 lighting)
 
 vec3 apply_local_lighting(vec3 view_position, vec3 surface_position, vec3 surface_normal, Material material)
 {
-    vec3 lighting = material.base_color * light_parameter.ambient;
+    vec3 lighting = material.base_color * light_parameter.ambient; //where ambient is in watts/meter^2 *str
+    lighting += material.emissive; //where emissive is in watts/meter^2 *str
 
     for (uint light = 0; light < light_parameter.count; light++)
     {
diff --git a/res/dpr/utility/material_library.glsl b/res/dpr/utility/material_library.glsl
index 8afb064b84fb21a75c3253dd4257a48115662c9d..1ba7d28330253ebc73a045a032355515b6ab79f9 100644
--- a/res/dpr/utility/material_library.glsl
+++ b/res/dpr/utility/material_library.glsl
@@ -38,11 +38,13 @@
 layout(set = MATERIAL_DESCRIPTOR_SET, binding = 0) uniform sampler2D sampler_color_opacity;
 layout(set = MATERIAL_DESCRIPTOR_SET, binding = 1) uniform sampler2D sampler_material_factor;
 layout(set = MATERIAL_DESCRIPTOR_SET, binding = 2) uniform sampler2D sampler_normal;
+layout(set = MATERIAL_DESCRIPTOR_SET, binding = 3) uniform sampler2D sampler_emissive;
 
 Material lookup_material(vec2 uv_coord)
 {
     vec4 color_opacity = texture(sampler_color_opacity, uv_coord);
     vec4 material_factor = texture(sampler_material_factor, uv_coord);
+    vec3 emissive_color = texture(sampler_emissive, uv_coord).xyz;
 
     Material material;
     material.base_color = color_opacity.xyz;
@@ -50,6 +52,7 @@ Material lookup_material(vec2 uv_coord)
     material.occlusion = material_factor.x;
     material.roughness = material_factor.y;
     material.metallic = material_factor.z;
+    material.emissive = emissive_color;
 
     return material;
 }
diff --git a/res/dpr/utility/material_struct.glsl b/res/dpr/utility/material_struct.glsl
index 16a048144a424ea290435be96ab3ca2e6922661b..4d6d7a73867bd254d7ec89310c2f283978d504a4 100644
--- a/res/dpr/utility/material_struct.glsl
+++ b/res/dpr/utility/material_struct.glsl
@@ -9,6 +9,8 @@ struct Material
     float occlusion;
     float roughness;
     float metallic;
+
+    vec3 emissive;
 };
 
 #endif
\ No newline at end of file
diff --git a/src/scene.cpp b/src/scene.cpp
index f6bae6881d2f79783e854ae2b9a918eb1e2c39b2..561ba946cab001ce054b7ebdec023087bc24e2de 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -51,6 +51,17 @@ bool Scene::create(const SceneConfig& config, lava::device_ptr device, lava::sta
         this->controller_right_alignment = config.controller_right_alignment;
     }
 
+    if (!config.sky_sphere_file.empty())
+    {
+        //NOTE: Need to compute scene bounds for sky-sphere
+        this->reset_transforms();
+
+        if (!this->load_sky_sphere(config.sky_sphere_file, config.sky_sphere_rings, config.sky_sphere_segments, device, staging))
+        {
+            return false;
+        }
+    }
+
     if (this->lights.empty())
     {
         this->create_default_light();
@@ -76,6 +87,7 @@ bool Scene::create(const SceneConfig& config, lava::device_ptr device, lava::sta
         return false;
     }
 
+    //NOTE: Recompute all transfromations for final scene bounds and matrices
     this->reset_transforms();
     
     return true;
@@ -467,13 +479,15 @@ void Scene::set_vertex_input_only_position(lava::graphics_pipeline* pipeline)
 
 void Scene::create_dummy_textures(lava::device_ptr device, lava::staging& staging)
 {
-    this->dummy_diffuse_texture = create_default_texture(device, { 1, 1 }, glm::vec3(1.0, 1.0, 1.0), 1.0);     //Diffuse: (1.0, 1.0, 1.0) Opacity: 1.0
-    this->dummy_specular_texture = create_default_texture(device, { 1, 1 }, glm::vec3(0.0, 1.0, 0.0), 0.0);    //Occlusion: 0.0 Roughness: 1.0 Metallic: 0.0
-    this->dummy_normal_texture = create_default_texture(device, { 1, 1 }, glm::vec3(0.5, 0.5, 0), 0.0);        //Normal: (0.5, 0.5) -> Vertex Normal
+    this->dummy_diffuse_texture = lava::create_default_texture(device, { 1, 1 }, glm::vec3(1.0, 1.0, 1.0), 1.0);  //Diffuse: (1.0, 1.0, 1.0) Opacity: 1.0
+    this->dummy_specular_texture = lava::create_default_texture(device, { 1, 1 }, glm::vec3(0.0, 1.0, 0.0), 0.0); //Occlusion: 0.0 Roughness: 1.0 Metallic: 0.0
+    this->dummy_normal_texture = lava::create_default_texture(device, { 1, 1 }, glm::vec3(0.5, 0.5, 0), 0.0);     //Normal: (0.5, 0.5) -> Vertex Normal
+    this->dummy_emissive_texture = lava::create_default_texture(device, { 1, 1 }, glm::vec3(0.0, 0.0, 0), 0.0);   //Emissive: (0.0, 0.0, 0.0)
 
     staging.add(this->dummy_diffuse_texture);
     staging.add(this->dummy_specular_texture);
     staging.add(this->dummy_normal_texture);
+    staging.add(this->dummy_emissive_texture);
 }
 
 void Scene::create_default_light()
@@ -515,7 +529,7 @@ bool Scene::create_descriptor_layouts(lava::device_ptr device, uint32_t frame_co
     uint32_t descriptor_count = /*Materials*/ this->materials.size() + /*Meshes*/ this->meshes.size() * frame_count + /*Lights*/ frame_count;
     lava::VkDescriptorPoolSizes descriptor_type_count =
     {
-        { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, /*Materials*/ (uint32_t)this->materials.size() * 3 },
+        { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, /*Materials*/ (uint32_t)this->materials.size() * 4 },
         { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, /*Meshes*/ (uint32_t)this->meshes.size() * frame_count + /*Lights*/ frame_count },
         { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, /*Lights*/ frame_count },
     };
@@ -554,6 +568,7 @@ bool Scene::create_descriptor_layouts(lava::device_ptr device, uint32_t frame_co
     this->material_descriptor->add_binding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
     this->material_descriptor->add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
     this->material_descriptor->add_binding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
+    this->material_descriptor->add_binding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
 
     if (!this->material_descriptor->create(device))
     {
@@ -568,7 +583,7 @@ bool Scene::create_descriptor_layouts(lava::device_ptr device, uint32_t frame_co
 bool Scene::create_material_descriptors(lava::device_ptr device)
 {
     std::vector<VkWriteDescriptorSet> descriptor_writes;
-    descriptor_writes.reserve(this->materials.size() * 3);
+    descriptor_writes.reserve(this->materials.size() * 4);
 
     for (SceneMaterial& material : this->materials)
     {
@@ -578,6 +593,7 @@ bool Scene::create_material_descriptors(lava::device_ptr device)
         textures.push_back(material.diffuse);
         textures.push_back(material.specular);
         textures.push_back(material.normal);
+        textures.push_back(material.emissive);
 
         for (uint32_t binding = 0; binding < textures.size(); binding++)
         {
@@ -856,6 +872,123 @@ bool Scene::load_controller(const std::string& file_name, SceneUnit unit, SceneO
     return true;
 }
 
+bool Scene::load_sky_sphere(const std::string& file_name, uint32_t ring_count, uint32_t segment_count, lava::device_ptr device, lava::staging& staging)
+{
+    lava::log()->info("Loading sky-sphere file '{}'", file_name.c_str());
+    lava::texture::ptr sky_sphere = lava::load_texture(device, file_name, VK_FORMAT_UNDEFINED);
+
+    if (sky_sphere == nullptr)
+    {
+        lava::log()->error("Faild to load sky-sphere file '{}'", file_name.c_str());
+
+        return false;
+    }
+
+    staging.add(sky_sphere);
+
+    uint32_t sky_material_index = this->materials.size();
+    SceneMaterial& sky_material = this->materials.emplace_back();
+    sky_material.diffuse = this->dummy_diffuse_texture;    
+    sky_material.specular = this->dummy_specular_texture;
+    sky_material.normal = this->dummy_normal_texture;
+    sky_material.emissive = sky_sphere;
+    
+    if (ring_count < 3)
+    {
+        lava::log()->error("Invalid number of rings for sky-sphere. The number of rings needs to be at least 3!");
+
+        return false;
+    }
+
+    if (segment_count < 3)
+    {
+        lava::log()->error("Invalid number of segments for sky-sphere. The number of segments needs to be at least 3!");
+
+        return false;
+    }
+
+    glm::vec3 center = (this->scene_min + this->scene_max) / 2.0f;
+    float radius = glm::distance(center, this->scene_max) * 10.0f;
+
+    uint32_t vertex_count = ring_count * segment_count;
+    uint32_t index_count = (ring_count - 1) * segment_count * 2;
+    
+    lava::mesh_data geometry;
+    geometry.vertices.reserve(vertex_count);
+    geometry.indices.reserve(index_count);
+
+    for (uint32_t ring = 0; ring < ring_count; ring++)
+    {
+        float coord_v = (float)ring / (float)(ring_count - 1);
+        float latitude = glm::pi<float>() * coord_v;
+
+        for (uint32_t segment = 0; segment < segment_count; segment++)
+        {
+            float coord_u = (float)segment / (float)(segment_count - 1);
+            float longitude = glm::two_pi<float>() * coord_u;
+
+            glm::vec3 position = center;
+            position.x += radius * glm::cos(longitude) * glm::sin(latitude);
+            position.y -= radius * glm::cos(latitude);
+            position.z += radius * glm::sin(longitude) * glm::sin(latitude);
+
+            glm::vec2 uv = glm::vec2(coord_u, 1.0 - coord_v);
+            glm::vec3 normal = glm::normalize(center - position);
+            glm::vec3 tangent = glm::vec3(1.0f, 0.0f, 0.0f);
+          
+            if (glm::abs(glm::dot(normal, glm::vec3(0.0f, 1.0f, 0.0f))) < 0.99f)
+            {
+                tangent = glm::normalize(glm::cross(normal, glm::vec3(0.0f, 1.0f, 0.0f)));
+            }
+
+            lava::vertex vertex;
+            vertex.position = position;
+            vertex.normal = normal;
+            vertex.color = glm::vec4(tangent, 0.0f);
+            vertex.uv = uv;
+
+            geometry.vertices.push_back(vertex);
+        }
+    }
+
+    for (uint32_t ring = 0; ring < (ring_count - 1); ring++)
+    {
+        uint32_t lower_ring_offset = ring * segment_count;
+        uint32_t upper_ring_offset = lower_ring_offset + segment_count;
+
+        for (uint32_t segment = 0; segment < segment_count; segment++)
+        {
+            uint32_t current_index = segment;
+            uint32_t next_index = (segment + 1) % segment_count;
+
+            geometry.indices.push_back(lower_ring_offset + current_index);
+            geometry.indices.push_back(lower_ring_offset + next_index);
+            geometry.indices.push_back(upper_ring_offset + next_index);
+
+            geometry.indices.push_back(upper_ring_offset + next_index);
+            geometry.indices.push_back(upper_ring_offset + current_index);
+            geometry.indices.push_back(lower_ring_offset + current_index);
+        }
+    }
+
+    SceneMesh& sky_mesh = this->meshes.emplace_back();
+    sky_mesh.node_index = INVALID_NODE;
+    sky_mesh.material_index = sky_material_index;
+    sky_mesh.local_min = center; //NOTE: The sky-sphere should not influence the scene bounds
+    sky_mesh.local_max = center;
+    sky_mesh.mesh = lava::make_mesh();
+    sky_mesh.mesh->add_data(geometry);
+
+    if (!sky_mesh.mesh->create(device))
+    {
+        lava::log()->error("Can't create mesh for sky-sphere!");
+
+        return false;
+    }
+
+    return true;
+}
+
 bool Scene::load_nodes(const aiNode* node, float scale, uint32_t base_mesh, SceneNodeIndex parent_index, std::map<std::string, SceneNodeIndex>& node_indices)
 {
     SceneNode scene_node;
@@ -1083,7 +1216,8 @@ bool Scene::load_materials(const aiScene* scene, const std::string& base_name, l
     {
         const aiMaterial* material = scene->mMaterials[index];
         SceneMaterial& scene_material = this->materials.emplace_back();
-        
+        scene_material.emissive = this->dummy_emissive_texture;
+
         if (!this->load_texture(material, base_name, aiTextureType_DIFFUSE, device, staging, scene_material.diffuse))
         {
             scene_material.diffuse = this->dummy_diffuse_texture;
@@ -1354,13 +1488,23 @@ void Scene::apply_transforms()
 
     for (SceneMesh& mesh : this->meshes)
     {
-        const SceneNode& node = this->nodes[mesh.node_index];
+        bool visible = true;
+        glm::mat4 localToWorldSpace = glm::mat4(1.0f);
+        glm::mat4 vectorToWorldSpace = glm::mat4(1.0f);
+
+        if (mesh.node_index >= 0)
+        {
+            const SceneNode& node = this->nodes[mesh.node_index];
+            visible = node.global_visible;
+            localToWorldSpace = node.current_global_transform;
+            vectorToWorldSpace = glm::transpose(glm::inverse(node.current_global_transform));
+        }
 
-        mesh.visible = node.global_visible;
-        mesh.data.localToWorldSpace = node.current_global_transform;
-        mesh.data.vectorToWorldSpace = glm::transpose(glm::inverse(node.current_global_transform));
+        mesh.visible = visible;
+        mesh.data.localToWorldSpace = localToWorldSpace;
+        mesh.data.vectorToWorldSpace = vectorToWorldSpace;
 
-        this->compute_mesh_bounds(mesh, node.current_global_transform);
+        this->compute_mesh_bounds(mesh, localToWorldSpace);
     }
 
     this->compute_scene_bounds();
diff --git a/src/scene.hpp b/src/scene.hpp
index ffbcbf92223e08c3f61a7a6d67461d023e3695f5..847d53ab647a3975041bf8777a5065e1426ee25e 100644
--- a/src/scene.hpp
+++ b/src/scene.hpp
@@ -36,6 +36,10 @@ struct SceneConfig
     std::string controller_left_file;
     std::string controller_right_file;
 
+    std::string sky_sphere_file;                //NOTE: The given file has to be a .hdr file.
+    uint32_t sky_sphere_rings = 16;             //NOTE: Defines the number of rings used in the mesh of the sky-sphere. Needs to be at least 3.
+    uint32_t sky_sphere_segments = 32;          //NOTE: Defines the number of segments used in the mesh of the sky-sphere. Needs to be at least 3.
+
     SceneUnit scene_unit = SCENE_UNIT_METERS;
     SceneUnit controller_left_unit = SCENE_UNIT_METERS;
     SceneUnit controller_right_unit = SCENE_UNIT_METERS;
@@ -96,6 +100,7 @@ struct SceneMaterial
     lava::texture::ptr diffuse;
     lava::texture::ptr specular;
     lava::texture::ptr normal;
+    lava::texture::ptr emissive;
     VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
 };
 
@@ -169,6 +174,7 @@ private:
 
     bool load_scene(const std::string& file_name, SceneUnit unit, SceneOrientation orientation, lava::device_ptr device, lava::staging& staging, std::map<std::string, SceneNodeIndex>& node_indices);
     bool load_controller(const std::string& file_name, SceneUnit unit, SceneOrientation orientation, lava::device_ptr device, lava::staging& staging, SceneNodeIndex& node_index, std::map<std::string, SceneNodeIndex>& node_indices);
+    bool load_sky_sphere(const std::string& file_name, uint32_t ring_count, uint32_t segment_count, lava::device_ptr device, lava::staging& staging);
 
     bool load_nodes(const aiNode* node, float scale, uint32_t base_mesh, SceneNodeIndex parent_index, std::map<std::string, SceneNodeIndex>& node_indices);
     bool load_cameras(const aiScene* scene, float scale, const std::map<std::string, SceneNodeIndex>& node_indices);
@@ -230,6 +236,7 @@ private:
     lava::texture::ptr dummy_diffuse_texture;
     lava::texture::ptr dummy_specular_texture;
     lava::texture::ptr dummy_normal_texture;
+    lava::texture::ptr dummy_emissive_texture;
 };
 
 Scene::Ptr make_scene();
\ No newline at end of file
diff --git a/src/utility/command_parser.cpp b/src/utility/command_parser.cpp
index 44c1294364a09becdde57e29591fb5db2445a2a3..d20aea60144c2dbea7bec8f9625127bd78a2267c 100644
--- a/src/utility/command_parser.cpp
+++ b/src/utility/command_parser.cpp
@@ -37,25 +37,38 @@ bool CommandParser::parse_command(const argh::parser& cmd_line)
 
     for (const std::pair<std::string, std::string>& parameter : cmd_line.params())
     {
-        if (parameter.first == "headset")
+        if (parameter.first == "sky-sphere")
         {
-            if (!this->set_headset(parameter.second))
+            std::string path = parameter.second;
+            std::string extension = path.substr(path.find_last_of('.'));
+
+            if (extension != ".hdr")
+            {
+                std::cout << "Invalid file format for parameter 'sky-sphere'. Only .hdr images supported. Use option --help to get more information." << std::endl;
+            }
+
+            this->sky_sphere_path = path;
+        }
+
+        else if (parameter.first == "scene-unit")
+        {
+            if (!this->set_scene_unit(parameter.second))
             {
                 return false;
             }
         }
 
-        else if (parameter.first == "stereo-strategy")
+        else if (parameter.first == "headset")
         {
-            if (!this->set_stero_strategy(parameter.second))
+            if (!this->set_headset(parameter.second))
             {
                 return false;
             }
         }
 
-        else if (parameter.first == "scene-unit")
+        else if (parameter.first == "stereo-strategy")
         {
-            if (!this->set_scene_unit(parameter.second))
+            if (!this->set_stero_strategy(parameter.second))
             {
                 return false;
             }
@@ -210,6 +223,11 @@ const std::string& CommandParser::get_scene_path() const
     return this->scene_path;
 }
 
+std::optional<std::string> CommandParser::get_sky_sphere_path() const
+{
+    return this->sky_sphere_path;
+}
+
 std::optional<std::string> CommandParser::get_animation_name() const
 {
     return this->animation_name;
@@ -256,6 +274,8 @@ void CommandParser::show_help()
     std::cout << "   depth-peeling-reprojection.exe [Options] [Scene File]" << std::endl;
     std::cout << std::endl;
     std::cout << "Options:" << std::endl;
+    std::cout << "   --sky-sphere={file}                  The sky sphere that should be shown. The given file has to be a .hdr file." << std::endl;
+    std::cout << "                                        If no file is specified, sky stays black." << std::endl;
     std::cout << "   --scene-unit={unit}                  The unit in which the geometry of the scene is defined." << std::endl;
     std::cout << "                                        Options: meters (default), centimeters" << std::endl;
     std::cout << "   --benchmark                          Play animation once and close program after completion." << std::endl;
diff --git a/src/utility/command_parser.hpp b/src/utility/command_parser.hpp
index e60027590817ad22e96cd8880248c9c776885623..8cc7ea9509db65a27dc2c3b222e3e9f96bc9d477 100644
--- a/src/utility/command_parser.hpp
+++ b/src/utility/command_parser.hpp
@@ -24,6 +24,7 @@ public:
     SceneUnit get_scene_unit() const;
 
     const std::string& get_scene_path() const;
+    std::optional<std::string> get_sky_sphere_path() const;
 
     std::optional<std::string> get_animation_name() const;
     std::optional<uint32_t> get_animation_index() const;
@@ -50,6 +51,7 @@ private:
     SceneUnit scene_unit = SCENE_UNIT_METERS;
 
     std::string scene_path = "";
+    std::optional<std::string> sky_sphere_path;
 
     std::optional<std::string> animation_name;
     std::optional<uint32_t> animation_index;
diff --git a/src/vr_application.cpp b/src/vr_application.cpp
index 59230bfa97e774a758186dae1f53bc91406f7cba..57cd864e689b680e77702bb8830621962c498e01 100644
--- a/src/vr_application.cpp
+++ b/src/vr_application.cpp
@@ -298,6 +298,11 @@ bool VRApplication::on_create()
     config.scene_file = this->command_parser.get_scene_path();
     config.scene_unit = this->command_parser.get_scene_unit();
     config.scene_orientation = SCENE_ORIENTATION_RIGHT_HANDED;
+    
+    if (this->command_parser.get_sky_sphere_path().has_value())
+    {
+        config.sky_sphere_file = this->command_parser.get_sky_sphere_path().value();
+    }
 
     if (!this->command_parser.should_benchmark())
     {