diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 33f0047cdc28f0e8133359446ef1e27091c42ebb..4db642f44293142a42c9a277d108e6fe225a0bda 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -31,7 +31,7 @@ namespace vkcv {
 		uint32_t getDepth() const;
 
 		[[nodiscard]]
-		vkcv::ImageHandle getHandle() const;
+		const vkcv::ImageHandle& getHandle() const;
 
 		[[nodiscard]]
 		uint32_t getMipCount() const;
@@ -45,7 +45,7 @@ namespace vkcv {
 	    // TODO: const qualifier removed, very hacky!!!
 	    //  Else you cannot recreate an image. Pls fix.
 		ImageManager*       m_manager;
-		ImageHandle   m_handle;
+		ImageHandle   		m_handle;
 
 		Image(ImageManager* manager, const ImageHandle& handle);
 		
diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp
index d16555add772d4e3364dad2a6f5a67671f1138d8..aaf2e1302f5435809221dff774f557c7d65c1a96 100644
--- a/modules/material/src/vkcv/material/Material.cpp
+++ b/modules/material/src/vkcv/material/Material.cpp
@@ -45,6 +45,16 @@ namespace vkcv::material {
 		}
 	}
 	
+	static void fillImage(Image& image, float data [4]) {
+		std::vector<float> vec (image.getWidth() * image.getHeight() * image.getDepth() * 4);
+		
+		for (size_t i = 0; i < vec.size(); i++) {
+			vec[i] = data[i % 4];
+		}
+		
+		image.fill(data);
+	}
+	
 	Material Material::createPBR(Core &core,
 								 const ImageHandle &colorImg, const SamplerHandle &colorSmp,
 								 const ImageHandle &normalImg, const SamplerHandle &normalSmp,
@@ -66,37 +76,37 @@ namespace vkcv::material {
 		};
 		
 		if (!colorImg) {
-			vkcv::Image defaultColor = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			vkcv::Image defaultColor = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
 			float colorData [4] = { 228, 51, 255, 1 };
-			defaultColor.fill(&colorData);
+			fillImage(defaultColor, colorData);
 			images[0] = defaultColor.getHandle();
 		}
 		
 		if (!normalImg) {
-			vkcv::Image defaultNormal = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			vkcv::Image defaultNormal = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
 			float normalData [4] = { 0, 0, 1, 0 };
-			defaultNormal.fill(&normalData);
+			fillImage(defaultNormal, normalData);
 			images[1] = defaultNormal.getHandle();
 		}
 		
 		if (!metRoughImg) {
-			vkcv::Image defaultRough = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			vkcv::Image defaultRough = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
 			float roughData [4] = { 228, 51, 255, 1 };
-			defaultRough.fill(&roughData);
+			fillImage(defaultRough, roughData);
 			images[2] = defaultRough.getHandle();
 		}
 		
 		if (!occlusionImg) {
-			vkcv::Image defaultOcclusion = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			vkcv::Image defaultOcclusion = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
 			float occlusionData [4] = { 228, 51, 255, 1 };
-			defaultOcclusion.fill(&occlusionData);
+			fillImage(defaultOcclusion, occlusionData);
 			images[3] = defaultOcclusion.getHandle();
 		}
 		
 		if (!emissiveImg) {
-			vkcv::Image defaultEmissive = core.createImage(vk::Format::eR8G8B8A8Srgb, 1, 1);
+			vkcv::Image defaultEmissive = core.createImage(vk::Format::eR8G8B8A8Srgb, 2, 2);
 			float emissiveData [4] = { 0, 0, 0, 1 };
-			defaultEmissive.fill(&emissiveData);
+			fillImage(defaultEmissive, emissiveData);
 			images[4] = defaultEmissive.getHandle();
 		}
 		
diff --git a/modules/scene/CMakeLists.txt b/modules/scene/CMakeLists.txt
index 8e742d92f6051f937ffd025909a6d041528a248e..cd2aff719242d92edca95c5a2a2c7ac01ec1205d 100644
--- a/modules/scene/CMakeLists.txt
+++ b/modules/scene/CMakeLists.txt
@@ -13,6 +13,9 @@ set(vkcv_scene_sources
 		${vkcv_scene_include}/vkcv/scene/Bounds.hpp
 		${vkcv_scene_source}/vkcv/scene/Bounds.cpp
 		
+		${vkcv_scene_include}/vkcv/scene/MeshPart.hpp
+		${vkcv_scene_source}/vkcv/scene/MeshPart.cpp
+		
 		${vkcv_scene_include}/vkcv/scene/Mesh.hpp
 		${vkcv_scene_source}/vkcv/scene/Mesh.cpp
 		
diff --git a/modules/scene/include/vkcv/scene/Bounds.hpp b/modules/scene/include/vkcv/scene/Bounds.hpp
index 474eb4f514fa268736745c131df2c4f7c9a9c423..43694aa80fd6ef7d389961c181aa20c7cf3d237b 100644
--- a/modules/scene/include/vkcv/scene/Bounds.hpp
+++ b/modules/scene/include/vkcv/scene/Bounds.hpp
@@ -11,7 +11,7 @@ namespace vkcv::scene {
 		
 	public:
 		Bounds();
-		~Bounds();
+		~Bounds() = default;
 		
 		Bounds(const Bounds& other) = default;
 		Bounds(Bounds&& other) = default;
diff --git a/modules/scene/include/vkcv/scene/Mesh.hpp b/modules/scene/include/vkcv/scene/Mesh.hpp
index 94c505a09ecb634cc49c103e94ec01d252a5796c..7416001edc185f3217950b1ff2b26cc65850d958 100644
--- a/modules/scene/include/vkcv/scene/Mesh.hpp
+++ b/modules/scene/include/vkcv/scene/Mesh.hpp
@@ -1,48 +1,13 @@
 #pragma once
 
-#include <memory>
-#include <vector>
+#include <glm/mat4x4.hpp>
 
-#include <vkcv/Buffer.hpp>
-#include <vkcv/material/Material.hpp>
-#include <vkcv/asset/asset_loader.hpp>
+#include <vkcv/camera/Camera.hpp>
 
-#include "Bounds.hpp"
+#include "MeshPart.hpp"
 
 namespace vkcv::scene {
 	
-	class Scene;
-	class Mesh;
-	
-	class MeshPart {
-		friend class Mesh;
-		
-	private:
-		Scene* m_scene;
-		BufferHandle m_vertices;
-		BufferHandle m_indices;
-		Bounds m_bounds;
-		size_t m_materialIndex;
-		
-		explicit MeshPart(Scene* scene);
-		
-		void load(const asset::Scene& scene,
-				  const asset::VertexGroup& vertexGroup);
-		
-	public:
-		~MeshPart();
-		
-		MeshPart(const MeshPart& other) = default;
-		MeshPart(MeshPart&& other) = default;
-		
-		MeshPart& operator=(const MeshPart& other) = default;
-		MeshPart& operator=(MeshPart&& other) = default;
-		
-		[[nodiscard]]
-		const material::Material& getMaterial() const;
-		
-	};
-	
 	class Node;
 	
 	class Mesh {
@@ -51,20 +16,24 @@ namespace vkcv::scene {
 	private:
 		Scene* m_scene;
 		std::vector<MeshPart> m_parts;
+		std::vector<DrawcallInfo> m_drawcalls;
+		glm::mat4 m_transform;
 		
 		explicit Mesh(Scene* scene);
 		
 		void load(const asset::Scene& scene,
 				  const asset::Mesh& mesh);
+		
+		void recordDrawcalls(std::vector<glm::mat4>& matrices, std::vector<DrawcallInfo>& drawcalls);
 	
 	public:
-		~Mesh() = default;
+		~Mesh();
 		
-		Mesh(const Mesh& other) = default;
-		Mesh(Mesh&& other) = default;
+		Mesh(const Mesh& other);
+		Mesh(Mesh&& other) noexcept;
 		
-		Mesh& operator=(const Mesh& other) = default;
-		Mesh& operator=(Mesh&& other) = default;
+		Mesh& operator=(const Mesh& other);
+		Mesh& operator=(Mesh&& other) noexcept;
 	
 	};
 	
diff --git a/modules/scene/include/vkcv/scene/MeshPart.hpp b/modules/scene/include/vkcv/scene/MeshPart.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..70ff7efcba4bf27a7d152c36782ccbe2953475d9
--- /dev/null
+++ b/modules/scene/include/vkcv/scene/MeshPart.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <vector>
+
+#include <vkcv/Buffer.hpp>
+#include <vkcv/asset/asset_loader.hpp>
+#include <vkcv/material/Material.hpp>
+
+#include "Bounds.hpp"
+
+namespace vkcv::scene {
+	
+	class Scene;
+	class Mesh;
+	
+	class MeshPart {
+		friend class Mesh;
+	
+	private:
+		Scene* m_scene;
+		BufferHandle m_vertices;
+		std::vector<VertexBufferBinding> m_vertexBindings;
+		BufferHandle m_indices;
+		size_t m_indexCount;
+		Bounds m_bounds;
+		size_t m_materialIndex;
+		
+		explicit MeshPart(Scene* scene);
+		
+		void load(const asset::Scene& scene,
+				  const asset::VertexGroup& vertexGroup,
+				  std::vector<DrawcallInfo>& drawcalls);
+	
+	public:
+		~MeshPart();
+		
+		MeshPart(const MeshPart& other);
+		MeshPart(MeshPart&& other) noexcept;
+		
+		MeshPart& operator=(const MeshPart& other);
+		MeshPart& operator=(MeshPart&& other) noexcept;
+		
+		[[nodiscard]]
+		const material::Material& getMaterial() const;
+		
+		explicit operator bool() const;
+		bool operator!() const;
+		
+	};
+
+}
diff --git a/modules/scene/include/vkcv/scene/Node.hpp b/modules/scene/include/vkcv/scene/Node.hpp
index c5d24fc1f28cf1181123415d96c8c2aa1585ae53..3aa0caebeb826f93a386a76562ab8bc451e193be 100644
--- a/modules/scene/include/vkcv/scene/Node.hpp
+++ b/modules/scene/include/vkcv/scene/Node.hpp
@@ -2,6 +2,8 @@
 
 #include <vector>
 
+#include <vkcv/camera/Camera.hpp>
+
 #include "Mesh.hpp"
 
 namespace vkcv::scene {
@@ -20,15 +22,17 @@ namespace vkcv::scene {
 		explicit Node(Scene* scene);
 		
 		void loadMesh(const asset::Scene& asset_scene, const asset::Mesh& asset_mesh);
+		
+		void recordDrawcalls(std::vector<glm::mat4>& matrices, std::vector<DrawcallInfo>& drawcalls);
 	
 	public:
-		~Node() = default;
+		~Node();
 		
-		Node(const Node& other) = default;
-		Node(Node&& other) = default;
+		Node(const Node& other);
+		Node(Node&& other) noexcept;
 		
-		Node& operator=(const Node& other) = default;
-		Node& operator=(Node&& other) = default;
+		Node& operator=(const Node& other);
+		Node& operator=(Node&& other) noexcept;
 		
 		Node& addNode();
 		
diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp
index c41fada092b83ec0089c94b96e6d16cad84fa92b..6320d3db9ad9097cd47d91c7f576400a30aee7cc 100644
--- a/modules/scene/include/vkcv/scene/Scene.hpp
+++ b/modules/scene/include/vkcv/scene/Scene.hpp
@@ -3,6 +3,7 @@
 #include <filesystem>
 
 #include <vkcv/Core.hpp>
+#include <vkcv/camera/Camera.hpp>
 #include <vkcv/material/Material.hpp>
 
 #include "Node.hpp"
@@ -26,16 +27,27 @@ namespace vkcv::scene {
 		explicit Scene(Core* core);
 		
 	public:
-		~Scene() = default;
+		~Scene();
 		
-		Scene(const Scene& other) = default;
-		Scene(Scene&& other) = default;
+		Scene(const Scene& other);
+		Scene(Scene&& other) noexcept;
 		
-		Scene& operator=(const Scene& other) = default;
-		Scene& operator=(Scene&& other) = default;
+		Scene& operator=(const Scene& other);
+		Scene& operator=(Scene&& other) noexcept;
 		
 		Node& addNode();
 		
+		size_t getMaterialCount() const;
+		
+		[[nodiscard]]
+		const material::Material& getMaterial(size_t index) const;
+		
+		void recordDrawcalls(CommandStreamHandle       		 &cmdStream,
+							 const camera::Camera			 &camera,
+							 const PassHandle                &pass,
+							 const PipelineHandle            &pipeline,
+							 const std::vector<ImageHandle>  &renderTargets);
+		
 		static Scene create(Core& core);
 		
 		static Scene load(Core& core, const std::filesystem::path &path);
diff --git a/modules/scene/src/vkcv/scene/Bounds.cpp b/modules/scene/src/vkcv/scene/Bounds.cpp
index a25a825cc188a700008f959474e40d3aeabe2cb1..39d8ae345abe891a3390b31e6cbcfc359b55b100 100644
--- a/modules/scene/src/vkcv/scene/Bounds.cpp
+++ b/modules/scene/src/vkcv/scene/Bounds.cpp
@@ -2,6 +2,10 @@
 #include "vkcv/scene/Bounds.hpp"
 
 namespace vkcv::scene {
+	
+	Bounds::Bounds() :
+	m_min(glm::vec3(0)),
+	m_max(glm::vec3(0)) {}
 
 	void Bounds::setMin(const glm::vec3 &min) {
 		m_min = min;
diff --git a/modules/scene/src/vkcv/scene/Mesh.cpp b/modules/scene/src/vkcv/scene/Mesh.cpp
index 3a2dd9c705b14d35c0cd6e9e05c741ff0c4aafb9..6668b8b522d440ee1e50986b4b14e63bf2f63cbe 100644
--- a/modules/scene/src/vkcv/scene/Mesh.cpp
+++ b/modules/scene/src/vkcv/scene/Mesh.cpp
@@ -4,174 +4,89 @@
 
 namespace vkcv::scene {
 	
-	MeshPart::MeshPart(Scene* scene) :
+	Mesh::Mesh(Scene* scene) :
 	m_scene(scene) {}
 	
-	void loadImage(Core& core, const asset::Scene& asset_scene,
-				   const asset::Texture& asset_texture,
-				   const vk::Format& format,
-				   ImageHandle& image, SamplerHandle& sampler) {
-		asset::Sampler* asset_sampler = nullptr;
-		
-		if ((asset_texture.sampler >= 0) && (asset_texture.sampler < asset_scene.samplers.size())) {
-			//asset_sampler = &(asset_scene.samplers[asset_texture.sampler]); // TODO
-		}
-		
-		Image img = core.createImage(format, asset_texture.w, asset_texture.h, 1, true);
-		img.fill(asset_texture.data.data());
-		image = img.getHandle();
-		
-		if (asset_sampler) {
-			//sampler = core.createSampler(asset_sampler) // TODO
-		}
-	}
-	
-	material::Material loadMaterial(Core& core, const asset::Scene& scene,
-					  				const asset::Material& material) {
-		ImageHandle diffuseImg;
-		SamplerHandle diffuseSmp;
-		
-		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
-			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
-					  diffuseImg,diffuseSmp);
-		}
-		
-		ImageHandle normalImg;
-		SamplerHandle normalSmp;
-		
-		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
-			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
-					  diffuseImg,diffuseSmp);
-		}
-		
-		ImageHandle metalRoughImg;
-		SamplerHandle metalRoughSmp;
-		
-		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
-			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
-					  diffuseImg,diffuseSmp);
-		}
-		
-		ImageHandle occlusionImg;
-		SamplerHandle occlusionSmp;
-		
-		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
-			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
-					  diffuseImg,diffuseSmp);
-		}
+	static glm::mat4 arrayTo4x4Matrix(const std::array<float,16>& array){
+		glm::mat4 matrix;
 		
-		ImageHandle emissionImg;
-		SamplerHandle emissionSmp;
-		
-		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
-			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
-					  diffuseImg,diffuseSmp);
+		for (int i = 0; i < 4; i++){
+			for (int j = 0; j < 4; j++){
+				matrix[i][j] = array[j * 4 + i];
+			}
 		}
 		
-		const float colorFactors [4] = {
-				material.baseColorFactor.r,
-				material.baseColorFactor.g,
-				material.baseColorFactor.b,
-				material.baseColorFactor.a
-		};
-		
-		const float emissionFactors[4] = {
-				material.emissiveFactor.r,
-				material.emissiveFactor.g,
-				material.emissiveFactor.b
-		};
-		
-		return material::Material::createPBR(
-				core,
-				diffuseImg, diffuseSmp,
-				normalImg, normalSmp,
-				metalRoughImg, metalRoughSmp,
-				occlusionImg, occlusionSmp,
-				emissionImg, emissionSmp,
-				colorFactors,
-				material.normalScale,
-				material.metallicFactor,
-				material.roughnessFactor,
-				material.occlusionStrength,
-				emissionFactors
-		);
+		return matrix;
 	}
 	
-	void MeshPart::load(const asset::Scene& scene,
-						const asset::VertexGroup &vertexGroup) {
-		Core& core = *(m_scene->m_core);
-		
-		auto vertexBuffer = core.createBuffer<uint8_t>(
-				BufferType::VERTEX, vertexGroup.vertexBuffer.data.size()
-		);
-		
-		vertexBuffer.fill(vertexGroup.vertexBuffer.data);
-		m_vertices = vertexBuffer.getHandle();
-		
-		auto indexBuffer = core.createBuffer<uint8_t>(
-				BufferType::INDEX, vertexGroup.indexBuffer.data.size()
-		);
-		
-		indexBuffer.fill(vertexGroup.indexBuffer.data);
-		m_indices = indexBuffer.getHandle();
-		
-		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
-		));
+	void Mesh::load(const asset::Scene &scene, const asset::Mesh &mesh) {
+		m_drawcalls.clear();
 		
-		if ((vertexGroup.materialIndex >= 0) &&
-			(vertexGroup.materialIndex < scene.materials.size())) {
-			m_materialIndex = vertexGroup.materialIndex;
+		for (const auto& vertexGroupIndex : mesh.vertexGroups) {
+			if ((vertexGroupIndex < 0) || (vertexGroupIndex >= scene.vertexGroups.size())) {
+				continue;
+			}
 			
-			auto& material = m_scene->m_materials[m_materialIndex];
+			MeshPart part (m_scene);
+			part.load(scene, scene.vertexGroups[vertexGroupIndex], m_drawcalls);
 			
-			if (0 == material.m_usages++) {
-				material.m_data = loadMaterial(core, scene, scene.materials[vertexGroup.materialIndex]);
+			if (!part) {
+				continue;
 			}
-		} else {
-			m_materialIndex = std::numeric_limits<size_t>::max();
+			
+			m_parts.push_back(part);
 		}
+		
+		m_transform = arrayTo4x4Matrix(mesh.modelMatrix);
 	}
 	
-	MeshPart::~MeshPart() {
-		if (m_materialIndex < std::numeric_limits<size_t>::max()) {
-			auto& material = m_scene->m_materials[m_materialIndex];
-			
-			if (material.m_usages > 0) {
-				material.m_usages--;
-			}
-		}
+	Mesh::~Mesh() {
+		m_drawcalls.clear();
+		m_parts.clear();
 	}
 	
-	const material::Material & MeshPart::getMaterial() const {
-		if (m_materialIndex < std::numeric_limits<size_t>::max()) {
-			return m_scene->m_materials[m_materialIndex].m_data;
-		} else {
-			static material::Material noMaterial;
-			return noMaterial;
+	Mesh::Mesh(const Mesh &other) :
+	m_scene(other.m_scene),
+	m_parts(other.m_parts),
+	m_drawcalls(other.m_drawcalls),
+	m_transform(other.m_transform) {}
+	
+	Mesh::Mesh(Mesh &&other) noexcept :
+	m_scene(other.m_scene),
+	m_parts(other.m_parts),
+	m_drawcalls(other.m_drawcalls),
+	m_transform(other.m_transform) {}
+	
+	Mesh &Mesh::operator=(const Mesh &other) {
+		if (&other == this) {
+			return *this;
 		}
+		
+		m_scene = other.m_scene;
+		m_parts = std::vector<MeshPart>(other.m_parts);
+		m_drawcalls = std::vector<DrawcallInfo>(other.m_drawcalls);
+		m_transform = other.m_transform;
+		
+		return *this;
 	}
 	
-	Mesh::Mesh(Scene* scene) :
-	m_scene(scene) {}
+	Mesh &Mesh::operator=(Mesh &&other) noexcept {
+		m_scene = other.m_scene;
+		m_parts = std::move(other.m_parts);
+		m_drawcalls = std::move(other.m_drawcalls);
+		m_transform = other.m_transform;
+		
+		return *this;
+	}
 	
-	void Mesh::load(const asset::Scene &scene, const asset::Mesh &mesh) {
-		for (const auto& vertexGroupIndex : mesh.vertexGroups) {
-			if ((vertexGroupIndex < 0) || (vertexGroupIndex >= scene.vertexGroups.size())) {
-				continue;
-			}
-			
-			MeshPart part (m_scene);
-			part.load(scene, scene.vertexGroups[vertexGroupIndex]);
-			m_parts.push_back(part);
+	void Mesh::recordDrawcalls(std::vector<glm::mat4>& matrices,
+							   std::vector<DrawcallInfo>& drawcalls) {
+		for (const auto& part : m_parts) {
+			matrices.push_back(m_transform);
+		}
+		
+		for (const auto& drawcall : m_drawcalls) {
+			drawcalls.push_back(drawcall);
 		}
 	}
 
diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..316cf673b2525eafaba20abc2f7ad867482cd6da
--- /dev/null
+++ b/modules/scene/src/vkcv/scene/MeshPart.cpp
@@ -0,0 +1,271 @@
+
+#include "vkcv/scene/MeshPart.hpp"
+#include "vkcv/scene/Scene.hpp"
+
+namespace vkcv::scene {
+	
+	MeshPart::MeshPart(Scene* scene) :
+			m_scene(scene),
+			m_vertices(),
+			m_vertexBindings(),
+			m_indices(),
+			m_indexCount(0),
+			m_bounds(),
+			m_materialIndex(std::numeric_limits<size_t>::max()) {}
+	
+	static void loadImage(Core& core, const asset::Scene& asset_scene,
+				   const asset::Texture& asset_texture,
+				   const vk::Format& format,
+				   ImageHandle& image, SamplerHandle& sampler) {
+		asset::Sampler* asset_sampler = nullptr;
+		
+		if ((asset_texture.sampler >= 0) && (asset_texture.sampler < asset_scene.samplers.size())) {
+			//asset_sampler = &(asset_scene.samplers[asset_texture.sampler]); // TODO
+		}
+		
+		Image img = core.createImage(format, asset_texture.w, asset_texture.h);
+		img.fill(asset_texture.data.data());
+		image = img.getHandle();
+		
+		if (asset_sampler) {
+			//sampler = core.createSampler(asset_sampler) // TODO
+		} else {
+			sampler = core.createSampler(
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerMipmapMode::LINEAR,
+					vkcv::SamplerAddressMode::REPEAT
+			);
+		}
+	}
+	
+	static material::Material loadMaterial(Core& core, const asset::Scene& scene,
+									const asset::Material& material) {
+		ImageHandle diffuseImg;
+		SamplerHandle diffuseSmp;
+		
+		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
+			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
+					  diffuseImg,diffuseSmp);
+		}
+		
+		ImageHandle normalImg;
+		SamplerHandle normalSmp;
+		
+		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
+			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
+					  diffuseImg,diffuseSmp);
+		}
+		
+		ImageHandle metalRoughImg;
+		SamplerHandle metalRoughSmp;
+		
+		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
+			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
+					  diffuseImg,diffuseSmp);
+		}
+		
+		ImageHandle occlusionImg;
+		SamplerHandle occlusionSmp;
+		
+		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
+			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
+					  diffuseImg,diffuseSmp);
+		}
+		
+		ImageHandle emissionImg;
+		SamplerHandle emissionSmp;
+		
+		if ((material.baseColor >= 0) && (material.baseColor < scene.textures.size())) {
+			loadImage(core, scene, scene.textures[material.baseColor], vk::Format::eR8G8B8A8Srgb,
+					  diffuseImg,diffuseSmp);
+		}
+		
+		const float colorFactors [4] = {
+				material.baseColorFactor.r,
+				material.baseColorFactor.g,
+				material.baseColorFactor.b,
+				material.baseColorFactor.a
+		};
+		
+		const float emissionFactors[4] = {
+				material.emissiveFactor.r,
+				material.emissiveFactor.g,
+				material.emissiveFactor.b
+		};
+		
+		return material::Material::createPBR(
+				core,
+				diffuseImg, diffuseSmp,
+				normalImg, normalSmp,
+				metalRoughImg, metalRoughSmp,
+				occlusionImg, occlusionSmp,
+				emissionImg, emissionSmp,
+				colorFactors,
+				material.normalScale,
+				material.metallicFactor,
+				material.roughnessFactor,
+				material.occlusionStrength,
+				emissionFactors
+		);
+	}
+	
+	void MeshPart::load(const asset::Scene& scene,
+						const asset::VertexGroup &vertexGroup,
+						std::vector<DrawcallInfo>& drawcalls) {
+		Core& core = *(m_scene->m_core);
+		
+		auto vertexBuffer = core.createBuffer<uint8_t>(
+				BufferType::VERTEX, vertexGroup.vertexBuffer.data.size()
+		);
+		
+		vertexBuffer.fill(vertexGroup.vertexBuffer.data);
+		m_vertices = vertexBuffer.getHandle();
+		
+		auto attributes = vertexGroup.vertexBuffer.attributes;
+		
+		std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
+			return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
+		});
+		
+		for (const auto& attribute : attributes) {
+			m_vertexBindings.emplace_back(attribute.offset, vertexBuffer.getVulkanHandle());
+		}
+		
+		auto indexBuffer = core.createBuffer<uint8_t>(
+				BufferType::INDEX, vertexGroup.indexBuffer.data.size()
+		);
+		
+		indexBuffer.fill(vertexGroup.indexBuffer.data);
+		m_indices = indexBuffer.getHandle();
+		m_indexCount = vertexGroup.numIndices;
+		
+		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())) {
+			m_materialIndex = vertexGroup.materialIndex;
+			
+			auto& material = m_scene->m_materials[m_materialIndex];
+			
+			if (0 == material.m_usages++) {
+				material.m_data = loadMaterial(core, scene, scene.materials[vertexGroup.materialIndex]);
+			}
+		} else {
+			m_materialIndex = std::numeric_limits<size_t>::max();
+		}
+		
+		if (*this) {
+			const auto& material = getMaterial();
+			const auto& descriptorSet = core.getDescriptorSet(material.getDescriptorSet());
+			
+			drawcalls.push_back(DrawcallInfo(
+					vkcv::Mesh(m_vertexBindings, indexBuffer.getVulkanHandle(), m_indexCount),
+					{ DescriptorSetUsage(0, descriptorSet.vulkanHandle) }
+			));
+		}
+	}
+	
+	MeshPart::~MeshPart() {
+		if ((m_scene->m_core) && (m_materialIndex < m_scene->m_materials.size())) {
+			auto& material = m_scene->m_materials[m_materialIndex];
+			
+			if (material.m_usages > 0) {
+				material.m_usages--;
+			}
+		}
+	}
+	
+	MeshPart::MeshPart(const MeshPart &other) :
+	m_scene(other.m_scene),
+	m_vertices(other.m_vertices),
+	m_vertexBindings(other.m_vertexBindings),
+	m_indices(other.m_indices),
+	m_indexCount(other.m_indexCount),
+	m_bounds(other.m_bounds),
+	m_materialIndex(other.m_materialIndex) {
+		if (m_materialIndex < std::numeric_limits<size_t>::max()) {
+			auto& material = m_scene->m_materials[m_materialIndex];
+			
+			material.m_usages++;
+		}
+	}
+	
+	MeshPart::MeshPart(MeshPart &&other) noexcept :
+	m_scene(other.m_scene),
+	m_vertices(other.m_vertices),
+	m_vertexBindings(other.m_vertexBindings),
+	m_indices(other.m_indices),
+	m_indexCount(other.m_indexCount),
+	m_bounds(other.m_bounds),
+	m_materialIndex(other.m_materialIndex) {
+		other.m_materialIndex = std::numeric_limits<size_t>::max();
+	}
+	
+	MeshPart &MeshPart::operator=(const MeshPart &other) {
+		if (&other == this) {
+			return *this;
+		}
+		
+		m_scene = other.m_scene;
+		m_vertices = other.m_vertices;
+		m_vertexBindings = other.m_vertexBindings;
+		m_indices = other.m_indices;
+		m_indexCount = other.m_indexCount;
+		m_bounds = other.m_bounds;
+		m_materialIndex = other.m_materialIndex;
+		
+		return *this;
+	}
+	
+	MeshPart &MeshPart::operator=(MeshPart &&other) noexcept {
+		m_scene = other.m_scene;
+		m_vertices = other.m_vertices;
+		m_vertexBindings = other.m_vertexBindings;
+		m_indices = other.m_indices;
+		m_indexCount = other.m_indexCount;
+		m_bounds = other.m_bounds;
+		m_materialIndex = other.m_materialIndex;
+		
+		other.m_materialIndex = std::numeric_limits<size_t>::max();
+		
+		return *this;
+	}
+	
+	const material::Material & MeshPart::getMaterial() const {
+		static material::Material noMaterial;
+		
+		if (m_materialIndex < m_scene->m_materials.size()) {
+			return m_scene->m_materials[m_materialIndex].m_data;
+		} else {
+			return noMaterial;
+		}
+	}
+	
+	MeshPart::operator bool() const {
+		return (
+				(m_materialIndex < m_scene->m_materials.size()) &&
+				(m_vertices) &&
+				(m_indices)
+		);
+	}
+	
+	bool MeshPart::operator!() const {
+		return (
+				(m_materialIndex >= m_scene->m_materials.size()) ||
+				(!m_vertices) ||
+				(!m_indices)
+		);
+	}
+
+}
diff --git a/modules/scene/src/vkcv/scene/Node.cpp b/modules/scene/src/vkcv/scene/Node.cpp
index c88c91413cbc1551d39f29c708410719647ca7a4..a2f30bb9fed0ba330afb2cf4033ae47ccaf6abe5 100644
--- a/modules/scene/src/vkcv/scene/Node.cpp
+++ b/modules/scene/src/vkcv/scene/Node.cpp
@@ -4,7 +4,44 @@
 namespace vkcv::scene {
 	
 	Node::Node(Scene* scene) :
-	m_scene(scene) {}
+	m_scene(scene),
+	m_meshes(),
+	m_nodes() {}
+	
+	Node::~Node() {
+		m_nodes.clear();
+		m_meshes.clear();
+	}
+	
+	Node::Node(const Node &other) :
+	m_scene(other.m_scene),
+	m_meshes(other.m_meshes),
+	m_nodes(other.m_nodes) {}
+	
+	Node::Node(Node &&other) noexcept :
+	m_scene(other.m_scene),
+	m_meshes(other.m_meshes),
+	m_nodes(other.m_nodes) {}
+	
+	Node &Node::operator=(const Node &other) {
+		if (&other == this) {
+			return *this;
+		}
+		
+		m_scene = other.m_scene;
+		m_meshes = std::vector<Mesh>(other.m_meshes);
+		m_nodes = std::vector<Node>(other.m_nodes);
+		
+		return *this;
+	}
+	
+	Node &Node::operator=(Node &&other) noexcept {
+		m_scene = other.m_scene;
+		m_meshes = std::move(other.m_meshes);
+		m_nodes = std::move(other.m_nodes);
+		
+		return *this;
+	}
 	
 	void Node::loadMesh(const asset::Scene &asset_scene, const asset::Mesh &asset_mesh) {
 		Mesh mesh (m_scene);
@@ -17,5 +54,16 @@ namespace vkcv::scene {
 		m_nodes.push_back(node);
 		return m_nodes.back();
 	}
+	
+	void Node::recordDrawcalls(std::vector<glm::mat4>& matrices,
+							   std::vector<DrawcallInfo>& drawcalls) {
+		for (auto& mesh : m_meshes) {
+			mesh.recordDrawcalls(matrices, drawcalls);
+		}
+		
+		for (auto& node : m_nodes) {
+			node.recordDrawcalls(matrices, drawcalls);
+		}
+	}
 
 }
diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp
index 8ee56ca7204d96823a9b1400be518b4c509950f5..c58125b779232b90634bf6b0dde3a9ffcee13651 100644
--- a/modules/scene/src/vkcv/scene/Scene.cpp
+++ b/modules/scene/src/vkcv/scene/Scene.cpp
@@ -7,7 +7,44 @@
 namespace vkcv::scene {
 	
 	Scene::Scene(Core* core) :
-	m_core(core) {}
+	m_core(core),
+	m_nodes(),
+	m_materials() {}
+	
+	Scene::~Scene() {
+		m_nodes.clear();
+		m_materials.clear();
+	}
+	
+	Scene::Scene(const Scene &other) :
+	m_core(other.m_core),
+	m_materials(other.m_materials),
+	m_nodes(other.m_nodes) {}
+	
+	Scene::Scene(Scene &&other) noexcept :
+	m_core(other.m_core),
+	m_materials(other.m_materials),
+	m_nodes(other.m_nodes) {}
+	
+	Scene &Scene::operator=(const Scene &other) {
+		if (&other == this) {
+			return *this;
+		}
+		
+		m_core = other.m_core;
+		m_materials = std::vector<Material>(other.m_materials);
+		m_nodes = std::vector<Node>(other.m_nodes);
+		
+		return *this;
+	}
+	
+	Scene &Scene::operator=(Scene &&other) noexcept {
+		m_core = other.m_core;
+		m_materials = std::move(other.m_materials);
+		m_nodes = std::move(other.m_nodes);
+		
+		return *this;
+	}
 	
 	Node& Scene::addNode() {
 		Node node (this);
@@ -15,6 +52,48 @@ namespace vkcv::scene {
 		return m_nodes.back();
 	}
 	
+	size_t Scene::getMaterialCount() const {
+		return m_materials.size();
+	}
+	
+	const material::Material & Scene::getMaterial(size_t index) const {
+		static material::Material noMaterial;
+		
+		if (index >= m_materials.size()) {
+			return noMaterial;
+		}
+		
+		return m_materials[index].m_data;
+	}
+	
+	void Scene::recordDrawcalls(CommandStreamHandle       		&cmdStream,
+								const camera::Camera			&camera,
+								const PassHandle                &pass,
+								const PipelineHandle            &pipeline,
+								const std::vector<ImageHandle>  &renderTargets) {
+		std::vector<glm::mat4> matrices;
+		std::vector<DrawcallInfo> drawcalls;
+		
+		for (auto& node : m_nodes) {
+			node.recordDrawcalls(matrices, drawcalls);
+		}
+		
+		for (auto& matrix : matrices) {
+			matrix = camera.getMVP() * matrix;
+		}
+		
+		PushConstantData pushConstantData (matrices.data(), sizeof(glm::mat4));
+		
+		m_core->recordDrawcallsToCmdStream(
+				cmdStream,
+				pass,
+				pipeline,
+				pushConstantData,
+				drawcalls,
+				renderTargets
+		);
+	}
+	
 	Scene Scene::create(Core& core) {
 		return Scene(&core);
 	}
diff --git a/projects/first_scene/CMakeLists.txt b/projects/first_scene/CMakeLists.txt
index 8b90739750011a36b4c1d9e0bff7cba986074228..467663dcb916da78d0625a33c6c88a1af3403af7 100644
--- a/projects/first_scene/CMakeLists.txt
+++ b/projects/first_scene/CMakeLists.txt
@@ -22,7 +22,7 @@ if(MSVC)
 endif()
 
 # including headers of dependencies and the VkCV framework
-target_include_directories(first_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include})
+target_include_directories(first_scene SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_scene_include})
 
 # linking with libraries from all dependencies and the VkCV framework
-target_link_libraries(first_scene vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera)
+target_link_libraries(first_scene vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera vkcv_scene)
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index 420400cdd04865ddd48eec7cf6000e36417d8095..919dc7dd8fbb8312ba2bd97cda5b707652888370 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -5,16 +5,9 @@
 #include <chrono>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/Logger.hpp>
+#include <vkcv/scene/Scene.hpp>
+
 
-glm::mat4 arrayTo4x4Matrix(std::array<float,16> array){
-    glm::mat4 matrix;
-    for (int i = 0; i < 4; i++){
-        for (int j = 0; j < 4; j++){
-            matrix[i][j] = array[j * 4 + i];
-        }
-    }
-    return matrix;
-}
 
 int main(int argc, const char** argv) {
 	const char* applicationName = "First Scene";
@@ -46,66 +39,10 @@ int main(int argc, const char** argv) {
 		{},
 		{ "VK_KHR_swapchain" }
 	);
-
-	vkcv::asset::Scene scene;
-
-	const char* path = argc > 1 ? argv[1] : "resources/Sponza/Sponza.gltf";
-	int result = vkcv::asset::loadScene(path, scene);
-
-	if (result == 1) {
-		std::cout << "Mesh loading successful!" << std::endl;
-	}
-	else {
-		std::cout << "Mesh loading failed: " << result << std::endl;
-		return 1;
-	}
-
-	assert(!scene.vertexGroups.empty());
-	std::vector<std::vector<uint8_t>> vBuffers;
-	std::vector<std::vector<uint8_t>> iBuffers;
-
-	std::vector<vkcv::VertexBufferBinding> vBufferBindings;
-	std::vector<std::vector<vkcv::VertexBufferBinding>> vertexBufferBindings;
-	std::vector<vkcv::asset::VertexAttribute> vAttributes;
-
-	for (int i = 0; i < scene.vertexGroups.size(); i++) {
-
-		vBuffers.push_back(scene.vertexGroups[i].vertexBuffer.data);
-		iBuffers.push_back(scene.vertexGroups[i].indexBuffer.data);
-
-		auto& attributes = scene.vertexGroups[i].vertexBuffer.attributes;
-
-		std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
-			return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
-			});
-	}
-
-	std::vector<vkcv::Buffer<uint8_t>> vertexBuffers;
-	for (const vkcv::asset::VertexGroup& group : scene.vertexGroups) {
-		vertexBuffers.push_back(core.createBuffer<uint8_t>(
-			vkcv::BufferType::VERTEX,
-			group.vertexBuffer.data.size()));
-		vertexBuffers.back().fill(group.vertexBuffer.data);
-	}
-
-	std::vector<vkcv::Buffer<uint8_t>> indexBuffers;
-	for (const auto& dataBuffer : iBuffers) {
-		indexBuffers.push_back(core.createBuffer<uint8_t>(
-			vkcv::BufferType::INDEX,
-			dataBuffer.size()));
-		indexBuffers.back().fill(dataBuffer);
-	}
-
-	int vertexBufferIndex = 0;
-	for (const auto& vertexGroup : scene.vertexGroups) {
-		for (const auto& attribute : vertexGroup.vertexBuffer.attributes) {
-			vAttributes.push_back(attribute);
-			vBufferBindings.push_back(vkcv::VertexBufferBinding(attribute.offset, vertexBuffers[vertexBufferIndex].getVulkanHandle()));
-		}
-		vertexBufferBindings.push_back(vBufferBindings);
-		vBufferBindings.clear();
-		vertexBufferIndex++;
-	}
+	
+	vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path(
+			argc > 1 ? argv[1] : "resources/Sponza/Sponza.gltf"
+	));
 
 	const vkcv::AttachmentDescription present_color_attachment(
 		vkcv::AttachmentOperation::STORE,
@@ -138,41 +75,8 @@ int main(int argc, const char** argv) {
 	}
 
 	const vkcv::VertexLayout sceneLayout(bindings);
-
-	uint32_t setID = 0;
-
-	std::vector<vkcv::DescriptorBinding> descriptorBindings = { sceneShaderProgram.getReflectedDescriptors()[setID] };
-
-	vkcv::SamplerHandle sampler = core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::REPEAT
-	);
-
-	std::vector<vkcv::Image> sceneImages;
-	std::vector<vkcv::DescriptorSetHandle> descriptorSets;
-	for (const auto& vertexGroup : scene.vertexGroups) {
-		descriptorSets.push_back(core.createDescriptorSet(descriptorBindings));
-
-		const auto& material = scene.materials[vertexGroup.materialIndex];
-
-		int baseColorIndex = material.baseColor;
-		if (baseColorIndex < 0) {
-			vkcv_log(vkcv::LogLevel::WARNING, "Material lacks base color");
-			baseColorIndex = 0;
-		}
-
-		vkcv::asset::Texture& sceneTexture = scene.textures[baseColorIndex];
-
-		sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h));
-		sceneImages.back().fill(sceneTexture.data.data());
-
-		vkcv::DescriptorWrites setWrites;
-		setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, sceneImages.back().getHandle()) };
-		setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) };
-		core.writeDescriptorSet(descriptorSets.back(), setWrites);
-	}
+	
+	const auto& material0 = scene.getMaterial(0);
 
 	const vkcv::PipelineConfig scenePipelineDefsinition{
 		sceneShaderProgram,
@@ -180,7 +84,7 @@ int main(int argc, const char** argv) {
 		UINT32_MAX,
 		scenePass,
 		{sceneLayout},
-		{ core.getDescriptorSet(descriptorSets[0]).layout },
+		{ core.getDescriptorSet(material0.getDescriptorSet()).layout },
 		true };
 	vkcv::PipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefsinition);
 	
