diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0a1af49ba57d2c8189f8387d6263cbe884daae70..e2418971bd4e066f2be54f91d059c3a7b19f385e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -750,9 +750,11 @@ message("=======================================================================
                 strategy/depth_peeling_reprojection/dpr_reproject.tese
                 strategy/depth_peeling_reprojection/dpr_reproject.frag
 
-                utility/deferred_local_light.vert
-                utility/deferred_local_light.frag
-                utility/deferred_local_light_with_shadow.frag
+                utility/deferred_lighting.vert
+                utility/deferred_lighting.frag
+                utility/deferred_lighting_shadow.frag
+				utility/deferred_lighting_indirect.frag
+				utility/deferred_lighting_indirect_shadow.frag
 
 				utility/indirect_capture.vert
 				utility/indirect_capture.frag
diff --git a/res/dpr/strategy/multi_view/multi_view_stereo.frag b/res/dpr/strategy/multi_view/multi_view_stereo.frag
index 831480eb0eb659e10894b6395864ca3353dc4aa1..9dd9da3b03a32adb155e1f29ab714d25e745c76a 100644
--- a/res/dpr/strategy/multi_view/multi_view_stereo.frag
+++ b/res/dpr/strategy/multi_view/multi_view_stereo.frag
@@ -5,6 +5,7 @@
 #define MATERIAL_DESCRIPTOR_SET 3
 #define LIGHT_DESCRIPTOR_SET 4
 #define SHADOW_DESCRIPTOR_SET 5
+#define INDIRECT_DESCRIPTOR_SET 6
 
 #include "math_library.glsl"
 #include "material_library.glsl"
diff --git a/res/dpr/utility/deferred_lighting.frag b/res/dpr/utility/deferred_lighting.frag
new file mode 100644
index 0000000000000000000000000000000000000000..c571998b2e6ba1f8f178d4fb29b14154bdf70506
--- /dev/null
+++ b/res/dpr/utility/deferred_lighting.frag
@@ -0,0 +1,6 @@
+#version 450 core
+#extension GL_GOOGLE_include_directive : require
+
+#define LIGHT_DESCRIPTOR_SET 1
+
+#include "deferred_lighting_base.glsl"
\ No newline at end of file
diff --git a/res/dpr/utility/deferred_local_light.vert b/res/dpr/utility/deferred_lighting.vert
similarity index 100%
rename from res/dpr/utility/deferred_local_light.vert
rename to res/dpr/utility/deferred_lighting.vert
diff --git a/res/dpr/utility/deferred_local_light.frag b/res/dpr/utility/deferred_lighting_base.glsl
similarity index 93%
rename from res/dpr/utility/deferred_local_light.frag
rename to res/dpr/utility/deferred_lighting_base.glsl
index 759b2bd6fbb7026eb208cfdd38cf8b91a333728a..ac28b69110b89fa1e1d03dc256db67946d306bdb 100644
--- a/res/dpr/utility/deferred_local_light.frag
+++ b/res/dpr/utility/deferred_lighting_base.glsl
@@ -1,8 +1,3 @@
-#version 450 core
-#extension GL_GOOGLE_include_directive : require
-
-#define LIGHT_DESCRIPTOR_SET 1
-
 #include "math_library.glsl"
 #include "light_library.glsl"
 #include "per_frame.inc"
diff --git a/res/dpr/utility/deferred_lighting_indirect.frag b/res/dpr/utility/deferred_lighting_indirect.frag
new file mode 100644
index 0000000000000000000000000000000000000000..5b03f084e2fbaf51f8ebdca640ad0746c90e2a18
--- /dev/null
+++ b/res/dpr/utility/deferred_lighting_indirect.frag
@@ -0,0 +1,7 @@
+#version 450 core
+#extension GL_GOOGLE_include_directive : require
+
+#define LIGHT_DESCRIPTOR_SET 1
+#define INDIRECT_DESCRIPTOR_SET 3
+
+#include "deferred_lighting_base.glsl"
\ No newline at end of file
diff --git a/res/dpr/utility/deferred_lighting_indirect_shadow.frag b/res/dpr/utility/deferred_lighting_indirect_shadow.frag
new file mode 100644
index 0000000000000000000000000000000000000000..a8a28ae3d8b62591c7957b0b5a14c5fd387e7638
--- /dev/null
+++ b/res/dpr/utility/deferred_lighting_indirect_shadow.frag
@@ -0,0 +1,8 @@
+#version 450 core
+#extension GL_GOOGLE_include_directive : require
+
+#define LIGHT_DESCRIPTOR_SET 1
+#define SHADOW_DESCRIPTOR_SET 3
+#define INDIRECT_DESCRIPTOR_SET 4
+
+#include "deferred_lighting_base.glsl"
\ No newline at end of file
diff --git a/res/dpr/utility/deferred_lighting_shadow.frag b/res/dpr/utility/deferred_lighting_shadow.frag
new file mode 100644
index 0000000000000000000000000000000000000000..f61a91b62072e01a0c439e86a46ba381023d9609
--- /dev/null
+++ b/res/dpr/utility/deferred_lighting_shadow.frag
@@ -0,0 +1,7 @@
+#version 450 core
+#extension GL_GOOGLE_include_directive : require
+
+#define LIGHT_DESCRIPTOR_SET 1
+#define SHADOW_DESCRIPTOR_SET 3
+
+#include "deferred_lighting_base.glsl"
\ No newline at end of file
diff --git a/res/dpr/utility/deferred_local_light_with_shadow.frag b/res/dpr/utility/deferred_local_light_with_shadow.frag
deleted file mode 100644
index c93f5f8d63edba16c20021fabf3ae23228e991e4..0000000000000000000000000000000000000000
--- a/res/dpr/utility/deferred_local_light_with_shadow.frag
+++ /dev/null
@@ -1,47 +0,0 @@
-#version 450 core
-#extension GL_GOOGLE_include_directive : require
-
-#define LIGHT_DESCRIPTOR_SET 1
-#define SHADOW_DESCRIPTOR_SET 3
-
-#include "math_library.glsl"
-#include "light_library.glsl"
-#include "per_frame.inc"
-
-layout(location = 0) out vec4 outColor;
-layout(location = 0) in vec2 inCoord;
-
-layout(set = 0, binding = 0) uniform sampler2D samplerDepthBuffer;
-layout(set = 0, binding = 1) uniform sampler2D samplerColorBuffer;
-layout(set = 0, binding = 2) uniform sampler2D samplerNormalBuffer;
-layout(set = 0, binding = 3) uniform sampler2D samplerMaterialBuffer;
-
-layout(set = 2, binding = 0) uniform PerFrameBuffer
-{
-    PerFrameData per_frame;
-};
-
-void main()
-{
-    float buffer_depth = texture(samplerDepthBuffer, inCoord).x;
-    vec4 buffer_color = texture(samplerColorBuffer, inCoord);
-    vec4 buffer_normal = texture(samplerNormalBuffer, inCoord);
-    vec4 buffer_material = texture(samplerMaterialBuffer, inCoord);
-
-    vec4 surface_position = per_frame.invProjection * (vec4(inCoord * 2.0 - 1.0, buffer_depth, 1.0));
-    surface_position /= surface_position.w;
-    surface_position = per_frame.invView * surface_position;
-
-    vec3 surface_normal = decode_normal(buffer_normal.xy);
-
-    Material material;
-    material.base_color = buffer_color.xyz;
-    material.occlusion = buffer_color.w;
-    material.roughness = buffer_material.x;
-    material.metallic = buffer_material.y;
-    material.emissive.xy = unpackHalf2x16(packUnorm2x16(buffer_normal.zw));
-    material.emissive.z = unpackHalf2x16(packUnorm4x8(buffer_material.zwzw)).x;
-    
-    vec3 lighting = apply_lighting(per_frame.eyePosition, surface_position.xyz, surface_normal, material);
-    outColor = vec4(lighting, 1.0);
-}
\ No newline at end of file
diff --git a/res/dpr/utility/indirect_injection.geom b/res/dpr/utility/indirect_injection.geom
index 58d3a2881b091799336fd7e4e9fc614b4e92936e..386e1677912ee6e075032471ef9083f67b3092b7 100644
--- a/res/dpr/utility/indirect_injection.geom
+++ b/res/dpr/utility/indirect_injection.geom
@@ -28,7 +28,6 @@ void main()
     outNormal = inNormal[0];
     gl_Position = vec4(position.xy, 0.5, 1.0);
     gl_Layer = int(position.z);
-    gl_PointSize = 1.0;
 
     EmitVertex();
     EndPrimitive();
diff --git a/src/scene.cpp b/src/scene.cpp
index b8c0657b1052cdb8f5a37a9a517d4a2653862be1..d7ecaf573f07ab1e7e499b8f6c5f31e0b0fde94a 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -1190,6 +1190,15 @@ bool Scene::load_lights(const aiScene* scene, float scale, const std::map<std::s
             return false;
         }
 
+        float light_scale = 1.0;
+
+        if (light->mType == aiLightSource_DIRECTIONAL)
+        {
+            //NOTE: If the scene is in centimeters assume that directional light intensity is given as watt / cm^2.
+            //      In this case the intensity has to be converted into watt / meter^2
+            light_scale = glm::pow(scale, 1); //It should be a 2 instead of a 1
+        }
+
         SceneLight& scene_light = this->lights.emplace_back();
         scene_light.node_index = node_indices.at(light->mName.C_Str());
         scene_light.initial_position = glm::make_vec3(&light->mPosition.x) * scale;
@@ -1197,7 +1206,7 @@ bool Scene::load_lights(const aiScene* scene, float scale, const std::map<std::s
 
         glsl::LightData& light_data = scene_light.data;
         light_data.position = scene_light.initial_position;
-        light_data.color = glm::make_vec3(&light->mColorDiffuse.r);
+        light_data.color = glm::make_vec3(&light->mColorDiffuse.r) * light_scale;
         light_data.outer_angle = light->mAngleOuterCone;
         light_data.direction = scene_light.initial_direction;
         light_data.inner_angle = light->mAngleInnerCone;
diff --git a/src/scene.hpp b/src/scene.hpp
index 1e490fef3890aae0aee8a958e56c61714cd76ba2..6b9635ecb57a373fb0e8d68e95313a541b9f97ae 100644
--- a/src/scene.hpp
+++ b/src/scene.hpp
@@ -216,7 +216,7 @@ private:
     glm::vec3 scene_min = glm::vec3(0.0f);
     glm::vec3 scene_max = glm::vec3(0.0f);
 
-    const glm::vec3 ambient_color = glm::vec3(0.5f); //NOTE: This factor is used so that the Bistro scene looks okay.
+    const glm::vec3 ambient_color = glm::vec3(0.0f); //NOTE: Indirect should be compute using an indirect cache.
     float exposure = 0.1f;                           //NOTE: This factor is used so that the Bistro scene looks okay.
     bool exposure_changed = false;
 
diff --git a/src/strategy/multi_view_stereo.cpp b/src/strategy/multi_view_stereo.cpp
index 3fe3e1922ec8325009c3f791e31335b2663b1876..afb9be602191bbe55ecabf370bbbba366c2d679e 100644
--- a/src/strategy/multi_view_stereo.cpp
+++ b/src/strategy/multi_view_stereo.cpp
@@ -28,6 +28,13 @@ bool MultiViewStereo::on_create()
         return false;
     }
 
+    this->indirect_cache = make_indirect_cache();
+
+    if (!this->indirect_cache->create(this->get_scene(), IndirectCacheSettings()))
+    {
+        return false;
+    }
+
     if (!this->create_pipeline_layout())
     {
         return false;
@@ -53,6 +60,12 @@ void MultiViewStereo::on_destroy()
         this->shadow_cache->destroy();
     }
 
+    if (this->indirect_cache != nullptr)
+    {
+        this->indirect_cache->destroy();
+        this->indirect_computed = false;
+    }
+
     if (this->pipeline_layout != nullptr)
     {
         this->pipeline_layout->destroy();
@@ -93,6 +106,12 @@ bool MultiViewStereo::on_render(VkCommandBuffer command_buffer, lava::index fram
 {
     this->get_headset()->submit_metadata(FrameMetadata());
 
+    if (!this->indirect_computed)
+    {
+        this->indirect_cache->compute_indirect(command_buffer, frame);
+        this->indirect_computed = true;
+    }
+
     this->get_pass_timer()->begin_pass(command_buffer, "shadow");
     this->shadow_cache->compute_shadow(command_buffer, frame);
     this->get_pass_timer()->end_pass(command_buffer);
@@ -228,6 +247,7 @@ bool MultiViewStereo::create_pipeline_layout()
     this->pipeline_layout->add(this->get_scene()->get_material_descriptor());
     this->pipeline_layout->add(this->get_scene()->get_light_descriptor());
     this->pipeline_layout->add(this->shadow_cache->get_descriptor());
+    this->pipeline_layout->add(this->indirect_cache->get_descriptor());
     
     if (!this->pipeline_layout->create(this->get_device()))
     {
@@ -411,6 +431,7 @@ void MultiViewStereo::pipeline_function(VkCommandBuffer command_buffer)
     this->pipeline_layout->bind(command_buffer, this->get_stereo_transform()->get_descriptor_set(EYE_RIGHT, frame_index), 1);
     this->pipeline_layout->bind(command_buffer, this->get_scene()->get_light_descriptor_set(frame_index), 4);
     this->pipeline_layout->bind(command_buffer, this->shadow_cache->get_descriptor_set(), 5);
+    this->pipeline_layout->bind(command_buffer, this->indirect_cache->get_descriptor_set(), 6);
 
     const std::vector<SceneMaterial>& materials = this->get_scene()->get_materials();
 
diff --git a/src/strategy/multi_view_stereo.hpp b/src/strategy/multi_view_stereo.hpp
index 895a6fb387f1baa0a180969b0b2b5b0d2c4682ca..c597d223efa85804690c0460c032815b0f0d0aba 100644
--- a/src/strategy/multi_view_stereo.hpp
+++ b/src/strategy/multi_view_stereo.hpp
@@ -4,6 +4,7 @@
 
 #include "stereo_strategy.hpp"
 #include "utility/shadow_cache.hpp"
+#include "utility/indirect_cache.hpp"
 
 class MultiViewStereo final : public StereoStrategy
 {
@@ -37,6 +38,9 @@ private:
     VkPhysicalDeviceMultiviewFeatures features;
 
     ShadowCache::Ptr shadow_cache;
+    IndirectCache::Ptr indirect_cache;
+    bool indirect_computed = false;
+
     lava::pipeline_layout::ptr pipeline_layout;
 
     lava::graphics_pipeline::ptr pipeline;
diff --git a/src/strategy/native_stereo_deferred.cpp b/src/strategy/native_stereo_deferred.cpp
index d8e5b1bac31823e1fa07caa0daddbc6e55373b8e..1bad6edf476267abf96b8a977405467fe6336737 100644
--- a/src/strategy/native_stereo_deferred.cpp
+++ b/src/strategy/native_stereo_deferred.cpp
@@ -10,6 +10,13 @@ bool NativeStereoDeferred::on_create()
         return false;
     }
 
+    this->indirect_cache = make_indirect_cache();
+
+    if (!this->indirect_cache->create(this->get_scene(), IndirectCacheSettings()))
+    {
+        return false;
+    }
+
     if (!this->create_pipeline_layout())
     {
         return false;
@@ -45,6 +52,12 @@ void NativeStereoDeferred::on_destroy()
         this->shadow_cache->destroy();
     }
 
+    if (this->indirect_cache != nullptr)
+    {
+        this->indirect_cache->destroy();
+        this->indirect_computed = false;
+    }
+
     if (this->pipeline_layout != nullptr)
     {
         this->pipeline_layout->destroy();
@@ -83,6 +96,12 @@ bool NativeStereoDeferred::on_render(VkCommandBuffer command_buffer, lava::index
 {
     this->get_headset()->submit_metadata(FrameMetadata());
 
+    if (!this->indirect_computed)
+    {
+        this->indirect_cache->compute_indirect(command_buffer, frame);
+        this->indirect_computed = true;
+    }
+
     this->get_pass_timer()->begin_pass(command_buffer, "shadow");
     this->shadow_cache->compute_shadow(command_buffer, frame);
     this->get_pass_timer()->end_pass(command_buffer);
@@ -145,7 +164,7 @@ bool NativeStereoDeferred::create_render_pass(Eye eye)
 {
     GeometryBuffer::Ptr geometry_buffer = make_geometry_buffer();
 
-    if (!geometry_buffer->create(this->get_headset()->get_framebuffer(eye), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, this->get_stereo_transform()->get_descriptor(), this->get_scene(), this->shadow_cache))
+    if (!geometry_buffer->create(this->get_headset()->get_framebuffer(eye), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, this->get_stereo_transform()->get_descriptor(), this->get_scene(), this->shadow_cache, this->indirect_cache))
     {
         lava::log()->error("Can't create geometry buffer for native stereo deferred!");
 
diff --git a/src/strategy/native_stereo_deferred.hpp b/src/strategy/native_stereo_deferred.hpp
index 0bb1bc86f2e5c94613b8536910a73a7f772398f6..df8c17dc57d6a757897622eebfceaa10e31c9fff 100644
--- a/src/strategy/native_stereo_deferred.hpp
+++ b/src/strategy/native_stereo_deferred.hpp
@@ -5,6 +5,7 @@
 #include "stereo_strategy.hpp"
 #include "utility/geometry_buffer.hpp"
 #include "utility/shadow_cache.hpp"
+#include "utility/indirect_cache.hpp"
 
 struct NativeStereoDeferredPass
 {
@@ -40,6 +41,9 @@ private:
 
 private:
     ShadowCache::Ptr shadow_cache;
+    IndirectCache::Ptr indirect_cache;
+    bool indirect_computed = false;
+
     lava::pipeline_layout::ptr pipeline_layout;
     std::array<NativeStereoDeferredPass, 2> eye_passes;
 };
diff --git a/src/strategy/native_stereo_forward.cpp b/src/strategy/native_stereo_forward.cpp
index 6a6d8709c93a085b68c2e128360db47a4ba0987c..5b00e4b1008ce423d517ce5f9c69e1fb7faf61dc 100644
--- a/src/strategy/native_stereo_forward.cpp
+++ b/src/strategy/native_stereo_forward.cpp
@@ -12,7 +12,7 @@ bool NativeStereoForward::on_create()
 
     this->indirect_cache = make_indirect_cache();
 
-    if (!this->indirect_cache->create(this->get_scene(), IndirectSettings()))
+    if (!this->indirect_cache->create(this->get_scene(), IndirectCacheSettings()))
     {
         return false;
     }
@@ -55,6 +55,7 @@ void NativeStereoForward::on_destroy()
     if (this->indirect_cache != nullptr)
     {
         this->indirect_cache->destroy();
+        this->indirect_computed = false;
     }
 
     if (this->pipeline_layout != nullptr)
diff --git a/src/utility/geometry_buffer.cpp b/src/utility/geometry_buffer.cpp
index d05b06b9066b4071a01d0b7e52b4d1df74e4af14..2482ef4d192740d799de857c43bde4c06bfc45df 100644
--- a/src/utility/geometry_buffer.cpp
+++ b/src/utility/geometry_buffer.cpp
@@ -1,12 +1,13 @@
 #include "geometry_buffer.hpp"
 
-bool GeometryBuffer::create(lava::image::ptr output_image, VkImageLayout output_layout, lava::descriptor::ptr per_frame_descriptor, Scene::Ptr scene, ShadowCache::Ptr shadow_cache)
+bool GeometryBuffer::create(lava::image::ptr output_image, VkImageLayout output_layout, lava::descriptor::ptr per_frame_descriptor, Scene::Ptr scene, ShadowCache::Ptr shadow_cache, IndirectCache::Ptr indirect_cache)
 {
     lava::device_ptr device = output_image->get_device();
     glm::uvec2 size = output_image->get_size();
 
     this->scene = scene;
     this->shadow_cache = shadow_cache;
+    this->indirect_cache = indirect_cache;
     this->output_image = output_image;
     this->output_layout = output_layout;
 
@@ -482,6 +483,11 @@ bool GeometryBuffer::create_pipeline(lava::device_ptr device, lava::descriptor::
         this->pipeline_layout->add(this->shadow_cache->get_descriptor()); //descriptor-set index 3: shadow-information
     }
 
+    if (this->indirect_cache != nullptr)
+    {
+        this->pipeline_layout->add(this->indirect_cache->get_descriptor()); //descriptor-set index 3 or 4: shadow-information
+    }
+
     if (!this->pipeline_layout->create(device))
     {
         lava::log()->error("Can't create pipeline layout for deferred local light pass!");
@@ -504,31 +510,32 @@ bool GeometryBuffer::create_pipeline(lava::device_ptr device, lava::descriptor::
     this->pipeline->set_input_assembly_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
     this->pipeline->add_color_blend_attachment(output_blend_state);
 
-    if (!this->pipeline->add_shader(lava::file_data("dpr/binary/deferred_local_light_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT))
+    if (!this->pipeline->add_shader(lava::file_data("dpr/binary/deferred_lighting_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT))
     {
-        lava::log()->error("Can't load vertex shader for deferred local light pass!");
+        lava::log()->error("Can't load vertex shader for deferred lighting pass!");
 
         return false;
     }
 
-    if (this->shadow_cache != nullptr)
+    std::string shader_name = "dpr/binary/deferred_lighting";
+
+    if (this->indirect_cache != nullptr)
     {
-        if (!this->pipeline->add_shader(lava::file_data("dpr/binary/deferred_local_light_with_shadow_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT))
-        {
-            lava::log()->error("Can't load fragment shader for deferred local light with shadow pass!");
+        shader_name += "_indirect";
+    }
 
-            return false;
-        }
+    if (this->shadow_cache != nullptr)
+    {
+        shader_name += "_shadow";
     }
 
-    else
+    shader_name += "_fragment.spirv";
+
+    if (!this->pipeline->add_shader(lava::file_data(shader_name.c_str()), VK_SHADER_STAGE_FRAGMENT_BIT))
     {
-        if (!this->pipeline->add_shader(lava::file_data("dpr/binary/deferred_local_light_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT))
-        {
-            lava::log()->error("Can't load fragment shader for deferred local light without shadow pass!");
+        lava::log()->error("Can't load fragment shader for deferred lighting pass!");
 
-            return false;
-        }
+        return false;
     }
 
     this->pipeline->on_process = [this](VkCommandBuffer command_buffer)
@@ -553,9 +560,20 @@ void GeometryBuffer::pipline_function(VkCommandBuffer command_buffer)
     this->pipeline_layout->bind(command_buffer, this->buffer_descriptor_set, 0);
     this->pipeline_layout->bind(command_buffer, this->scene->get_light_descriptor_set(this->frame), 1);
 
-    if (this->shadow_cache != nullptr)
+    if (this->shadow_cache != nullptr && this->indirect_cache != nullptr)
     {
         this->pipeline_layout->bind(command_buffer, this->shadow_cache->get_descriptor_set(), 3);
+        this->pipeline_layout->bind(command_buffer, this->indirect_cache->get_descriptor_set(), 4);
+    }
+
+    else if (this->shadow_cache != nullptr)
+    {
+        this->pipeline_layout->bind(command_buffer, this->shadow_cache->get_descriptor_set(), 3);
+    }
+
+    else if (this->indirect_cache != nullptr)
+    {
+        this->pipeline_layout->bind(command_buffer, this->indirect_cache->get_descriptor_set(), 4);
     }
 
     vkCmdDraw(command_buffer, 4, 1, 0, 0); //draw fullscreen quad
diff --git a/src/utility/geometry_buffer.hpp b/src/utility/geometry_buffer.hpp
index d9a89437a6a47eb4a4da7c794488431a86b153e4..735e3bd86316c5516b02a08318fa9da4e3fe91da 100644
--- a/src/utility/geometry_buffer.hpp
+++ b/src/utility/geometry_buffer.hpp
@@ -60,6 +60,7 @@
 
 #include "scene.hpp"
 #include "shadow_cache.hpp"
+#include "indirect_cache.hpp"
 
 class GeometryBuffer
 {
@@ -69,7 +70,7 @@ public:
 public:
     GeometryBuffer() = default;
 
-    bool create(lava::image::ptr output_image, VkImageLayout output_layout, lava::descriptor::ptr per_frame_descriptor, Scene::Ptr scene, ShadowCache::Ptr shadow_cache = {});
+    bool create(lava::image::ptr output_image, VkImageLayout output_layout, lava::descriptor::ptr per_frame_descriptor, Scene::Ptr scene, ShadowCache::Ptr shadow_cache = {}, IndirectCache::Ptr indirect_cache = {});
     void destroy();
     
     // Apply local lighting based on the perspective defined by the per_frame_descriptor_set and write the results into the output image
@@ -106,6 +107,7 @@ private:
 private:
     Scene::Ptr scene;
     ShadowCache::Ptr shadow_cache;
+    IndirectCache::Ptr indirect_cache;
     uint32_t frame = 0;
 
     lava::image::ptr output_image;
diff --git a/src/utility/indirect_cache.cpp b/src/utility/indirect_cache.cpp
index 6770fbf7857c9e38d81760c1d3ad0d7f22fa5a72..1eb521f840a6dd2e8f71056f4ce6973883d7fd32 100644
--- a/src/utility/indirect_cache.cpp
+++ b/src/utility/indirect_cache.cpp
@@ -8,10 +8,13 @@ namespace glsl
 #include "res/dpr/data/indirect_data.inc"
 }
 
-bool IndirectCache::create(Scene::Ptr scene, const IndirectSettings& settings)
+bool IndirectCache::create(Scene::Ptr scene, const IndirectCacheSettings& settings)
 {
     lava::device_ptr device = scene->get_light_descriptor()->get_device();
 
+	this->scene = scene;
+    this->settings = settings;
+
     this->compute_domain(scene, settings);
 
     if (!this->create_buffers(device, settings))
@@ -64,15 +67,118 @@ bool IndirectCache::create(Scene::Ptr scene, const IndirectSettings& settings)
         return false;
     }
 
-	this->scene = scene;
-    this->settings = settings;
-
     return true;
 }
 
 void IndirectCache::destroy()
 {
-    //TODO: ....
+    lava::device_ptr device = this->scene->get_light_descriptor()->get_device();
+
+    if (this->capture_pipeline != nullptr)
+    {
+        this->capture_pipeline->destroy();
+    }
+
+    if (this->injection_pipeline != nullptr)
+    {
+        this->capture_pipeline->destroy();
+    }
+
+    if (this->propagation_pipeline != nullptr)
+    {
+        this->propagation_pipeline->destroy();
+    }
+
+    if (this->capture_pass != nullptr)
+    {
+        this->capture_pass->destroy();
+    }
+
+    if (this->injection_pass != nullptr)
+    {
+        this->injection_pass->destroy();
+    }
+
+    if (this->capture_layout != nullptr)
+    {
+        this->capture_layout->destroy();
+    }
+
+    if (this->injection_layout != nullptr)
+    {
+        this->injection_layout->destroy();
+    }
+
+    if (this->propagation_layout != nullptr)
+    {
+        this->propagation_layout->destroy();
+    }
+
+    if (this->indirect_descriptor != nullptr)
+    {
+        this->indirect_descriptor->free(this->indirect_descriptor_set, this->descriptor_pool->get());
+        this->indirect_descriptor->destroy();
+    }
+
+    if (this->injection_descriptor != nullptr)
+    {
+        this->injection_descriptor->free(this->injection_descriptor_set, this->descriptor_pool->get());
+        this->injection_descriptor->destroy();
+    }
+
+    if (this->propagation_descriptor != nullptr)
+    {
+        this->propagation_descriptor->free(this->propagation_descriptor_set[0], this->descriptor_pool->get());
+        this->propagation_descriptor->free(this->propagation_descriptor_set[1], this->descriptor_pool->get());
+        this->propagation_descriptor->destroy();
+    }
+
+    if (this->descriptor_pool != nullptr)
+    {
+        this->descriptor_pool->destroy();
+    }
+
+    if (this->capture_depth_image != nullptr)
+    {
+        this->capture_depth_image->destroy();
+    }
+
+    if (this->capture_flux_image != nullptr)
+    {
+        this->capture_flux_image->destroy();
+    }
+
+    if (this->capture_normal_image != nullptr)
+    {
+        this->capture_normal_image->destroy();
+    }
+
+    if (this->domain_buffer != nullptr)
+    {
+        this->domain_buffer->destroy();
+    }
+
+    vkDestroySampler(device->get(), this->indirect_sampler, lava::memory::alloc());
+    vkDestroySampler(device->get(), this->injection_sampler, lava::memory::alloc());
+
+    for (uint32_t index = 0; index < distribution_red_image.size(); index++)
+    {
+        vkDestroyImageView(device->get(), distribution_red_image_view[index], lava::memory::alloc());
+        vkDestroyImageView(device->get(), distribution_green_image_view[index], lava::memory::alloc());
+        vkDestroyImageView(device->get(), distribution_blue_image_view[index], lava::memory::alloc());
+
+        vkDestroyImageView(device->get(), distribution_red_image_array_view[index], lava::memory::alloc());
+        vkDestroyImageView(device->get(), distribution_green_image_array_view[index], lava::memory::alloc());
+        vkDestroyImageView(device->get(), distribution_blue_image_array_view[index], lava::memory::alloc());
+
+        vkDestroyImage(device->get(), distribution_red_image[index], lava::memory::alloc());
+        vkDestroyImage(device->get(), distribution_green_image[index], lava::memory::alloc());
+        vkDestroyImage(device->get(), distribution_blue_image[index], lava::memory::alloc());
+
+        vmaFreeMemory(device->get_allocator()->get(), distribution_red_image_memory[index]);
+        vmaFreeMemory(device->get_allocator()->get(), distribution_green_image_memory[index]);
+        vmaFreeMemory(device->get_allocator()->get(), distribution_blue_image_memory[index]);
+    }
 }
 
 void IndirectCache::compute_indirect(VkCommandBuffer command_buffer, lava::index frame)
@@ -234,12 +340,12 @@ VkDescriptorSet IndirectCache::get_descriptor_set() const
     return this->indirect_descriptor_set;
 }
 
-const IndirectSettings& IndirectCache::get_settings() const
+const IndirectCacheSettings& IndirectCache::get_settings() const
 {
     return this->settings;
 }
 
-void IndirectCache::compute_domain(Scene::Ptr scene, const IndirectSettings& settings)
+void IndirectCache::compute_domain(Scene::Ptr scene, const IndirectCacheSettings& settings)
 {
     glm::vec3 scene_min = scene->get_scene_min();
     glm::vec3 scene_max = scene->get_scene_max();
@@ -272,7 +378,7 @@ void IndirectCache::compute_domain(Scene::Ptr scene, const IndirectSettings& set
     this->propagation_iterations = 2 * glm::max(this->domain_resolution.x, glm::max(this->domain_resolution.y, this->domain_resolution.z));
 }
 
-bool IndirectCache::create_buffers(lava::device_ptr device, const IndirectSettings& settings)
+bool IndirectCache::create_buffers(lava::device_ptr device, const IndirectCacheSettings& settings)
 {
     glsl::IndirectDomain indirect_domain;
     indirect_domain.resolution = this->domain_resolution;
@@ -294,7 +400,7 @@ bool IndirectCache::create_buffers(lava::device_ptr device, const IndirectSettin
     return true;
 }
 
-bool IndirectCache::create_images(lava::device_ptr device, const IndirectSettings& settings)
+bool IndirectCache::create_images(lava::device_ptr device, const IndirectCacheSettings& settings)
 {
     this->capture_depth_image = lava::make_image(VK_FORMAT_D16_UNORM);
     this->capture_depth_image->set_usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
@@ -517,7 +623,7 @@ bool IndirectCache::create_samplers(lava::device_ptr device)
     sampler_info.compareEnable = VK_FALSE;
     sampler_info.compareOp = VK_COMPARE_OP_LESS;
     sampler_info.minLod = 0.0f;
-    sampler_info.maxLod = VK_LOD_CLAMP_NONE;
+    sampler_info.maxLod = 0.0f;
     sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
     sampler_info.unnormalizedCoordinates = VK_FALSE;
 
@@ -807,7 +913,7 @@ bool IndirectCache::create_layouts(lava::device_ptr device, Scene::Ptr scene)
     return true;
 }
 
-bool IndirectCache::create_capture_pass(lava::device_ptr device, const IndirectSettings& settings)
+bool IndirectCache::create_capture_pass(lava::device_ptr device, const IndirectCacheSettings& settings)
 {
     VkClearValue clear_depth;
     clear_depth.depthStencil.depth = 1.0;
diff --git a/src/utility/indirect_cache.hpp b/src/utility/indirect_cache.hpp
index 49fefcbfc3a1c9aca5e885701ff60c399487e799..df471b1a8379c2713382d55f33dc38ef348f27ae 100644
--- a/src/utility/indirect_cache.hpp
+++ b/src/utility/indirect_cache.hpp
@@ -8,10 +8,10 @@
 
 #include "scene.hpp"
 
-struct IndirectSettings
+struct IndirectCacheSettings
 {
     uint32_t capture_resolution = 1024;
-    float cell_size = 0.8f; //Where cell size is in meters
+    float cell_size = 1.0f; //Where cell size is in meters
 };
 
 class IndirectCache
@@ -22,7 +22,7 @@ public:
 public:
     IndirectCache() = default;
 
-    bool create(Scene::Ptr scene, const IndirectSettings& settings);
+    bool create(Scene::Ptr scene, const IndirectCacheSettings& settings);
     void destroy();
 
     void compute_indirect(VkCommandBuffer command_buffer, lava::index frame);
@@ -30,17 +30,17 @@ public:
     lava::descriptor::ptr get_descriptor() const;
     VkDescriptorSet get_descriptor_set() const;
 
-    const IndirectSettings& get_settings() const;
+    const IndirectCacheSettings& get_settings() const;
 
 private:
-    void compute_domain(Scene::Ptr scene, const IndirectSettings& settings);
+    void compute_domain(Scene::Ptr scene, const IndirectCacheSettings& settings);
 
-    bool create_buffers(lava::device_ptr device, const IndirectSettings& settings);
-    bool create_images(lava::device_ptr device, const IndirectSettings& settings);
+    bool create_buffers(lava::device_ptr device, const IndirectCacheSettings& settings);
+    bool create_images(lava::device_ptr device, const IndirectCacheSettings& settings);
     bool create_samplers(lava::device_ptr device);
     bool create_descriptors(lava::device_ptr device);
     bool create_layouts(lava::device_ptr device, Scene::Ptr scene);
-    bool create_capture_pass(lava::device_ptr device, const IndirectSettings& settings);
+    bool create_capture_pass(lava::device_ptr device, const IndirectCacheSettings& settings);
     bool create_capture_pipeline(lava::device_ptr device);
     bool create_injection_pass(lava::device_ptr device);
     bool create_injection_pipeline(lava::device_ptr device);
@@ -53,7 +53,7 @@ private:
 
 private:
     Scene::Ptr scene;
-    IndirectSettings settings;
+    IndirectCacheSettings settings;
 
     uint32_t frame = 0;
     uint32_t light_index = 0;