diff --git a/res/dpr/data/material_data.inc b/res/dpr/data/material_data.inc
new file mode 100644
index 0000000000000000000000000000000000000000..7a952c297fed86347710e17e02d096a2011700d6
--- /dev/null
+++ b/res/dpr/data/material_data.inc
@@ -0,0 +1,22 @@
+#ifndef SHADER_INCLUDE_MATERIAL_DATA
+#define SHADER_INCLUDE_MATERIAL_DATA
+
+//NOTE: Struct needs to be multiple of 256
+struct MaterialData
+{
+    vec3 base_color;
+    float opacity;
+
+    vec3 emissive;
+    float roughness;
+
+    uvec3 padding1;
+    float metallic;
+
+    uvec4 padding2;
+    mat4 padding3;
+    mat4 padding4;
+    mat4 padding5;
+};
+
+#endif
\ No newline at end of file
diff --git a/res/dpr/data/mesh_data.inc b/res/dpr/data/mesh_data.inc
index 7ae6b1952676a224856ab1004c50410305510643..d45aa5728a9d28106d45a84e9f8064fa3ac1e899 100644
--- a/res/dpr/data/mesh_data.inc
+++ b/res/dpr/data/mesh_data.inc
@@ -1,6 +1,13 @@
-struct MeshData {
+#ifndef SHADER_INCLUDE_MESH_DATA
+#define SHADER_INCLUDE_MESH_DATA
+
+//NOTE: Struct needs to be multiple of 256
+struct MeshData
+{
     mat4 localToWorldSpace;
 	mat4 vectorToWorldSpace;
 	mat4 padding1;
 	mat4 padding2;
 };
+
+#endif
\ No newline at end of file
diff --git a/res/dpr/data/per_frame.inc b/res/dpr/data/per_frame.inc
index 4aef982cbcbc7e1b8949cf57d411eebd265ed69b..345f2fca07221b30072ebd81520372e7d190f939 100644
--- a/res/dpr/data/per_frame.inc
+++ b/res/dpr/data/per_frame.inc
@@ -1,3 +1,6 @@
+#ifndef SHADER_INCLUDE_PER_FRAME_DATA
+#define SHADER_INCLUDE_PER_FRAME_DATA
+
 struct PerFrameData
 {
     mat4 projection;
@@ -7,4 +10,6 @@ struct PerFrameData
     mat4 invView;
     mat4 invProjection;
     vec3 eyePosition;
-};
\ No newline at end of file
+};
+
+#endif
\ No newline at end of file
diff --git a/res/dpr/utility/material_library.glsl b/res/dpr/utility/material_library.glsl
index 8cc6515b286088406309783d789ace779181da9a..9639a76d528da5e5eb81f1447f1a69fde17e086e 100644
--- a/res/dpr/utility/material_library.glsl
+++ b/res/dpr/utility/material_library.glsl
@@ -33,6 +33,7 @@
     #error "The material descripotor-set is not specified"
 #endif
 
+#include "material_data.inc"
 #include "material_struct.glsl"
 
 layout(set = MATERIAL_DESCRIPTOR_SET, binding = 0) uniform sampler2D sampler_color_opacity;
@@ -40,6 +41,11 @@ layout(set = MATERIAL_DESCRIPTOR_SET, binding = 1) uniform sampler2D sampler_mat
 layout(set = MATERIAL_DESCRIPTOR_SET, binding = 2) uniform sampler2D sampler_normal;
 layout(set = MATERIAL_DESCRIPTOR_SET, binding = 3) uniform sampler2D sampler_emissive;
 
