diff --git a/modules/material/CMakeLists.txt b/modules/material/CMakeLists.txt
index d5b654cc6d00ce77d93b4666f48b7a5097e674b3..ed3804531d36f9850bbb5d334e4fed9b43d92434 100644
--- a/modules/material/CMakeLists.txt
+++ b/modules/material/CMakeLists.txt
@@ -12,8 +12,6 @@ set(vkcv_material_include ${PROJECT_SOURCE_DIR}/include)
 set(vkcv_material_sources
 		${vkcv_material_include}/vkcv/material/Material.hpp
 		${vkcv_material_source}/vkcv/material/Material.cpp
-		${vkcv_material_include}/vkcv/material/PBRMaterial.hpp
-		${vkcv_material_source}/vkcv/material/PBRMaterial.cpp
 )
 
 # adding source files to the module
diff --git a/modules/material/include/vkcv/material/Material.hpp b/modules/material/include/vkcv/material/Material.hpp
index 00b492072fa4ef8b7b41f70202d515ee4ac828fa..f5bd0e1fc966381e902921361a3b7f396ec4550d 100644
--- a/modules/material/include/vkcv/material/Material.hpp
+++ b/modules/material/include/vkcv/material/Material.hpp
@@ -1,14 +1,68 @@
 #pragma once
+
+#include <vector>
+
+#include <vkcv/Core.hpp>
 #include <vkcv/Handles.hpp>
 
 namespace vkcv::material {
-
+	
+	enum class MaterialType {
+		PBR_MATERIAL = 1,
+		
+		UNKNOWN = 0
+	};
+	
 	class Material {
 	private:
+		struct Texture {
+			ImageHandle m_Image;
+			SamplerHandle m_Sampler;
+			std::vector<float> m_Factors;
+		};
+		
+		MaterialType m_Type;
+		DescriptorSetHandle m_DescriptorSet;
+		std::vector<Texture> m_Textures;
+		
 	public:
-		const DescriptorSetHandle m_DescriptorSetHandle;
-	protected:
-		Material(const DescriptorSetHandle& setHandle); 
+		Material();
+		~Material() = default;
+		
+		Material(const Material& other) = default;
+		Material(Material&& other) = default;
+		
+		Material& operator=(const Material& other) = default;
+		Material& operator=(Material&& other) = default;
+		
+		[[nodiscard]]
+		MaterialType getType() const;
+		
+		[[nodiscard]]
+		const DescriptorSetHandle& getDescriptorSet() const;
+		
+		bool operator!() const;
+		
+		static const std::vector<DescriptorBinding>& getPBRDescriptorBindings() noexcept;
+		
+		static Material createPBR(Core &core,
+								  ImageHandle &colorImg,
+								  SamplerHandle &colorSmp,
+								  ImageHandle &normalImg,
+								  SamplerHandle &normalSmp,
+								  ImageHandle &metRoughImg,
+								  SamplerHandle &metRoughSmp,
+								  ImageHandle &occlusionImg,
+								  SamplerHandle &occlusionSmp,
+								  ImageHandle &emissiveImg,
+								  SamplerHandle &emissiveSmp,
+								  float baseColorFactor [4],
+								  float metallicFactor,
+								  float roughnessFactor,
+								  float normalScale,
+								  float occlusionStrength,
+								  float emissiveFactor [3]);
+	
 	};
 	
 }