@@ -193,25 +97,6 @@ int main(int argc, const char** argv) {
 
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 
-    std::vector<vkcv::DrawcallInfo> drawcalls;
-	for(int i = 0; i < scene.vertexGroups.size(); i++){
-        vkcv::Mesh renderMesh(vertexBufferBindings[i], indexBuffers[i].getVulkanHandle(), scene.vertexGroups[i].numIndices);
-
-        vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSets[i]).vulkanHandle);
-
-	    drawcalls.push_back(vkcv::DrawcallInfo(renderMesh, {descriptorUsage}));
-	}
-
-	std::vector<glm::mat4> modelMatrices;
-	modelMatrices.resize(scene.vertexGroups.size(), glm::mat4(1.f));
-	for (const auto &mesh : scene.meshes) {
-		const glm::mat4 m = arrayTo4x4Matrix(mesh.modelMatrix);
-		for (const auto &vertexGroupIndex : mesh.vertexGroups) {
-			modelMatrices[vertexGroupIndex] = m;
-		}
-	}
-	std::vector<glm::mat4> mvp;
-
 	auto start = std::chrono::system_clock::now();
 	while (window.isWindowOpen()) {
         vkcv::Window::pollEvents();
@@ -236,25 +121,16 @@ int main(int argc, const char** argv) {
 		
 		start = end;
 		cameraManager.update(0.000001 * static_cast<double>(deltatime.count()));
-		glm::mat4 vp = cameraManager.getActiveCamera().getMVP();
-
-		mvp.clear();
-        for (const auto& m : modelMatrices) {
-            mvp.push_back(vp * m);
-        }
-
-		vkcv::PushConstantData pushConstantData((void*)mvp.data(), sizeof(glm::mat4));
 
 		const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 
-		core.recordDrawcallsToCmdStream(
-			cmdStream,
-			scenePass,
-			scenePipeline,
-			pushConstantData,
-			drawcalls,
-			renderTargets);
+		scene.recordDrawcalls(cmdStream,
+							  cameraManager.getActiveCamera(),
+							  scenePass,
+							  scenePipeline,
+							  renderTargets);
+		
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);
 		core.endFrame();
diff --git a/src/vkcv/Handles.cpp b/src/vkcv/Handles.cpp
index 020489418c8e2db6ce2062d6fd20f06f90a05c37..65fc02dedeba39953c173103efe9b228f49e5d7f 100644
--- a/src/vkcv/Handles.cpp
+++ b/src/vkcv/Handles.cpp
@@ -1,5 +1,7 @@
 #include "vkcv/Handles.hpp"
 
+#include <iostream>
+
 namespace vkcv {
 	
 	Handle::Handle() :
@@ -11,7 +13,7 @@ namespace vkcv {
 	{}
 	
 	Handle::~Handle() {
-		if ((m_rc) && (--(*m_rc) == 0)) {
+		if ((m_rc) && (*m_rc > 0) && (--(*m_rc) == 0)) {
 			if (m_destroy) {
 				m_destroy(m_id);
 			}
@@ -82,9 +84,9 @@ namespace vkcv {
 	
 	std::ostream& operator << (std::ostream& out, const Handle& handle) {
 		if (handle) {
-			return out << "[Handle: " << handle.getId() << ":" << handle.getRC() << "]";
+			return out << "[" << typeid(handle).name() << ": " << handle.getId() << ":" << handle.getRC() << "]";
 		} else {
-			return out << "[Handle: none]";
+			return out << "[" << typeid(handle).name() << ": none]";
 		}
 	}
 	
diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp
index 4b43b1298a0c997d9769ce3710013e22a6edd0cf..e97e31b557a0e30d172be61b79b049f7272af241 100644
--- a/src/vkcv/Image.cpp
+++ b/src/vkcv/Image.cpp
@@ -53,7 +53,7 @@ namespace vkcv{
 		m_manager->switchImageLayoutImmediate(m_handle, newLayout);
 	}
 
-	vkcv::ImageHandle Image::getHandle() const {
+	const vkcv::ImageHandle& Image::getHandle() const {
 		return m_handle;
 	}