+layout(set = MATERIAL_DESCRIPTOR_SET, binding = 4) uniform MaterialDataBuffer
+{
+    MaterialData material_data;
+};
+
 Material lookup_material(vec2 uv_coord)
 {
     vec4 color_opacity = texture(sampler_color_opacity, uv_coord);
@@ -47,12 +53,12 @@ Material lookup_material(vec2 uv_coord)
     vec3 emissive_color = texture(sampler_emissive, uv_coord).xyz;
 
     Material material;
-    material.base_color = color_opacity.xyz;
-    material.opacity = color_opacity.w;
+    material.base_color = color_opacity.xyz * material_data.base_color;
+    material.opacity = color_opacity.w * material_data.opacity;
     material.occlusion = material_factor.x;
-    material.roughness = material_factor.y;
-    material.metallic = material_factor.z;
-    material.emissive = emissive_color;
+    material.roughness = material_factor.y * material_data.roughness;
+    material.metallic = material_factor.z  * material_data.metallic;
+    material.emissive = emissive_color * material_data.emissive;
 
     return material;
 }
diff --git a/src/scene.cpp b/src/scene.cpp
index d7ecaf573f07ab1e7e499b8f6c5f31e0b0fde94a..481cb16a39dc1f1bf841febaedaa1c349ef77b31 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -73,7 +73,7 @@ bool Scene::create(const SceneConfig& config, lava::device_ptr device, lava::sta
         return false;
     }
 
-    if (!this->create_material_descriptors(device))
+    if (!this->create_material_buffer(device))
     {
         return false;
     }
@@ -599,6 +599,7 @@ bool Scene::create_descriptor_layouts(lava::device_ptr device, uint32_t frame_co
     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);