diff --git a/modules/material/include/vkcv/material/PBRMaterial.hpp b/modules/material/include/vkcv/material/PBRMaterial.hpp
deleted file mode 100644
index 09a5214b0e748a09ef8caefe5bf2b1a69ecbd8e1..0000000000000000000000000000000000000000
--- a/modules/material/include/vkcv/material/PBRMaterial.hpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#pragma once
-
-#include <vector>
-
-#include <vkcv/DescriptorConfig.hpp>
-#include <vkcv/Core.hpp>
-
-
-#include "Material.hpp"
-
-namespace vkcv::material
-{
-    class PBRMaterial : Material
-    {
-    private:
-        struct vec3 {
-            float x, y, z;
-        };
-        struct vec4 {
-            float x, y, z, a;
-        };
-        PBRMaterial(const ImageHandle& colorImg,
-            const SamplerHandle& colorSmp,
-            const ImageHandle& normalImg,
-            const SamplerHandle& normalSmp,
-            const ImageHandle& metRoughImg,
-            const SamplerHandle& metRoughSmp,
-            const ImageHandle& occlusionImg,
-            const SamplerHandle& occlusionSmp,
-            const ImageHandle& emissiveImg,
-            const SamplerHandle& emissiveSmp,
-            const DescriptorSetHandle& setHandle,
-            vec4 baseColorFactor,
-            float metallicFactor,
-            float roughnessFactor,
-            float normalScale,
-            float occlusionStrength,
-            vec3 emissiveFactor) noexcept;
-
-
-    public:
-        PBRMaterial() = delete;
-        
-        const ImageHandle   m_ColorTexture;
-        const SamplerHandle m_ColorSampler;
-
-        const ImageHandle   m_NormalTexture;
-        const SamplerHandle m_NormalSampler;
-
-        const ImageHandle   m_MetRoughTexture;
-        const SamplerHandle m_MetRoughSampler;
-
-        const ImageHandle m_OcclusionTexture;
-        const SamplerHandle m_OcclusionSampler;
-
-        const ImageHandle m_EmissiveTexture;
-        const SamplerHandle m_EmissiveSampler;
-
-        //
-        const vec4 m_BaseColorFactor;
-		const float m_MetallicFactor;
-		const float m_RoughnessFactor;
-		const float m_NormalScale;
-		const float m_OcclusionStrength;
-		const vec3 m_EmissiveFactor;
-
-        /*
-        * Returns the material's necessary descriptor bindings which serves as its descriptor layout
-        * The binding is in the following order:
-        * 0 - diffuse texture
-        * 1 - diffuse sampler
-        * 2 - normal texture
-        * 3 - normal sampler
-        * 4 - metallic roughness texture
-        * 5 - metallic roughness sampler
-        * 6 - occlusion texture
-        * 7 - occlusion sampler
-        * 8 - emissive texture
-        * 9 - emissive sampler
-        */
-        static std::vector<DescriptorBinding> getDescriptorBindings() noexcept;
-
-        static PBRMaterial create(
-            vkcv::Core* core,
-            ImageHandle          &colorImg,
-            SamplerHandle        &colorSmp,
-            ImageHandle          &normalImg,
-            SamplerHandle        &normalSmp,
-            ImageHandle          &metRoughImg,
-            SamplerHandle        &metRoughSmp,
-			ImageHandle			&occlusionImg,
-			SamplerHandle		&occlusionSmp,
-			ImageHandle			&emissiveImg,
-			SamplerHandle		&emissiveSmp,
-            vec4 baseColorFactor,
-            float metallicFactor,
-            float roughnessFactor,
-            float normalScale,
-            float occlusionStrength,
-            vec3 emissiveFactor);
-
-    };
-}
\ No newline at end of file
diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp
index 9168bcfbf924e9868ceaaff74aef5d3c6b99739c..86c6b7ae42ffdfca77966af946776979862f5d83 100644
--- a/modules/material/src/vkcv/material/Material.cpp
+++ b/modules/material/src/vkcv/material/Material.cpp
@@ -2,11 +2,159 @@
 #include "vkcv/material/Material.hpp"
 
 namespace vkcv::material {
+	
+	Material::Material() {
+		m_Type = MaterialType::UNKNOWN;
+	}
 
-	//TODO
-
-	Material::Material(const DescriptorSetHandle& setHandle) : m_DescriptorSetHandle(setHandle)
+	MaterialType Material::getType() const {
+		return m_Type;
+	}
+	
+	const DescriptorSetHandle & Material::getDescriptorSet() const {
+		return m_DescriptorSet;
+	}
+	
+	bool Material::operator!() const {
+		return (m_Type == MaterialType::UNKNOWN);
+	}
+	
+	const std::vector<DescriptorBinding>& Material::getPBRDescriptorBindings() noexcept
 	{
+		static std::vector<DescriptorBinding> bindings;
+		
+		if (bindings.empty()) {
+			bindings.emplace_back(0, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(1, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(2, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(3, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(4, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(5, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(6, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(7, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(8, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
+			bindings.emplace_back(9, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
+		}
+		
+		return bindings;
+	}
+	
+	Material Material::createPBR(Core &core,
+								 ImageHandle &colorImg, SamplerHandle &colorSmp,
+								 ImageHandle &normalImg, SamplerHandle &normalSmp,
+								 ImageHandle &metRoughImg, SamplerHandle &metRoughSmp,
+								 ImageHandle &occlusionImg, SamplerHandle &occlusionSmp,
+								 ImageHandle &emissiveImg, SamplerHandle &emissiveSmp,
+								 float baseColorFactor [4],
+								 float metallicFactor,
+								 float roughnessFactor,
+								 float normalScale,
+								 float occlusionStrength,
+								 float emissiveFactor [3]) {
+		if (!colorImg) {
+			vkcv::Image defaultColor = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			float colorData [4] = { 228, 51, 255, 1 };
+			defaultColor.fill(&colorData);
+			colorImg = defaultColor.getHandle();
+		}
+		
+		if (!normalImg) {
+			vkcv::Image defaultNormal = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			float normalData [4] = { 0, 0, 1, 0 };
+			defaultNormal.fill(&normalData);
+			normalImg = defaultNormal.getHandle();
+		}
+		
+		if (!metRoughImg) {
+			vkcv::Image defaultRough = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			float roughData [4] = { 228, 51, 255, 1 };
+			defaultRough.fill(&roughData);
+			metRoughImg = defaultRough.getHandle();
+		}
+		
+		if (!occlusionImg) {
+			vkcv::Image defaultOcclusion = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			float occlusionData [4] = { 228, 51, 255, 1 };
+			defaultOcclusion.fill(&occlusionData);
+			occlusionImg = defaultOcclusion.getHandle();
+		}
+		
+		if (!emissiveImg) {
+			vkcv::Image defaultEmissive = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			float emissiveData [4] = { 0, 0, 0, 1 };
+			defaultEmissive.fill(&emissiveData);
+			emissiveImg = defaultEmissive.getHandle();
+		}
+		
+		if (!colorSmp) {
+			colorSmp = core.createSampler(
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerMipmapMode::LINEAR,
+					vkcv::SamplerAddressMode::REPEAT
+			);
+		}
+		
+		if (!normalSmp) {
+			normalSmp = core.createSampler(
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerMipmapMode::LINEAR,
+					vkcv::SamplerAddressMode::REPEAT
+			);
+		}
+		
+		if (!metRoughSmp) {
+			metRoughSmp = core.createSampler(
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerMipmapMode::LINEAR,
+					vkcv::SamplerAddressMode::REPEAT
+			);
+		}
+		
+		if (!occlusionSmp) {
+			occlusionSmp = core.createSampler(
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerMipmapMode::LINEAR,
+					vkcv::SamplerAddressMode::REPEAT
+			);
+		}
+		
+		if (!emissiveSmp) {
+			emissiveSmp = core.createSampler(
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerMipmapMode::LINEAR,
+					vkcv::SamplerAddressMode::REPEAT
+			);
+		}
+		
+		const auto& bindings = getPBRDescriptorBindings();
+		vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(bindings);
+		
+		
+		Material material;
+		material.m_Type = MaterialType::PBR_MATERIAL;
+		material.m_DescriptorSet = descriptorSet;
+		
+		material.m_Textures.reserve(bindings.size());
+		material.m_Textures.push_back({ colorImg, colorSmp, std::vector<float>(baseColorFactor, baseColorFactor+4) });
+		material.m_Textures.push_back({ normalImg, normalSmp, std::vector<float>(&normalScale, &normalScale+1) });
+		material.m_Textures.push_back({ metRoughImg, metRoughSmp, std::vector<float>(&metallicFactor, &metallicFactor+1) });
+		material.m_Textures.push_back({ occlusionImg, occlusionSmp, std::vector<float>(&occlusionStrength, &occlusionStrength+1) });
+		material.m_Textures.push_back({ emissiveImg, emissiveSmp, std::vector<float>(emissiveFactor, emissiveFactor+3) });
+		
+		vkcv::DescriptorWrites setWrites;
+		
+		for (size_t i = 0; i < material.m_Textures.size(); i++) {
+			setWrites.sampledImageWrites.emplace_back(i * 2, material.m_Textures[i].m_Image);
+			setWrites.samplerWrites.emplace_back(i * 2 + 1, material.m_Textures[i].m_Sampler);
+		}
+		
+		core.writeDescriptorSet(descriptorSet, setWrites);
+		return material;
 	}
 
 }
diff --git a/modules/material/src/vkcv/material/PBRMaterial.cpp b/modules/material/src/vkcv/material/PBRMaterial.cpp
deleted file mode 100644
index d27e755c06a39e369d22efc997a0b411d067c132..0000000000000000000000000000000000000000
--- a/modules/material/src/vkcv/material/PBRMaterial.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-#include "vkcv/material/PBRMaterial.hpp"
-
-
-namespace vkcv::material
-{
-    PBRMaterial::PBRMaterial(
-        const ImageHandle& colorImg,
-        const SamplerHandle& colorSmp,
-        const ImageHandle& normalImg,
-        const SamplerHandle& normalSmp,
-        const ImageHandle& metRoughImg,
-        const SamplerHandle& metRoughSmp,
-        const ImageHandle& occlusionImg,
-        const SamplerHandle& occlusionSmp,
-        const ImageHandle& emissiveImg,
-        const SamplerHandle& emissiveSmp,
-        const DescriptorSetHandle& setHandle,
-        vec4 baseColorFactor,
-        float metallicFactor,
-        float roughnessFactor,
-        float normalScale,
-        float occlusionStrength,
-        vec3 emissiveFactor) noexcept :
-        m_ColorTexture(colorImg),
-        m_ColorSampler(colorSmp),
-        m_NormalTexture(normalImg),
-        m_NormalSampler(normalSmp),
-        m_MetRoughTexture(metRoughImg),
-        m_MetRoughSampler(metRoughSmp),
-        m_OcclusionTexture(occlusionImg),
-        m_OcclusionSampler(occlusionSmp),
-        m_EmissiveTexture(emissiveImg),
-        m_EmissiveSampler(emissiveSmp),
-        Material(setHandle),
-        m_BaseColorFactor(baseColorFactor),
-        m_MetallicFactor(metallicFactor),
-        m_RoughnessFactor(roughnessFactor),
-        m_NormalScale(normalScale),
-        m_OcclusionStrength(occlusionStrength),
-        m_EmissiveFactor(emissiveFactor)
-    {
-    }
-
-    std::vector<DescriptorBinding> PBRMaterial::getDescriptorBindings() noexcept
-    {
-		static std::vector<DescriptorBinding> bindings;
-		
-		if (bindings.empty()) {
-			bindings.emplace_back(0, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(1, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(2, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(3, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(4, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(5, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(6, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(7, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(8, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT);
-			bindings.emplace_back(9, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT);
-		}
-    	
-        return bindings;
-    }
-
-    PBRMaterial PBRMaterial::create(
-        vkcv::Core* core,
-        ImageHandle& colorImg,
-        SamplerHandle& colorSmp,
-        ImageHandle& normalImg,
-        SamplerHandle& normalSmp,
-        ImageHandle& metRoughImg,
-        SamplerHandle& metRoughSmp,
-        ImageHandle& occlusionImg,
-        SamplerHandle& occlusionSmp,
-        ImageHandle& emissiveImg,
-        SamplerHandle& emissiveSmp,
-        vec4 baseColorFactor,
-        float metallicFactor,
-        float roughnessFactor,
-        float normalScale,
-        float occlusionStrength,
-        vec3 emissiveFactor)
-    {
-        //Test if Images and samplers valid, if not use default
-         if (!colorImg) {
-            vkcv::Image defaultColor = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
-            vec4 colorData{ 228, 51, 255,1 };
-            defaultColor.fill(&colorData);
-            colorImg = defaultColor.getHandle();
-        }
-        if (!normalImg) {
-            vkcv::Image defaultNormal = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
-            vec4 normalData{ 0, 0, 1,0 };
-            defaultNormal.fill(&normalData);
-            normalImg = defaultNormal.getHandle();
-        }
-        if (!metRoughImg) {
-            vkcv::Image defaultRough = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
-            vec4 roughData{ 228, 51, 255,1 };
-            defaultRough.fill(&roughData);
-            metRoughImg = defaultRough.getHandle();
-        }
-        if (!occlusionImg) {
-            vkcv::Image defaultOcclusion = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
-            vec4 occlusionData{ 228, 51, 255,1 };
-            defaultOcclusion.fill(&occlusionData);
-            occlusionImg = defaultOcclusion.getHandle();
-        }
-        if (!emissiveImg) {
-            vkcv::Image defaultEmissive = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
-            vec4 emissiveData{ 0, 0, 0,1 };
-            defaultEmissive.fill(&emissiveData);
-            emissiveImg = defaultEmissive.getHandle();
-        }
-        if (!colorSmp) {            
-            colorSmp = core->createSampler(
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerMipmapMode::LINEAR,
-                vkcv::SamplerAddressMode::REPEAT
-            );            
-        }
-        if (!normalSmp) {            
-            normalSmp = core->createSampler(
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerMipmapMode::LINEAR,
-                vkcv::SamplerAddressMode::REPEAT
-            );            
-        }
-        if (!metRoughSmp) {
-            metRoughSmp = core->createSampler(
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerMipmapMode::LINEAR,
-                vkcv::SamplerAddressMode::REPEAT
-            );            
-        }
-        if (!occlusionSmp) {
-            occlusionSmp = core->createSampler(
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerMipmapMode::LINEAR,
-                vkcv::SamplerAddressMode::REPEAT
-            );
-        }
-        if (!emissiveSmp) {
-            emissiveSmp = core->createSampler(
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerFilterType::LINEAR,
-                vkcv::SamplerMipmapMode::LINEAR,
-                vkcv::SamplerAddressMode::REPEAT
-            );
-        }
-        
-
-
-        //create descriptorset
-        vkcv::DescriptorSetHandle descriptorSetHandle = core->createDescriptorSet(getDescriptorBindings());
-        //writes
-        vkcv::DescriptorWrites setWrites;
-        setWrites.sampledImageWrites = {
-            vkcv::SampledImageDescriptorWrite(0, colorImg),
-            vkcv::SampledImageDescriptorWrite(2, normalImg),
-            vkcv::SampledImageDescriptorWrite(4, metRoughImg),
-            vkcv::SampledImageDescriptorWrite(6, occlusionImg),
-            vkcv::SampledImageDescriptorWrite(8, emissiveImg) };
-        setWrites.samplerWrites = {
-            vkcv::SamplerDescriptorWrite(1, colorSmp),
-            vkcv::SamplerDescriptorWrite(3, normalSmp),
-            vkcv::SamplerDescriptorWrite(5, metRoughSmp),
-            vkcv::SamplerDescriptorWrite(7, occlusionSmp),
-            vkcv::SamplerDescriptorWrite(9, emissiveSmp) };
-        core->writeDescriptorSet(descriptorSetHandle, setWrites);
-
-        return PBRMaterial(
-            colorImg,
-            colorSmp,
-            normalImg,
-            normalSmp,
-            metRoughImg,
-            metRoughSmp,
-            occlusionImg,
-            occlusionSmp,
-            emissiveImg,
-            emissiveSmp,
-            descriptorSetHandle,
-            baseColorFactor,
-            metallicFactor,
-            roughnessFactor,
-            normalScale,
-            occlusionStrength,
-            emissiveFactor);
-    }
-}
\ No newline at end of file
diff --git a/modules/scene/CMakeLists.txt b/modules/scene/CMakeLists.txt
index 2152d45383d91496013ad7d1785099c3aa019a89..189eb7f62a5e0e920cad182a0c2ef6b3ec3184ae 100644
--- a/modules/scene/CMakeLists.txt
+++ b/modules/scene/CMakeLists.txt
@@ -21,10 +21,10 @@ add_library(vkcv_scene STATIC ${vkcv_scene_sources})
 target_link_libraries(vkcv_scene vkcv)
 
 # including headers of dependencies and the VkCV framework
-target_include_directories(vkcv_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_asset_loader_include})
+target_include_directories(vkcv_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_asset_loader_include} ${vkcv_material_include} ${vkcv_camera_include})
 
 # add the own include directory for public headers
 target_include_directories(vkcv_scene BEFORE PUBLIC ${vkcv_scene_include})
 
 # linking with libraries from all dependencies and the VkCV framework
-target_link_libraries(vkcv_scene vkcv vkcv_asset_loader)
\ No newline at end of file
+target_link_libraries(vkcv_scene vkcv vkcv_asset_loader vkcv_material vkcv_camera)
\ No newline at end of file
diff --git a/modules/scene/include/vkcv/scene/Bounds.hpp b/modules/scene/include/vkcv/scene/Bounds.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..474eb4f514fa268736745c131df2c4f7c9a9c423
--- /dev/null
+++ b/modules/scene/include/vkcv/scene/Bounds.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <glm/vec3.hpp>
+
+namespace vkcv::scene {
+	
+	class Bounds {
+	private:
+		glm::vec3 m_min;
+		glm::vec3 m_max;
+		
+	public:
+		Bounds();
+		~Bounds();
+		
+		Bounds(const Bounds& other) = default;
+		Bounds(Bounds&& other) = default;
+		
+		Bounds& operator=(const Bounds& other) = default;
+		Bounds& operator=(Bounds&& other) = default;
+		
+		void setMin(const glm::vec3& min);
+		
+		const glm::vec3& getMin() const;
+		
+		void setMax(const glm::vec3& max);
+		
+		const glm::vec3& getMax() const;
+		
+		void setCenter(const glm::vec3& center);
+		
+		glm::vec3 getCenter() const;
+		
+		void setSize(const glm::vec3& size);
+		
+		glm::vec3 getSize() const;
+	
+	};
+	
+}
diff --git a/modules/scene/include/vkcv/scene/Mesh.hpp b/modules/scene/include/vkcv/scene/Mesh.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1a1c1a868da4703818766390bc379887d913e5a9
--- /dev/null
+++ b/modules/scene/include/vkcv/scene/Mesh.hpp
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include <vkcv/Buffer.hpp>
+#include <vkcv/material/Material.hpp>
+#include <vkcv/asset/asset_loader.hpp>
+
+#include "Bounds.hpp"
+
+namespace vkcv::scene {
+	
+	class MeshPart {
+		friend class Mesh;
+		
+	private:
+		material::Material* m_material;
+		Buffer<uint8_t> m_vertices;
+		Buffer<uint8_t> m_indices;
+		Bounds m_bounds;
+		
+		MeshPart();
+		
+		void load(const asset::Scene& scene,
+				  const asset::VertexGroup& vertexGroup);
+		
+	public:
+		~MeshPart();
+		
+	};
+	
+	class Mesh {
+	private:
+		std::vector<MeshPart> m_parts;
+	
+	public:
+	
+	};
+	
+}
diff --git a/modules/scene/include/vkcv/scene/Node.hpp b/modules/scene/include/vkcv/scene/Node.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ef21061f9c9d6d8adc26bf5ebfbc5572f7785632
--- /dev/null
+++ b/modules/scene/include/vkcv/scene/Node.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <vector>
+
+#include "Mesh.hpp"
+
+namespace vkcv::scene {
+	
+	class Node {
+	private:
+		std::vector<Mesh> m_models;
+		std::vector<Node> m_nodes;
+	
+	public:
+	};
+	
+}
diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp
index 5acefd582c0a613ccbb4c08ac8edba4faf2d6c5e..db3c303a0e9bfb92425b7abfc0362fe76205de3a 100644
--- a/modules/scene/include/vkcv/scene/Scene.hpp
+++ b/modules/scene/include/vkcv/scene/Scene.hpp
@@ -1,10 +1,38 @@
 #pragma once
 
+#include <filesystem>
+
+#include <vkcv/material/Material.hpp>
+
+#include "Node.hpp"
+
 namespace vkcv::scene {
 	
 	class Scene {
 	private:
+		struct Material {
+			size_t m_usages;
+			material::Material m_data;
+		};
+		
+		std::vector<Node> m_nodes;
+		std::vector<Material> m_materials;
+		
+		Scene() = default;
+		
 	public:
+		~Scene() = default;
+		
+		Scene(const Scene& other) = default;
+		Scene(Scene&& other) = default;
+		
+		Scene& operator=(const Scene& other) = default;
+		Scene& operator=(Scene&& other) = default;
+		
+		static Scene create();
+		
+		static Scene load(const std::filesystem::path &path);
+		
 	};
 	
 }
\ No newline at end of file
diff --git a/modules/scene/src/vkcv/scene/Bounds.cpp b/modules/scene/src/vkcv/scene/Bounds.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e49a20c52e1073f5cc45fe71387f5743c4877163
--- /dev/null
+++ b/modules/scene/src/vkcv/scene/Bounds.cpp
@@ -0,0 +1,42 @@
+
+#include "vkcv/scene/Bounds.hpp"
+
+namespace vkcv::scene {
+
+	void Bounds::setMin(const glm::vec3 &min) {
+		m_min = min;
+	}
+	
+	const glm::vec3 & Bounds::getMin() const {
+		return m_min;
+	}
+	
+	void Bounds::setMax(const glm::vec3 &max) {
+		m_max = max;
+	}
+	
+	const glm::vec3 & Bounds::getMax() const {
+		return m_max;
+	}
+	
+	void Bounds::setCenter(const glm::vec3 &center) {
+		const glm::vec3 size = getSize();
+		m_min = center - size / 2;
+		m_max = center + size / 2;
+	}
+	
+	glm::vec3 Bounds::getCenter() const {
+		return (m_min + m_max) / 2;
+	}
+	
+	void Bounds::setSize(const glm::vec3 &size) {
+		const glm::vec3 center = getCenter();
+		m_min = center - size / 2;
+		m_max = center + size / 2;
+	}
+	
+	glm::vec3 Bounds::getSize() const {
+		return (m_max - m_min);
+	}
+
+}
diff --git a/modules/scene/src/vkcv/scene/Mesh.cpp b/modules/scene/src/vkcv/scene/Mesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..02bc4aaec61fe8d8dcad422753f66f2ac28cba53
--- /dev/null
+++ b/modules/scene/src/vkcv/scene/Mesh.cpp
@@ -0,0 +1,28 @@
+
+#include "vkcv/scene/Mesh.hpp"
+
+namespace vkcv::scene {
+	
+	void MeshPart::load(const asset::Scene& scene,
+						const asset::VertexGroup &vertexGroup) {
+		m_bounds.setMin(glm::vec3(
+				vertexGroup.min.x,
+				vertexGroup.min.y,
+				vertexGroup.min.z
+		));
+		
+		m_bounds.setMax(glm::vec3(
+				vertexGroup.max.x,
+				vertexGroup.max.y,
+				vertexGroup.max.z
+		));
+		
+		if ((vertexGroup.materialIndex >= 0) &&
+			(vertexGroup.materialIndex < scene.materials.size())) {
+			const asset::Material& material = scene.materials[vertexGroup.materialIndex];
+			
+			
+		}
+	}
+
+}
diff --git a/modules/scene/src/vkcv/scene/Node.cpp b/modules/scene/src/vkcv/scene/Node.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..51a2497dc4910c7dbd3dc0898beae97e4c83261c
--- /dev/null
+++ b/modules/scene/src/vkcv/scene/Node.cpp
@@ -0,0 +1,8 @@
+
+#include "vkcv/scene/Node.hpp"
+
+namespace vkcv::scene {
+
+
+
+}
diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp
index edbbd4454e9f520d233c0103e83bd8406e81ca95..a6512e42a17492ccdbd7a6ea3cc4bde314dc2ab7 100644
--- a/modules/scene/src/vkcv/scene/Scene.cpp
+++ b/modules/scene/src/vkcv/scene/Scene.cpp
@@ -1,8 +1,36 @@
 
 #include "vkcv/scene/Scene.hpp"
 
+#include <vkcv/Logger.hpp>
+#include <vkcv/asset/asset_loader.hpp>
+
 namespace vkcv::scene {
 	
-	//TODO
+	Scene Scene::create() {
+		return Scene();
+	}
+	
+	Scene Scene::load(const std::filesystem::path &path) {
+		asset::Scene asset_scene;
+		
+		if (!asset::loadScene(path.string(), asset_scene)) {
+			vkcv_log(LogLevel::WARNING, "Scene could not be loaded")
+			return create();
+		}
+		
+		Scene scene = create();
+		
+		for (const auto& material : asset_scene.materials) {
+			scene.m_materials.push_back({
+				0, material::Material()
+			});
+		}
+		
+		for (const auto& mesh : asset_scene.meshes) {
+			//TODO
+		}
+		
+		return scene;
+	}
 	
 }