+    this->material_descriptor->add_binding(4, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
 
     if (!this->material_descriptor->create(device))
     {
@@ -610,10 +611,27 @@ bool Scene::create_descriptor_layouts(lava::device_ptr device, uint32_t frame_co
     return true;
 }
 
-bool Scene::create_material_descriptors(lava::device_ptr device)
+bool Scene::create_material_buffer(lava::device_ptr device)
 {
+    std::vector<glsl::MaterialData> material_data;
+    material_data.reserve(this->materials.size());
+
+    for (const SceneMaterial& material : this->materials)
+    {
+        material_data.push_back(material.material_data);
+    }
+
+    this->material_data_buffer = lava::make_buffer();
+
+    if (!this->material_data_buffer->create_mapped(device, material_data.data(), sizeof(glsl::MaterialData) * material_data.size(), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT))
+    {
+        lava::log()->error("Can't create material data buffer!");
+
+        return false;
+    }
+
     std::vector<VkWriteDescriptorSet> descriptor_writes;
-    descriptor_writes.reserve(this->materials.size() * 4);
+    descriptor_writes.reserve(this->materials.size() * 5);
 
     for (SceneMaterial& material : this->materials)
     {
@@ -627,20 +645,34 @@ bool Scene::create_material_descriptors(lava::device_ptr device)
 
         for (uint32_t binding = 0; binding < textures.size(); binding++)
         {
-            VkWriteDescriptorSet descriptor_write;
-            descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            descriptor_write.pNext = nullptr;
-            descriptor_write.dstSet = material.descriptor_set;
-            descriptor_write.dstBinding = binding;
-            descriptor_write.dstArrayElement = 0;
-            descriptor_write.descriptorCount = 1;
-            descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-            descriptor_write.pImageInfo = textures[binding]->get_descriptor_info();
-            descriptor_write.pBufferInfo = nullptr;
-            descriptor_write.pTexelBufferView = nullptr;
-
-            descriptor_writes.push_back(descriptor_write);
+            VkWriteDescriptorSet texture_write;
+            texture_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            texture_write.pNext = nullptr;
+            texture_write.dstSet = material.descriptor_set;
+            texture_write.dstBinding = binding;
+            texture_write.dstArrayElement = 0;
+            texture_write.descriptorCount = 1;
+            texture_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+            texture_write.pImageInfo = textures[binding]->get_descriptor_info();
+            texture_write.pBufferInfo = nullptr;
+            texture_write.pTexelBufferView = nullptr;
+
+            descriptor_writes.push_back(texture_write);
         }
+
+        VkWriteDescriptorSet buffer_write;
+        buffer_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+        buffer_write.pNext = nullptr;
+        buffer_write.dstSet = material.descriptor_set;
+        buffer_write.dstBinding = 4;
+        buffer_write.dstArrayElement = 0;
+        buffer_write.descriptorCount = 1;
+        buffer_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+        buffer_write.pImageInfo = nullptr;
+        buffer_write.pBufferInfo = this->material_data_buffer->get_descriptor_info();
+        buffer_write.pTexelBufferView = nullptr;
+
+        descriptor_writes.push_back(buffer_write);
     }
 
     vkUpdateDescriptorSets(device->get(), descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
@@ -1311,14 +1343,47 @@ bool Scene::load_materials(const aiScene* scene, const std::string& base_name, l
         SceneMaterial& scene_material = this->materials.emplace_back();
         scene_material.emissive = this->dummy_emissive_texture;
 
+        aiColor3D diffuse_color = aiColor3D(0.0f, 0.0f, 0.0f);
+        material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse_color);
+
+        aiColor3D emissive_color = aiColor3D(0.0f, 0.0f, 0.0f);
+        material->Get(AI_MATKEY_COLOR_EMISSIVE, emissive_color);
+
+        float opacity = 1.0f;
+        material->Get(AI_MATKEY_OPACITY, opacity);
+
+        float shininess = 0.0f;
+        material->Get(AI_MATKEY_SHININESS, shininess);
+
+        float reflectivity = 0.0f;
+        material->Get(AI_MATKEY_REFLECTIVITY, reflectivity);
+
+        glsl::MaterialData& material_data = scene_material.material_data;
+        material_data.base_color = glm::vec3(1.0f);
+        material_data.opacity = 1.0f;
+        material_data.emissive = glm::make_vec3(&emissive_color.r);
+        material_data.roughness = 1.0f;
+        material_data.padding1 = glm::uvec3(0);
+        material_data.metallic = 0.0f;
+        material_data.padding2 = glm::uvec4(0);
+        material_data.padding3 = glm::mat4(0);
+        material_data.padding4 = glm::mat4(0);
+        material_data.padding5 = glm::mat4(0);
+
         if (!this->load_texture(material, base_name, aiTextureType_DIFFUSE, device, staging, scene_material.diffuse))
         {
             scene_material.diffuse = this->dummy_diffuse_texture;
+
+            material_data.base_color = glm::make_vec3(&diffuse_color.r);
+            material_data.opacity = glm::clamp(opacity, 0.0f, 1.0f);
         }
 
         if (!this->load_texture(material, base_name, aiTextureType_SPECULAR, device, staging, scene_material.specular))
         {
             scene_material.specular = this->dummy_specular_texture;
+
+            material_data.roughness = glm::clamp(1.0f - (glm::sqrt(shininess) / 10.0f), 0.0f, 1.0f);
+            material_data.metallic = glm::clamp(reflectivity, 0.0f, 1.0f);
         }
 
         if (!this->load_texture(material, base_name, aiTextureType_NORMALS, device, staging, scene_material.normal))
diff --git a/src/scene.hpp b/src/scene.hpp
index c96b6fbe4cf2b13095daf0b2ccfba7e892445a68..b4099ff0d3df0d85b84f53496618acc379055221 100644
--- a/src/scene.hpp
+++ b/src/scene.hpp
@@ -13,6 +13,7 @@ using namespace glm;
 using uint = glm::uint32;
 #include "res/dpr/data/mesh_data.inc"
 #include "res/dpr/data/light_data.inc"
+#include "res/dpr/data/material_data.inc"
 }
 
 #define INVALID_NODE -1
@@ -103,6 +104,7 @@ struct SceneMaterial
     lava::texture::ptr specular;
     lava::texture::ptr normal;
     lava::texture::ptr emissive;
+    glsl::MaterialData material_data;
     VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
 };
 
@@ -173,7 +175,7 @@ private:
     void create_default_light();
 
     bool create_descriptor_layouts(lava::device_ptr device, uint32_t frame_count);
-    bool create_material_descriptors(lava::device_ptr device);
+    bool create_material_buffer(lava::device_ptr device);
     bool create_light_buffer(lava::device_ptr device, uint32_t frame_count);
     bool create_mesh_buffer(lava::device_ptr device, uint32_t frame_count);
 
@@ -234,6 +236,7 @@ private:
     std::vector<lava::buffer::ptr> mesh_data_buffer;
     std::vector<lava::buffer::ptr> light_data_buffer;
     lava::buffer::ptr light_parameter_buffer;
+    lava::buffer::ptr material_data_buffer;
 
     lava::descriptor::pool::ptr descriptor_pool;
     lava::descriptor::ptr mesh_descriptor;
diff --git a/src/strategy/multi_view_stereo.cpp b/src/strategy/multi_view_stereo.cpp
index 577df49f78eb119abfaa3ce89249f3d9fec7470b..75da988e9ff0679c5f3f66c8ea78db23ea9cd99b 100644
--- a/src/strategy/multi_view_stereo.cpp
+++ b/src/strategy/multi_view_stereo.cpp
@@ -76,6 +76,10 @@ bool MultiViewStereo::on_render(VkCommandBuffer command_buffer, lava::index fram
 {
     this->get_headset()->submit_metadata(FrameMetadata());
 
+    this->get_pass_timer()->begin_pass(command_buffer, "shadow");
+    this->get_application()->get_shadow_cache()->compute_shadow(command_buffer, frame);
+    this->get_pass_timer()->end_pass(command_buffer);
+
     this->get_pass_timer()->begin_pass(command_buffer, "multi_eye");
     this->render_pass->process(command_buffer, 0);
     this->get_pass_timer()->end_pass(command_buffer);
diff --git a/src/strategy/native_stereo_deferred.cpp b/src/strategy/native_stereo_deferred.cpp
index d891225c0fbc349a36efabe708bb063a0c312e42..74f93ecedb437c22f80d9cc07f6e92e76be9d4c6 100644
--- a/src/strategy/native_stereo_deferred.cpp
+++ b/src/strategy/native_stereo_deferred.cpp
@@ -71,6 +71,10 @@ bool NativeStereoDeferred::on_render(VkCommandBuffer command_buffer, lava::index
 {
     this->get_headset()->submit_metadata(FrameMetadata());
 
+    this->get_pass_timer()->begin_pass(command_buffer, "shadow");
+    this->get_application()->get_shadow_cache()->compute_shadow(command_buffer, frame);
+    this->get_pass_timer()->end_pass(command_buffer);
+
     this->get_pass_timer()->begin_pass(command_buffer, "left_eye");
     this->eye_passes[0].render_pass->process(command_buffer, 0);
     this->get_pass_timer()->end_pass(command_buffer);
diff --git a/src/strategy/native_stereo_forward.cpp b/src/strategy/native_stereo_forward.cpp
index 41b2e4ed9fe767f841bd1fc9b91dfb6838f8b800..d6985c98273ff18d296a2fdbc4601d80080c986c 100644
--- a/src/strategy/native_stereo_forward.cpp
+++ b/src/strategy/native_stereo_forward.cpp
@@ -71,6 +71,10 @@ bool NativeStereoForward::on_render(VkCommandBuffer command_buffer, lava::index
 {
     this->get_headset()->submit_metadata(FrameMetadata());
 
+    this->get_pass_timer()->begin_pass(command_buffer, "shadow");
+    this->get_application()->get_shadow_cache()->compute_shadow(command_buffer, frame);
+    this->get_pass_timer()->end_pass(command_buffer);
+
     this->get_pass_timer()->begin_pass(command_buffer, "left_eye");
     this->eye_passes[0].render_pass->process(command_buffer, 0);
     this->get_pass_timer()->end_pass(command_buffer);
diff --git a/src/utility/shadow_cache.hpp b/src/utility/shadow_cache.hpp
index cab6af7e537731e0c99a7037244e07a29935cfce..d0969a99306697919ed5d2091f293eac0bedb2a9 100644
--- a/src/utility/shadow_cache.hpp
+++ b/src/utility/shadow_cache.hpp
@@ -40,7 +40,7 @@
 
 struct ShadowCacheSettings
 {
-    uint32_t resolution = 2048;
+    uint32_t resolution = 1024;
 
     bool use_directional = true;
     bool use_spot = true;