diff --git a/src/Engine/Asset.cpp b/src/Engine/Asset.cpp
index 5a956ace6a267b1da7c9e3d5588c9ac8264baa88..71458652f5638e4f1aa2430e2e5ac02310b42769 100644
--- a/src/Engine/Asset.cpp
+++ b/src/Engine/Asset.cpp
@@ -150,6 +150,11 @@ Asset::TextureDocument Asset::LoadTextureDocument(Sprite texture)
 	return TextureDocument(std::move(createInfo));
 }
 
+Engine::Renderer::MeshDocument Asset::LoadMesh(size_t i)
+{
+	return Engine::Renderer::MeshDocument();
+}
+
 static Asset::MeshDocument::IndexType ToIndexType(fx::gltf::Accessor::ComponentType componentType)
 {
 	switch (componentType)
diff --git a/src/Engine/Asset.hpp b/src/Engine/Asset.hpp
index 6fabdec161c59d54c0242788ab965c18a18753f2..b350dbb76028bba95a15e19ac752864a316f052f 100644
--- a/src/Engine/Asset.hpp
+++ b/src/Engine/Asset.hpp
@@ -8,6 +8,8 @@
 #include <vector>
 #include <array>
 
+#include "Renderer/MeshDocument.hpp"
+
 namespace Asset
 {
 	constexpr std::string_view textureFolderPath = "Data/Textures/";
@@ -29,6 +31,8 @@ namespace Asset
 	MeshDocument LoadMeshDocument(Mesh mesh);
 	MeshDocument LoadMeshDocument(const std::string& path);
 	TextureDocument LoadTextureDocument(Sprite texture);
+
+	Engine::Renderer::MeshDocument LoadMesh(size_t i);
 }
 
 class Asset::MeshDocument
@@ -80,7 +84,6 @@ public:
 	const uint8_t* GetDataPtr(Attribute type) const;
 	Data GetData(Attribute type) const;
 
-private:
 	std::vector<uint8_t> byteArray;
 	std::array<Data, static_cast<size_t>(Attribute::COUNT)> data;
 	IndexType indexType;
diff --git a/src/Engine/Engine.cpp b/src/Engine/Engine.cpp
index 38ccf4f182eb76f663110f23d23662e403e7b8cf..3485afaa8eaade7e4de8b876a4e5d0c3d2485006 100644
--- a/src/Engine/Engine.cpp
+++ b/src/Engine/Engine.cpp
@@ -23,6 +23,8 @@
 
 #include <iostream>
 
+std::vector<std::unique_ptr<Engine::Scene>> Engine::Core::scenes;
+
 class ScriptTest : public Engine::Components::ScriptBase
 {
 	using ParentType = Engine::Components::ScriptBase;
@@ -52,7 +54,28 @@ void rendererDebugCallback(std::string_view message)
 	std::cout << "Renderer log: " << message << std::endl;
 }
 
-std::vector<std::unique_ptr<Engine::Scene>> Engine::Core::scenes;
+namespace Engine
+{
+	void InitializeRenderer()
+	{
+		// Initialize renderer
+		Renderer::InitInfo rendererInitInfo;
+
+		rendererInitInfo.preferredAPI = Renderer::API::OpenGL;
+
+		// Debug info
+		rendererInitInfo.debugInitInfo.useDebugging = true;
+		rendererInitInfo.debugInitInfo.errorMessageCallback = rendererDebugCallback;
+
+		rendererInitInfo.surfaceDimensions = Application::GetWindowSize();
+		rendererInitInfo.surfaceHandle = Application::Core::GetMainWindowHandle();
+
+		rendererInitInfo.assetLoadCreateInfo.meshLoader = &Asset::LoadMesh;
+
+		rendererInitInfo.openGLInitInfo.glSwapBuffers = &Application::Core::GL_SwapWindow;
+		Renderer::Core::Initialize(rendererInitInfo);
+	}
+}
 
 void Engine::Core::Run()
 {
@@ -61,14 +84,7 @@ void Engine::Core::Run()
 	Input::Core::Initialize();
 	Physics2D::Core::Initialize();
 
-	// Initialize renderer
-	Renderer::CreateInfo rendererCreateInfo;
-	rendererCreateInfo.preferredAPI = Renderer::API::OpenGL;
-	rendererCreateInfo.surfaceDimensions = Application::GetWindowSize();
-	rendererCreateInfo.surfaceHandle = Application::Core::GetMainWindowHandle();
-	rendererCreateInfo.debugCreateInfo.errorMessageCallback = rendererDebugCallback;
-	rendererCreateInfo.openGLCreateInfo.glSwapBuffers = Application::Core::GL_SwapWindow;
-	Renderer::Core::Initialize(std::move(rendererCreateInfo));
+	InitializeRenderer();
 
 
 	// Create scene and make viewport 0 point to scene 0.
diff --git a/src/Engine/Renderer/MeshDocument.hpp b/src/Engine/Renderer/MeshDocument.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..501fd3e5eca3b2755afd778dde962356e229b40c
--- /dev/null
+++ b/src/Engine/Renderer/MeshDocument.hpp
@@ -0,0 +1,99 @@
+#pragma once
+
+#include <cstddef>
+#include <array>
+
+namespace Engine
+{
+	namespace Renderer
+	{
+		class MeshDocument
+		{
+		public:
+			using PositionType = std::array<float, 3>;
+			using UVType = std::array<float, 2>;
+			using NormalType = std::array<float, 3>;
+			using TangentType = std::array<float, 3>;
+
+			enum class IndexType
+			{
+				UInt16,
+				UInt32
+			};
+
+			static uint8_t ToByteSize(IndexType type);
+
+			struct DataInfo
+			{
+				size_t byteOffset;
+				size_t byteLength;
+			};
+
+			enum class Attribute
+			{
+				Position,
+				TexCoord,
+				Normal,
+				Tangent,
+				Index,
+				COUNT
+			};
+
+			struct CreateInfo
+			{
+				std::vector<uint8_t> byteArray;
+				DataInfo posData;
+				DataInfo uvData;
+				DataInfo normalData;
+				DataInfo tangentData;
+				DataInfo indexData;
+				IndexType indexType;
+			};
+
+			MeshDocument(CreateInfo&& createInfo);
+			MeshDocument() = default;
+
+			DataInfo GetData(Attribute attr) const;
+			const uint8_t* GetDataPtr(Attribute attr) const;
+
+			IndexType GetIndexType() const;
+			uint32_t GetIndexCount() const;
+
+			size_t GetTotalByteLength() const;
+
+			IndexType indexType;
+			std::vector<uint8_t> byteArray;
+			std::array<DataInfo, static_cast<size_t>(Attribute::COUNT)> data;	
+		};
+
+		inline MeshDocument::DataInfo MeshDocument::GetData(Attribute attr) const
+		{
+			return data.at(static_cast<size_t>(attr));
+		}
+
+		inline const uint8_t* MeshDocument::GetDataPtr(Attribute attr) const
+		{
+			return byteArray.data() + GetData(attr).byteOffset;
+		}
+
+		inline MeshDocument::IndexType MeshDocument::GetIndexType() const
+		{
+			return indexType;
+		}
+
+		inline uint32_t MeshDocument::GetIndexCount() const
+		{
+			return uint32_t( GetData( Attribute::Index).byteLength / ToByteSize(GetIndexType() ) );
+		}
+
+		inline size_t MeshDocument::GetTotalByteLength() const
+		{
+			return data.size();
+		}
+
+		inline uint8_t MeshDocument::ToByteSize(IndexType type)
+		{
+			return type == IndexType::UInt16 ? uint8_t(2) : uint8_t(4);
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/Engine/Renderer/OpenGL.cpp b/src/Engine/Renderer/OpenGL.cpp
index b9fb42d355c478c1c21b19814ced71433aaba64b..9459f736a7b7985b01fa466f11a4f9d76aa81830 100644
--- a/src/Engine/Renderer/OpenGL.cpp
+++ b/src/Engine/Renderer/OpenGL.cpp
@@ -1,9 +1,8 @@
 #include "Renderer.hpp"
 #include "RendererData.hpp"
+#include "MeshDocument.hpp"
 #include "OpenGL.hpp"
 
-#include "../Asset.hpp"
-
 #include "GL/glew.h"
 
 #include <cassert>
@@ -36,7 +35,7 @@ namespace Engine
 			struct LightDataUBO;
 
 			void UpdateVBODatabase(Data& data, const std::vector<MeshID>& loadQueue);
-			std::optional<VBO> VBOFromPath(const std::string& path);
+			std::optional<VBO> VBOFromPath(size_t id);
 			void UpdateIBODatabase(Data& data, const std::vector<SpriteID>& loadQueue);
 
 			Data& GetAPIData();
@@ -51,504 +50,499 @@ namespace Engine
 			void GLDebugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
 		}
 	}
-}
 
-struct Engine::Renderer::OpenGL::CameraDataUBO
-{
-	Math::Vector3D wsPosition;
-	float padding1;
-	Math::Matrix<4, 4, float> viewProjection;
-};
+	struct Renderer::OpenGL::CameraDataUBO
+	{
+		Math::Vector3D wsPosition;
+		float padding1;
+		Math::Matrix<4, 4, float> viewProjection;
+	};
 
-struct Engine::Renderer::OpenGL::LightDataUBO
-{
-	Math::Vector4D ambientLight;
-	uint32_t pointLightCount;
-	std::array<uint32_t, 3> padding1;
-	std::array<Math::Vector4D, 10> pointLightIntensity;
-	std::array<Math::Vector4D, 10> pointLightPos;
-};
-
-struct Engine::Renderer::OpenGL::VertexBufferObject
-{
-	enum class Attribute
+	struct Renderer::OpenGL::LightDataUBO
 	{
-		Position,
-		TexCoord,
-		Normal,
-		Index,
-		COUNT
+		Math::Vector4D ambientLight;
+		uint32_t pointLightCount;
+		std::array<uint32_t, 3> padding1;
+		std::array<Math::Vector4D, 10> pointLightIntensity;
+		std::array<Math::Vector4D, 10> pointLightPos;
 	};
-	
-	void DeallocateDeviceBuffers();
 
-	GLuint vertexArrayObject;
-	std::array<GLuint, static_cast<size_t>(Attribute::COUNT)> attributeBuffers;
-	uint32_t numIndices;
-	GLenum indexType;
-};
+	struct Renderer::OpenGL::VertexBufferObject
+	{
+		enum class Attribute
+		{
+			Position,
+			TexCoord,
+			Normal,
+			Index,
+			COUNT
+		};
+
+		void DeallocateDeviceBuffers();
+
+		GLuint vertexArrayObject;
+		std::array<GLuint, static_cast<size_t>(Attribute::COUNT)> attributeBuffers;
+		uint32_t numIndices;
+		GLenum indexType;
+	};
 
-struct Engine::Renderer::OpenGL::ImageBufferObject
-{
-	void DeallocateDeviceBuffers();
-	GLuint texture;
-};
+	struct Renderer::OpenGL::ImageBufferObject
+	{
+		void DeallocateDeviceBuffers();
+		GLuint texture;
+	};
 
-struct Engine::Renderer::OpenGL::Data
-{
-	std::function<void(void*)> glSwapBuffers;
+	struct Renderer::OpenGL::Data
+	{
+		std::function<void(void*)> glSwapBuffers;
 
-	std::unordered_map<MeshID, VBO> vboDatabase;
-	VBO quadVBO;
+		std::unordered_map<MeshID, VBO> vboDatabase;
+		VBO quadVBO;
 
-	std::unordered_map<SpriteID, IBO> iboDatabase;
+		std::unordered_map<SpriteID, IBO> iboDatabase;
 
-	GLuint cameraDataUBO;
-	GLuint lightDataUBO;
-	GLuint samplerObject;
+		GLuint cameraDataUBO;
+		GLuint lightDataUBO;
+		GLuint samplerObject;
 
-	GLuint spriteProgram;
-	GLint spriteModelUniform;
-	GLint spriteSamplerUniform;
+		GLuint spriteProgram;
+		GLint spriteModelUniform;
+		GLint spriteSamplerUniform;
 
-	GLuint meshProgram;
-	GLint meshModelUniform;
-};
+		GLuint meshProgram;
+		GLint meshModelUniform;
+	};
 
-Engine::Renderer::OpenGL::Data& Engine::Renderer::OpenGL::GetAPIData() { return std::any_cast<Data&>(Core::GetAPIData()); }
+	Renderer::OpenGL::Data& Renderer::OpenGL::GetAPIData() { return std::any_cast<Data&>(Core::GetAPIData()); }
 
-static std::string LoadShader(const std::string& fileName)
-{
-	std::ifstream file;
-	file.open((fileName).c_str());
+	static std::string LoadShader(const std::string& fileName)
+	{
+		std::ifstream file;
+		file.open((fileName).c_str());
 
-	std::string output;
-	std::string line;
+		std::string output;
+		std::string line;
 
-	if (file.is_open())
-	{
-		while (file.good())
+		if (file.is_open())
 		{
-			getline(file, line);
-			output.append(line + "\n");
+			while (file.good())
+			{
+				getline(file, line);
+				output.append(line + "\n");
+			}
+		}
+		else
+		{
+			Renderer::LogDebugMessage("Unable to load shader : " + fileName);
 		}
-	}
-	else
-	{
-		if (Engine::Renderer::Core::GetData().debugData.errorMessageCallback)
-			Engine::Renderer::Core::GetData().debugData.errorMessageCallback("Unable to load shader : " + fileName);
 
+		return output;
 	}
 
-	return output;
-}
-
-static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage)
-{
-	GLint success = 0;
-	GLchar error[1024] = { 0 };
-
-	if (isProgram)
-		glGetProgramiv(shader, flag, &success);
-	else
-		glGetShaderiv(shader, flag, &success);
-
-	if (success == GL_FALSE)
+	static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage)
 	{
+		GLint success = 0;
+		GLchar error[1024] = { 0 };
+
 		if (isProgram)
-			glGetProgramInfoLog(shader, sizeof(error), NULL, error);
+			glGetProgramiv(shader, flag, &success);
 		else
-			glGetShaderInfoLog(shader, sizeof(error), NULL, error);
+			glGetShaderiv(shader, flag, &success);
 
-		if (Engine::Renderer::Core::GetData().debugData.errorMessageCallback)
-			Engine::Renderer::Core::GetData().debugData.errorMessageCallback(errorMessage + ": '" + error);
-	}
-}
-
-static GLuint CreateShader(const std::string& text, GLuint type)
-{
-	GLuint shader = glCreateShader(type);
+		if (success == GL_FALSE)
+		{
+			if (isProgram)
+				glGetProgramInfoLog(shader, sizeof(error), NULL, error);
+			else
+				glGetShaderInfoLog(shader, sizeof(error), NULL, error);
 
-	if (shader == 0)
-	{
-		if (Engine::Renderer::Core::GetData().debugData.errorMessageCallback)
-			Engine::Renderer::Core::GetData().debugData.errorMessageCallback("Error compiling shader type " + type);
+			Renderer::LogDebugMessage(errorMessage + ": '" + error);
+		}
 	}
 
-	const GLchar* p[1];
-	p[0] = text.c_str();
-	GLint lengths[1];
-	lengths[0] = static_cast<GLint>(text.length());
-
-	glShaderSource(shader, 1, p, lengths);
-	glCompileShader(shader);
-
-	std::string test = "Error compiling ";
-	if (type == GL_VERTEX_SHADER)
-	    test += "vertex";
-    else if (type == GL_FRAGMENT_SHADER)
-        test += "fragment";
-    test += " shader";
-	CheckShaderError(shader, GL_COMPILE_STATUS, false, test);
+	static GLuint CreateShader(const std::string& text, GLuint type)
+	{
+		GLuint shader = glCreateShader(type);
 
-	return shader;
-}
+		if (shader == 0)
+			Renderer::LogDebugMessage("Error compiling shader type " + type);
 
-void Engine::Renderer::OpenGL::LoadSpriteShader(Data& data)
-{
-	// Create shader
-	data.spriteProgram = glCreateProgram();
+		const GLchar* p[1];
+		p[0] = text.c_str();
+		GLint lengths[1];
+		lengths[0] = static_cast<GLint>(text.length());
 
-	std::array<GLuint, 2> shaders{};
-	shaders[0] = CreateShader(LoadShader("Data/Shaders/Sprite/sprite.vert"), GL_VERTEX_SHADER);
-	shaders[1] = CreateShader(LoadShader("Data/Shaders/Sprite/sprite.frag"), GL_FRAGMENT_SHADER);
+		glShaderSource(shader, 1, p, lengths);
+		glCompileShader(shader);
 
-	for (unsigned int i = 0; i < 2; i++)
-		glAttachShader(data.spriteProgram, shaders[i]);
+		std::string test = "Error compiling ";
+		if (type == GL_VERTEX_SHADER)
+			test += "vertex";
+		else if (type == GL_FRAGMENT_SHADER)
+			test += "fragment";
+		test += " shader";
+		CheckShaderError(shader, GL_COMPILE_STATUS, false, test);
 
-	glLinkProgram(data.spriteProgram);
-	CheckShaderError(data.spriteProgram, GL_LINK_STATUS, true, "Error linking shader program");
+		return shader;
+	}
 
-	glValidateProgram(data.spriteProgram);
-	CheckShaderError(data.spriteProgram, GL_LINK_STATUS, true, "Invalid shader program");
+	void Renderer::OpenGL::LoadSpriteShader(Data& data)
+	{
+		// Create shader
+		data.spriteProgram = glCreateProgram();
 
-	for (unsigned int i = 0; i < 2; i++)
-		glDeleteShader(shaders[i]);
+		std::array<GLuint, 2> shaders{};
+		shaders[0] = CreateShader(LoadShader("Data/Shaders/Sprite/sprite.vert"), GL_VERTEX_SHADER);
+		shaders[1] = CreateShader(LoadShader("Data/Shaders/Sprite/sprite.frag"), GL_FRAGMENT_SHADER);
 
-	// Grab uniforms
-	data.spriteModelUniform = glGetUniformLocation(data.spriteProgram, "model");
+		for (unsigned int i = 0; i < 2; i++)
+			glAttachShader(data.spriteProgram, shaders[i]);
 
-	data.spriteSamplerUniform = glGetUniformLocation(data.spriteProgram, "sampler");
-}
+		glLinkProgram(data.spriteProgram);
+		CheckShaderError(data.spriteProgram, GL_LINK_STATUS, true, "Error linking shader program");
 
-void Engine::Renderer::OpenGL::LoadMeshShader(Engine::Renderer::OpenGL::Data &data)
-{
-	// Create shader
-	data.meshProgram = glCreateProgram();
+		glValidateProgram(data.spriteProgram);
+		CheckShaderError(data.spriteProgram, GL_LINK_STATUS, true, "Invalid shader program");
 
-	std::array<GLuint, 2> shader{};
-	shader[0] = CreateShader(LoadShader("Data/Shaders/Mesh/Mesh.vert"), GL_VERTEX_SHADER);
-	shader[1] = CreateShader(LoadShader("Data/Shaders/Mesh/Mesh.frag"), GL_FRAGMENT_SHADER);
+		for (unsigned int i = 0; i < 2; i++)
+			glDeleteShader(shaders[i]);
 
-	for (unsigned int i = 0; i < 2; i++)
-		glAttachShader(data.meshProgram, shader[i]);
+		// Grab uniforms
+		data.spriteModelUniform = glGetUniformLocation(data.spriteProgram, "model");
 
-	glLinkProgram(data.meshProgram);
-	CheckShaderError(data.meshProgram, GL_LINK_STATUS, true, "Error linking shader program");
+		data.spriteSamplerUniform = glGetUniformLocation(data.spriteProgram, "sampler");
+	}
 
-	glValidateProgram(data.meshProgram);
-	CheckShaderError(data.meshProgram, GL_LINK_STATUS, true, "Invalid shader program");
+	void Renderer::OpenGL::LoadMeshShader(Engine::Renderer::OpenGL::Data &data)
+	{
+		// Create shader
+		data.meshProgram = glCreateProgram();
 
-	for (unsigned int i = 0; i < 2; i++)
-		glDeleteShader(shader[i]);
+		std::array<GLuint, 2> shader{};
+		shader[0] = CreateShader(LoadShader("Data/Shaders/Mesh/Mesh.vert"), GL_VERTEX_SHADER);
+		shader[1] = CreateShader(LoadShader("Data/Shaders/Mesh/Mesh.frag"), GL_FRAGMENT_SHADER);
 
-	// Grab uniforms
-	data.meshModelUniform = glGetUniformLocation(data.meshProgram, "model");
+		for (unsigned int i = 0; i < 2; i++)
+			glAttachShader(data.meshProgram, shader[i]);
 
-	glUniformBlockBinding(data.meshProgram, 1, 1);
-}
+		glLinkProgram(data.meshProgram);
+		CheckShaderError(data.meshProgram, GL_LINK_STATUS, true, "Error linking shader program");
 
-void Engine::Renderer::OpenGL::CreateStandardUBOs(Data& data)
-{
-	std::array<GLuint, 2> buffers;
-	glGenBuffers(2, buffers.data());
+		glValidateProgram(data.meshProgram);
+		CheckShaderError(data.meshProgram, GL_LINK_STATUS, true, "Invalid shader program");
 
-	data.cameraDataUBO = buffers[0];
-	data.lightDataUBO = buffers[1];
+		for (unsigned int i = 0; i < 2; i++)
+			glDeleteShader(shader[i]);
 
-	// Make camera ubo
-	glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO);
-	glNamedBufferData(data.cameraDataUBO, sizeof(CameraDataUBO), nullptr, GL_DYNAMIC_DRAW);
-	glBindBufferRange(GL_UNIFORM_BUFFER, 0, data.cameraDataUBO, 0, sizeof(CameraDataUBO));
+		// Grab uniforms
+		data.meshModelUniform = glGetUniformLocation(data.meshProgram, "model");
 
-	// Make light ubo
-	glBindBuffer(GL_UNIFORM_BUFFER, data.lightDataUBO);
-	glNamedBufferData(data.lightDataUBO, sizeof(LightDataUBO), nullptr, GL_DYNAMIC_DRAW);
-	glBindBufferRange(GL_UNIFORM_BUFFER, 1, data.lightDataUBO, 0, sizeof(LightDataUBO));
-}
+		glUniformBlockBinding(data.meshProgram, 1, 1);
+	}
 
-void Engine::Renderer::OpenGL::GLDebugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
-{
-	Core::GetData().debugData.errorMessageCallback(message);
-}
+	void Renderer::OpenGL::CreateStandardUBOs(Data& data)
+	{
+		std::array<GLuint, 2> buffers;
+		glGenBuffers(2, buffers.data());
 
-void Engine::Renderer::OpenGL::Initialize(std::any& apiData, CreateInfo&& createInfo)
-{
-	auto glInitResult = glewInit();
-	assert(glInitResult == 0);
+		data.cameraDataUBO = buffers[0];
+		data.lightDataUBO = buffers[1];
 
-	apiData = std::make_any<Data>();
-	Data& data = std::any_cast<Data&>(apiData);
+		// Make camera ubo
+		glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO);
+		glNamedBufferData(data.cameraDataUBO, sizeof(CameraDataUBO), nullptr, GL_DYNAMIC_DRAW);
+		glBindBufferRange(GL_UNIFORM_BUFFER, 0, data.cameraDataUBO, 0, sizeof(CameraDataUBO));
 
-	data.glSwapBuffers = std::move(createInfo.glSwapBuffers);
+		// Make light ubo
+		glBindBuffer(GL_UNIFORM_BUFFER, data.lightDataUBO);
+		glNamedBufferData(data.lightDataUBO, sizeof(LightDataUBO), nullptr, GL_DYNAMIC_DRAW);
+		glBindBufferRange(GL_UNIFORM_BUFFER, 1, data.lightDataUBO, 0, sizeof(LightDataUBO));
+	}
 
-	// Initialize debug stuff
-	if (Core::GetData().debugData.errorMessageCallback)
+	void Renderer::OpenGL::GLDebugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
 	{
-		GLint flags;
-		glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
-		if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
-		{
-			glEnable(GL_DEBUG_OUTPUT);
-			glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
-			glDebugMessageCallback(&GLDebugOutputCallback, nullptr);
-			glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
-		}
-		else
-			Core::GetData().debugData.errorMessageCallback("Error. Couldn't make GL Debug Output");
+		LogDebugMessage(message);
 	}
-	
-
-	CreateStandardUBOs(data);
-
-	// Gen sampler
-	glGenSamplers(1, &data.samplerObject);
-	glSamplerParameteri(data.samplerObject, GL_TEXTURE_WRAP_S, GL_REPEAT);
-	glSamplerParameteri(data.samplerObject, GL_TEXTURE_WRAP_T, GL_REPEAT);
-	glSamplerParameteri(data.samplerObject, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glSamplerParameteri(data.samplerObject, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
-	// Load sprite VBO
-	auto quadVBOOpt = VBOFromPath(static_cast<std::string>(Renderer::Setup::assetPath) + "/Meshes/SpritePlane/SpritePlane.gltf");
-	if (quadVBOOpt.has_value())
-		data.quadVBO = quadVBOOpt.value();
-	else
-		assert(false);
-
-	glEnable(GL_DEPTH_TEST);
-
-	glEnable(GL_CULL_FACE);
-	glCullFace(GL_BACK);
+	void Renderer::OpenGL::Initialize(std::any& apiData, const InitInfo& createInfo)
+	{
+		auto glInitResult = glewInit();
+		assert(glInitResult == 0);
 
-	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+		apiData = std::make_any<Data>();
+		Data& data = std::any_cast<Data&>(apiData);
 
+		data.glSwapBuffers = std::move(createInfo.glSwapBuffers);
 
+		// Initialize debug stuff
+		if constexpr (Setup::enableDebugging)
+		{
+			if (Core::GetData().debugData.useDebugging)
+			{
+				GLint flags;
+				glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
+				if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
+				{
+					glEnable(GL_DEBUG_OUTPUT);
+					glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+					glDebugMessageCallback(&GLDebugOutputCallback, nullptr);
+					glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
+				}
+				else
+					LogDebugMessage("Error. Couldn't make GL Debug Output");
+			}
+		}
+		
+
+		CreateStandardUBOs(data);
+
+		// Gen sampler
+		glGenSamplers(1, &data.samplerObject);
+		glSamplerParameteri(data.samplerObject, GL_TEXTURE_WRAP_S, GL_REPEAT);
+		glSamplerParameteri(data.samplerObject, GL_TEXTURE_WRAP_T, GL_REPEAT);
+		glSamplerParameteri(data.samplerObject, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glSamplerParameteri(data.samplerObject, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+		// Load sprite VBO
+		/*
+		auto quadVBOOpt = VBOFromPath(static_cast<std::string>(Renderer::Setup::assetPath) + "/Meshes/SpritePlane/SpritePlane.gltf");
+		if (quadVBOOpt.has_value())
+			data.quadVBO = quadVBOOpt.value();
+		else
+			assert(false);
+			*/
 
-	//LoadSpriteShader(data);
-	LoadMeshShader(data);
-}
+		glEnable(GL_DEPTH_TEST);
 
-void Engine::Renderer::OpenGL::Terminate(std::any& apiData)
-{
-	Data& data = std::any_cast<Data&>(apiData);
+		glEnable(GL_CULL_FACE);
+		glCullFace(GL_BACK);
 
-	data.quadVBO.DeallocateDeviceBuffers();
-	for (auto& vboItem : data.vboDatabase)
-		vboItem.second.DeallocateDeviceBuffers();
+		//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
-	for (auto& iboItem : data.vboDatabase)
-		iboItem.second.DeallocateDeviceBuffers();
 
-	glDeleteProgram(data.spriteProgram);
-	glDeleteProgram(data.meshProgram);
 
-	//delete static_cast<Data*>(apiData);
-	//apiData = nullptr;
-}
+		//LoadSpriteShader(data);
+		LoadMeshShader(data);
+	}
 
-void Engine::Renderer::OpenGL::PrepareRenderingEarly(const std::vector<SpriteID>& spriteLoadQueue, const std::vector<MeshID>& meshLoadQueue)
-{
-	Data& data = GetAPIData();
+	void Renderer::OpenGL::Terminate(std::any& apiData)
+	{
+		Data& data = std::any_cast<Data&>(apiData);
 
-	UpdateIBODatabase(data, spriteLoadQueue);
-	UpdateVBODatabase(data, meshLoadQueue);
+		data.quadVBO.DeallocateDeviceBuffers();
+		for (auto& vboItem : data.vboDatabase)
+			vboItem.second.DeallocateDeviceBuffers();
 
-	const auto& renderGraph = Core::GetRenderGraph();
+		for (auto& iboItem : data.vboDatabase)
+			iboItem.second.DeallocateDeviceBuffers();
 
-	// Update ambient light
-	constexpr GLintptr ambientLightOffset = offsetof(LightDataUBO, LightDataUBO::ambientLight);
-	glNamedBufferSubData(data.lightDataUBO, ambientLightOffset, sizeof(renderGraph.ambientLight), renderGraph.ambientLight.Data());
+		glDeleteProgram(data.spriteProgram);
+		glDeleteProgram(data.meshProgram);
 
-	// Update light count
-	auto pointLightCount = static_cast<uint32_t>(renderGraph.pointLights.size());
-	constexpr GLintptr pointLightCountDataOffset = offsetof(LightDataUBO, LightDataUBO::pointLightCount);
-	glNamedBufferSubData(data.lightDataUBO, pointLightCountDataOffset, sizeof(pointLightCount), &pointLightCount);
+		//delete static_cast<Data*>(apiData);
+		//apiData = nullptr;
+	}
 
-	// Update intensities
-	const size_t elements = Math::Min(10, renderGraph.pointLights.size());
-	std::array<Math::Vector4D, 10> intensityData;
-	for (size_t i = 0; i < elements; i++)
-		intensityData[i] = renderGraph.pointLights[i].AsVec4();
-	size_t byteLength = sizeof(Math::Vector4D) * elements;
-	constexpr GLintptr pointLightIntensityOffset = offsetof(LightDataUBO, LightDataUBO::pointLightIntensity);
-	glNamedBufferSubData(data.lightDataUBO, pointLightIntensityOffset, byteLength, intensityData.data());
-}
+	void Renderer::OpenGL::PrepareRenderingEarly(const std::vector<SpriteID>& spriteLoadQueue, const std::vector<MeshID>& meshLoadQueue)
+	{
+		Data& data = GetAPIData();
+
+		UpdateIBODatabase(data, spriteLoadQueue);
+		UpdateVBODatabase(data, meshLoadQueue);
+
+		const auto& renderGraph = Core::GetRenderGraph();
+
+		// Update ambient light
+		constexpr GLintptr ambientLightOffset = offsetof(LightDataUBO, LightDataUBO::ambientLight);
+		glNamedBufferSubData(data.lightDataUBO, ambientLightOffset, sizeof(renderGraph.ambientLight), renderGraph.ambientLight.Data());
+
+		// Update light count
+		auto pointLightCount = static_cast<uint32_t>(renderGraph.pointLights.size());
+		constexpr GLintptr pointLightCountDataOffset = offsetof(LightDataUBO, LightDataUBO::pointLightCount);
+		glNamedBufferSubData(data.lightDataUBO, pointLightCountDataOffset, sizeof(pointLightCount), &pointLightCount);
+
+		// Update intensities
+		const size_t elements = Math::Min(10, renderGraph.pointLights.size());
+		std::array<Math::Vector4D, 10> intensityData;
+		for (size_t i = 0; i < elements; i++)
+			intensityData[i] = renderGraph.pointLights[i].AsVec4();
+		size_t byteLength = sizeof(Math::Vector4D) * elements;
+		constexpr GLintptr pointLightIntensityOffset = offsetof(LightDataUBO, LightDataUBO::pointLightIntensity);
+		glNamedBufferSubData(data.lightDataUBO, pointLightIntensityOffset, byteLength, intensityData.data());
+	}
 
-void Engine::Renderer::OpenGL::PrepareRenderingLate()
-{
-	Data& data = GetAPIData();
-
-	const auto& renderGraphTransform = Core::GetRenderGraphTransform();
-
-	// Update lights positions
-	const size_t elements = Math::Min(10, renderGraphTransform.pointLights.size());
-	std::array<Math::Vector4D, 10> posData;
-	for (size_t i = 0; i < elements; i++)
-		posData[i] = renderGraphTransform.pointLights[i].AsVec4();
-	size_t byteLength = sizeof(Math::Vector4D) * elements;
-	constexpr GLintptr pointLightPosDataOffset = offsetof(LightDataUBO, LightDataUBO::pointLightPos);
-	glNamedBufferSubData(data.lightDataUBO, pointLightPosDataOffset, byteLength, posData.data());
-
-	auto& viewport = Renderer::GetViewport(0);
-
-	// Update camera UBO
-	auto& cameraInfo = Renderer::Core::GetCameraInfo();
-	const Math::Vector3D& cameraWSPosition = cameraInfo.worldSpacePos;
-	constexpr GLintptr cameraWSPositionDataOffset = offsetof(CameraDataUBO, CameraDataUBO::wsPosition);
-	glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO);
-	glBufferSubData(GL_UNIFORM_BUFFER, cameraWSPositionDataOffset, sizeof(cameraWSPosition), cameraWSPosition.Data());
-
-	auto viewMatrix = cameraInfo.GetModel(viewport.GetDimensions().GetAspectRatio());
-	constexpr GLintptr cameraViewProjectionDataOffset = offsetof(CameraDataUBO, CameraDataUBO::viewProjection);
-	glBufferSubData(GL_UNIFORM_BUFFER, cameraViewProjectionDataOffset, sizeof(viewMatrix), viewMatrix.Data());
-}
-
-void Engine::Renderer::OpenGL::Draw()
-{
-	Data& data = GetAPIData();
+	void Renderer::OpenGL::PrepareRenderingLate()
+	{
+		Data& data = GetAPIData();
+
+		const auto& renderGraphTransform = Core::GetRenderGraphTransform();
+
+		// Update lights positions
+		const size_t elements = Math::Min(10, renderGraphTransform.pointLights.size());
+		std::array<Math::Vector4D, 10> posData;
+		for (size_t i = 0; i < elements; i++)
+			posData[i] = renderGraphTransform.pointLights[i].AsVec4();
+		size_t byteLength = sizeof(Math::Vector4D) * elements;
+		constexpr GLintptr pointLightPosDataOffset = offsetof(LightDataUBO, LightDataUBO::pointLightPos);
+		glNamedBufferSubData(data.lightDataUBO, pointLightPosDataOffset, byteLength, posData.data());
+
+		auto& viewport = Renderer::GetViewport(0);
+
+		// Update camera UBO
+		auto& cameraInfo = Renderer::Core::GetCameraInfo();
+		const Math::Vector3D& cameraWSPosition = cameraInfo.worldSpacePos;
+		constexpr GLintptr cameraWSPositionDataOffset = offsetof(CameraDataUBO, CameraDataUBO::wsPosition);
+		glBindBuffer(GL_UNIFORM_BUFFER, data.cameraDataUBO);
+		glBufferSubData(GL_UNIFORM_BUFFER, cameraWSPositionDataOffset, sizeof(cameraWSPosition), cameraWSPosition.Data());
+
+		auto viewMatrix = cameraInfo.GetModel(viewport.GetDimensions().GetAspectRatio());
+		constexpr GLintptr cameraViewProjectionDataOffset = offsetof(CameraDataUBO, CameraDataUBO::viewProjection);
+		glBufferSubData(GL_UNIFORM_BUFFER, cameraViewProjectionDataOffset, sizeof(viewMatrix), viewMatrix.Data());
+	}
 
-	glClearColor(0.25f, 0.f, 0.f, 1.f);
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	void Renderer::OpenGL::Draw()
+	{
+		Data& data = GetAPIData();
 
+		glClearColor(0.25f, 0.f, 0.f, 1.f);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-	const auto& renderGraph = Core::GetRenderGraph();
-	const auto& renderGraphTransform = Core::GetRenderGraphTransform();
 
-	Draw_SpritePass(data, renderGraph.sprites, renderGraphTransform.sprites);
-	Draw_MeshPass(data, renderGraph.meshes, renderGraphTransform.meshes);
+		const auto& renderGraph = Core::GetRenderGraph();
+		const auto& renderGraphTransform = Core::GetRenderGraphTransform();
 
-	auto& viewport = Renderer::GetViewport(0);
+		Draw_SpritePass(data, renderGraph.sprites, renderGraphTransform.sprites);
+		Draw_MeshPass(data, renderGraph.meshes, renderGraphTransform.meshes);
 
-	data.glSwapBuffers(viewport.GetSurfaceHandle());
-}
+		auto& viewport = Renderer::GetViewport(0);
 
-void Engine::Renderer::OpenGL::Draw_SpritePass(const Data& data,
-		 									   const std::vector<SpriteID>& sprites,
-											   const std::vector<Math::Matrix4x4>& transforms)
-{
-	auto& viewport = Renderer::GetViewport(0);
+		data.glSwapBuffers(viewport.GetSurfaceHandle());
+	}
 
-	// Sprite render pass
-	if (!sprites.empty())
+	void Renderer::OpenGL::Draw_SpritePass(const Data& data,
+										   const std::vector<SpriteID>& sprites,
+										   const std::vector<Math::Matrix4x4>& transforms)
 	{
-		glUseProgram(data.spriteProgram);
+		auto& viewport = Renderer::GetViewport(0);
 
-		glProgramUniform1ui(data.spriteProgram, data.spriteSamplerUniform, 0);
-		glBindSampler(0, data.samplerObject);
+		// Sprite render pass
+		if (!sprites.empty())
+		{
+			glUseProgram(data.spriteProgram);
 
-		const auto& spriteVBO = data.quadVBO;
-		glBindVertexArray(spriteVBO.vertexArrayObject);
+			glProgramUniform1ui(data.spriteProgram, data.spriteSamplerUniform, 0);
+			glBindSampler(0, data.samplerObject);
 
-		for (size_t i = 0; i < sprites.size(); i++)
-		{
-			glProgramUniformMatrix4fv(data.spriteProgram, data.spriteModelUniform, 1, GL_FALSE, transforms[i].data.data());
+			const auto& spriteVBO = data.quadVBO;
+			glBindVertexArray(spriteVBO.vertexArrayObject);
 
-			glActiveTexture(GL_TEXTURE0);
-			const IBO& ibo = data.iboDatabase.at(sprites[i]);
-			glBindTexture(GL_TEXTURE_2D, ibo.texture);
+			for (size_t i = 0; i < sprites.size(); i++)
+			{
+				glProgramUniformMatrix4fv(data.spriteProgram, data.spriteModelUniform, 1, GL_FALSE, transforms[i].data.data());
+
+				glActiveTexture(GL_TEXTURE0);
+				const IBO& ibo = data.iboDatabase.at(sprites[i]);
+				glBindTexture(GL_TEXTURE_2D, ibo.texture);
 
-			glDrawElements(GL_TRIANGLES, spriteVBO.numIndices, spriteVBO.indexType, nullptr);
+				glDrawElements(GL_TRIANGLES, spriteVBO.numIndices, spriteVBO.indexType, nullptr);
+			}
 		}
 	}
-}
 
-void Engine::Renderer::OpenGL::Draw_MeshPass(const Engine::Renderer::OpenGL::Data &data,
-											 const std::vector<Engine::Renderer::MeshID> &meshes,
-											 const std::vector<Math::Matrix4x4> &transforms)
-{
-	auto& viewport = Renderer::GetViewport(0);
-
-	if (!meshes.empty())
+	void Renderer::OpenGL::Draw_MeshPass(const Engine::Renderer::OpenGL::Data &data,
+										 const std::vector<Engine::Renderer::MeshID> &meshes,
+									     const std::vector<Math::Matrix4x4> &transforms)
 	{
-		glUseProgram(data.meshProgram);
+		auto& viewport = Renderer::GetViewport(0);
 
-		for (size_t i = 0; i < meshes.size(); i++)
+		if (!meshes.empty())
 		{
-			glProgramUniformMatrix4fv(data.meshProgram, data.meshModelUniform, 1, GL_FALSE, transforms[i].data.data());
+			glUseProgram(data.meshProgram);
+
+			for (size_t i = 0; i < meshes.size(); i++)
+			{
+				glProgramUniformMatrix4fv(data.meshProgram, data.meshModelUniform, 1, GL_FALSE, transforms[i].data.data());
 
-			const VBO& vbo = data.vboDatabase.at(meshes[i]);
-			glBindVertexArray(vbo.vertexArrayObject);
+				const VBO& vbo = data.vboDatabase.at(meshes[i]);
+				glBindVertexArray(vbo.vertexArrayObject);
 
-			glDrawElements(GL_TRIANGLES, vbo.numIndices, vbo.indexType, nullptr);
+				glDrawElements(GL_TRIANGLES, vbo.numIndices, vbo.indexType, nullptr);
+			}
 		}
 	}
-}
 
-
-void Engine::Renderer::OpenGL::UpdateVBODatabase(Data& data, const std::vector<MeshID>& loadQueue)
-{
-	for (const auto& id : loadQueue)
+	void Renderer::OpenGL::UpdateVBODatabase(Data& data, const std::vector<MeshID>& loadQueue)
 	{
-		std::string path = Asset::GetPath(static_cast<Asset::Mesh>(id));
-
-		auto vboOpt = VBOFromPath(path);
-		assert(vboOpt.has_value());
+		for (const auto& id : loadQueue)
+		{
+			auto vboOpt = VBOFromPath(static_cast<size_t>(id));
+			assert(vboOpt.has_value());
 
-		data.vboDatabase.insert({ id, vboOpt.value() });
+			data.vboDatabase.insert({ id, vboOpt.value() });
+		}
 	}
-}
 
-void Engine::Renderer::OpenGL::UpdateIBODatabase(Data& data, const std::vector<SpriteID>& loadQueue)
-{
-	glActiveTexture(GL_TEXTURE0);
-	for (const auto& id : loadQueue)
+	void Renderer::OpenGL::UpdateIBODatabase(Data& data, const std::vector<SpriteID>& loadQueue)
 	{
-		auto texDocument = Asset::LoadTextureDocument(static_cast<Asset::Sprite>(id));
+		glActiveTexture(GL_TEXTURE0);
+		for (const auto& id : loadQueue)
+		{
+			/*auto texDocument = Asset::LoadTextureDocument(static_cast<Asset::Sprite>(id));
 
-		IBO ibo;
+			IBO ibo;
 
-		glGenTextures(1, &ibo.texture);
-		glBindTexture(GL_TEXTURE_2D, ibo.texture);
+			glGenTextures(1, &ibo.texture);
+			glBindTexture(GL_TEXTURE_2D, ibo.texture);
 
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texDocument.GetDimensions().width, texDocument.GetDimensions().height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDocument.GetData());
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texDocument.GetDimensions().width, texDocument.GetDimensions().height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texDocument.GetData());
 
-		data.iboDatabase.insert({ id, ibo });
+			data.iboDatabase.insert({ id, ibo });*/
+		}
 	}
-}
 
-void Engine::Renderer::OpenGL::VBO::DeallocateDeviceBuffers()
-{
-	glDeleteBuffers(static_cast<GLint>(attributeBuffers.size()), attributeBuffers.data());
-	glDeleteVertexArrays(1, &vertexArrayObject);
-}
+	void Renderer::OpenGL::VBO::DeallocateDeviceBuffers()
+	{
+		glDeleteBuffers(static_cast<GLint>(attributeBuffers.size()), attributeBuffers.data());
+		glDeleteVertexArrays(1, &vertexArrayObject);
+	}
 
-void Engine::Renderer::OpenGL::IBO::ImageBufferObject::DeallocateDeviceBuffers()
-{
-	glDeleteTextures(1, &texture);
-}
+	void Renderer::OpenGL::IBO::ImageBufferObject::DeallocateDeviceBuffers()
+	{
+		glDeleteTextures(1, &texture);
+	}
 
-std::optional<Engine::Renderer::OpenGL::VBO> Engine::Renderer::OpenGL::VBOFromPath(const std::string& path)
-{
-	using namespace Asset;
-	auto meshDocument = LoadMeshDocument(path);
+	std::optional<Renderer::OpenGL::VBO> Renderer::OpenGL::VBOFromPath(size_t id)
+	{
+		const auto meshDocument = Core::GetData().assetLoadData.meshLoader(id);
 
-	VBO vbo;
+		VBO vbo;
 
-	vbo.indexType = meshDocument.GetIndexType() == MeshDocument::IndexType::Uint16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-	vbo.numIndices = meshDocument.GetIndexCount();
+		vbo.indexType = meshDocument.GetIndexType() == MeshDocument::IndexType::UInt16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+		vbo.numIndices = meshDocument.GetIndexCount();
 
-	glGenVertexArrays(1, &vbo.vertexArrayObject);
-	glBindVertexArray(vbo.vertexArrayObject);
+		glGenVertexArrays(1, &vbo.vertexArrayObject);
+		glBindVertexArray(vbo.vertexArrayObject);
 
-	glGenBuffers(static_cast<GLint>(vbo.attributeBuffers.size()), vbo.attributeBuffers.data());
+		glGenBuffers(static_cast<GLint>(vbo.attributeBuffers.size()), vbo.attributeBuffers.data());
 
-	glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Position)]);
-	glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Position).byteLength, meshDocument.GetDataPtr(Asset::MeshDocument::Attribute::Position), GL_STATIC_DRAW);
-	glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::Position));
-	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Position)]);
+		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Position).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::Position), GL_STATIC_DRAW);
+		glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::Position));
+		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
-	glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::TexCoord)]);
-	glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::TexCoord).byteLength, meshDocument.GetDataPtr(Asset::MeshDocument::Attribute::TexCoord), GL_STATIC_DRAW);
-	glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::TexCoord));
-	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
+		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::TexCoord)]);
+		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::TexCoord).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::TexCoord), GL_STATIC_DRAW);
+		glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::TexCoord));
+		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
 
-	glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Normal)]);
-	glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Normal).byteLength, meshDocument.GetDataPtr(Asset::MeshDocument::Attribute::Normal), GL_STATIC_DRAW);
-	glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::Normal));
-	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
+		glBindBuffer(GL_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Normal)]);
+		glBufferData(GL_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Normal).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::Normal), GL_STATIC_DRAW);
+		glEnableVertexAttribArray(static_cast<size_t>(VBO::Attribute::Normal));
+		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Index)]);
-	glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshDocument.GetData(Asset::MeshDocument::Attribute::Index).byteLength, meshDocument.GetDataPtr(Asset::MeshDocument::Attribute::Index), GL_STATIC_DRAW);
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.attributeBuffers[static_cast<size_t>(VBO::Attribute::Index)]);
+		glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshDocument.GetData(MeshDocument::Attribute::Index).byteLength, meshDocument.GetDataPtr(MeshDocument::Attribute::Index), GL_STATIC_DRAW);
 
-	return vbo;
+		return vbo;
+	}
 }
\ No newline at end of file
diff --git a/src/Engine/Renderer/OpenGL.hpp b/src/Engine/Renderer/OpenGL.hpp
index 901d5ebf85f8b4f39f56d2a07b0850b422d55500..e7f51e2e6a1ee24c2302fe2f5ceb54c3e86659d4 100644
--- a/src/Engine/Renderer/OpenGL.hpp
+++ b/src/Engine/Renderer/OpenGL.hpp
@@ -11,7 +11,7 @@ namespace Engine
 	{
 		namespace OpenGL
 		{
-			void Initialize(std::any& apiData, CreateInfo&& createInfo);
+			void Initialize(std::any& apiData, const InitInfo& createInfo);
 			void Terminate(std::any& apiData);
 			void PrepareRenderingEarly(const std::vector<SpriteID>& spriteLoadQueue, const std::vector<MeshID>& meshLoadQueue);
 			void PrepareRenderingLate();
diff --git a/src/Engine/Renderer/OpenGLCreateInfo.hpp b/src/Engine/Renderer/OpenGLCreateInfo.hpp
index 30809c3375be71f417801dfe7a553f0ae3bfb751..d4c764f15c76107c7f9d89cf7f297dfbb1e78138 100644
--- a/src/Engine/Renderer/OpenGLCreateInfo.hpp
+++ b/src/Engine/Renderer/OpenGLCreateInfo.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "Typedefs.hpp"
 #include <functional>
 
 namespace Engine
@@ -8,10 +9,12 @@ namespace Engine
 	{
 		namespace OpenGL
 		{
-			struct CreateInfo
+			struct InitInfo
 			{
 				std::function<void(void*)> glSwapBuffers;
 			};
+
+			bool IsValid(const InitInfo& initInfo, ErrorMessageCallbackPFN callback);
 		}
 	}
 }
\ No newline at end of file
diff --git a/src/Engine/Renderer/Renderer.cpp b/src/Engine/Renderer/Renderer.cpp
index 8cdecf09a849b61a75f3a24316b7141dfdc46f15..4677f1a36b2c4911443f1a93ef0deec48668292e 100644
--- a/src/Engine/Renderer/Renderer.cpp
+++ b/src/Engine/Renderer/Renderer.cpp
@@ -16,226 +16,331 @@ namespace Engine
 			static std::unique_ptr<Data> data;
 
 			void UpdateAssetReferences(Data& data, const RenderGraph& oldRG, const RenderGraph* newRG);
+
+			bool IsValid(const InitInfo& createInfo, ErrorMessageCallbackPFN callback);
 		}
 	}
-}
 
-const Engine::Renderer::Core::Data& Engine::Renderer::Core::GetData()
-{
-	return *data;
-}
+	bool Renderer::Core::IsValid(const InitInfo& createInfo, ErrorMessageCallbackPFN callback)
+	{
+		const auto& DebugMessage = [callback](const char* message)
+		{
+			if (callback)
+				callback(message);
+		};
 
-Engine::Renderer::Viewport& Engine::Renderer::NewViewport(Utility::ImgDim dimensions, void* surfaceHandle)
-{
-	Core::data->viewports.emplace_back(std::make_unique<Viewport>(dimensions, surfaceHandle));
-	return *Core::data->viewports.back();
-}
+		if (createInfo.surfaceHandle == nullptr)
+		{
+			DebugMessage("Error. InitInfo needs a window/surface handle.");
+			return false;
+		}
 
-size_t Engine::Renderer::GetViewportCount() { return Core::data->viewports.size(); }
+		if (createInfo.surfaceDimensions[0] == 0 || createInfo.surfaceDimensions[1] == 1)
+		{
+			DebugMessage("Error. InitInfo::surfaceDimensions can't have any dimension(s) with value 0.");
+			return false;
+		}
 
-Engine::Renderer::Viewport& Engine::Renderer::GetViewport(size_t index) { return *Core::data->viewports[index]; }
+		// Asset load stuff
+		if (createInfo.assetLoadCreateInfo.meshLoader == nullptr)
+		{
+			DebugMessage("Error. MeshLoader pointer in initialization cannot be nullptr.");
+			return false;
+		}
 
-Engine::Renderer::API Engine::Renderer::GetActiveAPI()
-{
-	if (Core::data)
-		return Core::data->activeAPI;
-	else
-		return API::None;
-}
+		// Debug stuff
+		if (createInfo.debugInitInfo.useDebugging == true)
+		{
+			const DebugCreateInfo& debugInfo = createInfo.debugInitInfo;
+			if (debugInfo.errorMessageCallback == nullptr)
+			{
+				DebugMessage("Error. DebugCreateInfo::errorMessageCallback cannot be nullptr when DebugCreateInfo::enableDebug is true.");
+				return false;
+			}
+		}
+
+		switch (createInfo.preferredAPI)
+		{
+		case API::OpenGL:
+			if (IsValid(createInfo.openGLInitInfo, createInfo.debugInitInfo.errorMessageCallback) == true)
+				break;
+			else
+				return false;
+		default:
+			DebugMessage("Error. InitInfo::preferredAPI can't be set to 'API::None'");
+			return false;
+		}
 
-std::any& Engine::Renderer::Core::GetAPIData() { return data->apiData; }
+		return true;
+	}
 
-bool Engine::Renderer::Core::Initialize(CreateInfo&& createInfo)
-{
-	Core::data = std::make_unique<Data>();
-	Data& data = *Core::data;
+	bool Renderer::OpenGL::IsValid(const InitInfo& initInfo, ErrorMessageCallbackPFN callback)
+	{
+		const auto& DebugMessage = [callback](const char* message)
+		{
+			if (callback)
+				callback(message);
+		};
 
-	data.activeAPI = createInfo.preferredAPI;
+		if (initInfo.glSwapBuffers == nullptr)
+		{
+			DebugMessage("Error. Renderer::OpenGL::InitInfo must point to a valid function.");
+			return false;
+		}
 
-	data.debugData = std::move(createInfo.debugCreateInfo);
+		return true;
+	}
 
-	NewViewport(createInfo.surfaceDimensions, createInfo.surfaceHandle);
+	const Renderer::Core::Data& Engine::Renderer::Core::GetData()
+	{
+		return *data;
+	}
 
-	switch (data.activeAPI)
+	Renderer::Viewport& Engine::Renderer::NewViewport(Utility::ImgDim dimensions, void* surfaceHandle)
 	{
-	case API::OpenGL:
-		OpenGL::Initialize(data.apiData, std::move(createInfo.openGLCreateInfo));
-		data.Draw = OpenGL::Draw;
-		data.PrepareRenderingEarly = OpenGL::PrepareRenderingEarly;
-		data.PrepareRenderingLate = OpenGL::PrepareRenderingLate;
-		break;
-	default:
-		break;
+		Core::data->viewports.emplace_back(std::make_unique<Viewport>(dimensions, surfaceHandle));
+		return *Core::data->viewports.back();
 	}
 
-	return true;
-}
+	size_t Renderer::GetViewportCount() { return Core::data->viewports.size(); }
 
-void Engine::Renderer::Core::Terminate()
-{
-	switch (GetActiveAPI())
+	Renderer::Viewport& Renderer::GetViewport(size_t index) { return *Core::data->viewports[index]; }
+
+	Renderer::API Renderer::GetActiveAPI()
 	{
-	case API::OpenGL:
-		OpenGL::Terminate(data->apiData);
-		break;
-	default:
-		break;
+		if (Core::data)
+			return Core::data->activeAPI;
+		else
+			return API::None;
 	}
 
-	data = nullptr;
-}
+	std::any& Renderer::Core::GetAPIData() { return data->apiData; }
 
-void Engine::Renderer::Core::PrepareRenderingEarly(RenderGraph& renderGraphInput)
-{
-	Data& data = *Core::data;
+	bool Renderer::Core::Initialize(const InitInfo& createInfo)
+	{
+		if constexpr (Setup::enableDebugging)
+		{
+			if (createInfo.debugInitInfo.useDebugging)
+			{
+				bool valid = IsValid(createInfo, createInfo.debugInitInfo.errorMessageCallback);
+				if (!valid)
+					LogDebugMessage("Error. InitInfo is not valid.");
+				assert(valid);
+			}
+		}
 
-    auto& renderGraph = data.renderGraph;
+		Core::data = std::make_unique<Data>();
+		Data& data = *Core::data;
 
-	UpdateAssetReferences(data, renderGraph, &renderGraphInput);
+		// Debug info
+		if constexpr (Setup::enableDebugging)
+		{
+			data.debugData = createInfo.debugInitInfo;
+		}
 
-	std::swap(renderGraph, renderGraphInput);
+		data.activeAPI = createInfo.preferredAPI;
 
-	if (!data.loadSpriteQueue.empty() || !data.loadMeshQueue.empty())
-		data.debugData.errorMessageCallback("Loading sprite/mesh resource(s)...");
-	data.PrepareRenderingEarly(data.loadSpriteQueue, data.loadMeshQueue);
+		data.assetLoadData = createInfo.assetLoadCreateInfo;
 
-	data.loadSpriteQueue.clear();
-	data.unloadSpriteQueue.clear();
-	data.loadMeshQueue.clear();
-	data.unloadMeshQueue.clear();
-}
+		NewViewport(createInfo.surfaceDimensions, createInfo.surfaceHandle);
 
-void Engine::Renderer::Core::PrepareRenderingLate(RenderGraphTransform &input)
-{
-	const auto& renderGraph = data->renderGraph;
-	auto& renderGraphTransform = data->renderGraphTransform;
+		switch (data.activeAPI)
+		{
+		case API::OpenGL:
+			OpenGL::Initialize(data.apiData, createInfo.openGLInitInfo);
+			data.Draw = OpenGL::Draw;
+			data.PrepareRenderingEarly = OpenGL::PrepareRenderingEarly;
+			data.PrepareRenderingLate = OpenGL::PrepareRenderingLate;
+			break;
+		default:
+			break;
+		}
 
-	assert(IsCompatible(renderGraph, input));
+		return true;
+	}
 
-	std::swap(renderGraphTransform, input);
+	void Renderer::Core::Terminate()
+	{
+		switch (GetActiveAPI())
+		{
+		case API::OpenGL:
+			OpenGL::Terminate(data->apiData);
+			break;
+		default:
+			break;
+		}
 
-	data->PrepareRenderingLate();
-}
+		data = nullptr;
+	}
 
-void Engine::Renderer::Core::Draw()
-{
-	data->Draw();
-}
+	void Renderer::Core::PrepareRenderingEarly(RenderGraph& renderGraphInput)
+	{
+		Data& data = *Core::data;
 
-const Engine::Renderer::RenderGraph &Engine::Renderer::Core::GetRenderGraph()
-{
-	return data->renderGraph;
-}
+		auto& renderGraph = data.renderGraph;
 
-const Engine::Renderer::RenderGraphTransform &Engine::Renderer::Core::GetRenderGraphTransform()
-{
-	return data->renderGraphTransform;
-}
+		UpdateAssetReferences(data, renderGraph, &renderGraphInput);
 
-const Engine::Renderer::CameraInfo &Engine::Renderer::Core::GetCameraInfo()
-{
-	return data->cameraInfo;
-}
+		std::swap(renderGraph, renderGraphInput);
 
-void Engine::Renderer::Core::SetCameraInfo(const CameraInfo &input)
-{
-	data->cameraInfo = input;
-}
+		if (!data.loadSpriteQueue.empty() || !data.loadMeshQueue.empty())
+			LogDebugMessage("Loading sprite/mesh resource(s)...");
+		data.PrepareRenderingEarly(data.loadSpriteQueue, data.loadMeshQueue);
 
-Engine::Renderer::SceneData::SceneData()
-{
-    sceneID = Core::data->sceneIDCounter;
-    Core::data->sceneIDCounter++;
-}
-
-Engine::Renderer::Viewport::Viewport(Utility::ImgDim dimensions, void* surfaceHandle) :
-	sceneRef(nullptr),
-	cameraIndex(0),
-	dimensions(dimensions),
-	surfaceHandle(surfaceHandle)
-{
-}
+		data.loadSpriteQueue.clear();
+		data.unloadSpriteQueue.clear();
+		data.loadMeshQueue.clear();
+		data.unloadMeshQueue.clear();
+	}
 
-Utility::ImgDim Engine::Renderer::Viewport::GetDimensions() const { return dimensions; }
+	void Renderer::Core::PrepareRenderingLate(RenderGraphTransform &input)
+	{
+		Data& data = *Core::data;
 
-size_t Engine::Renderer::Viewport::GetCameraIndex() const { return cameraIndex; }
+		const auto& renderGraph = data.renderGraph;
+		auto& renderGraphTransform = data.renderGraphTransform;
 
-void* Engine::Renderer::Viewport::GetSurfaceHandle() { return surfaceHandle; }
+		if constexpr (Setup::enableDebugging)
+		{
+			if (data.debugData.useDebugging)
+			{
+				bool compatible = IsCompatible(renderGraph, input);
+				if (!compatible)
+				{
+					LogDebugMessage("Error. Newly submitted RenderGraphTransform is not compatible with previously submitted RenderGraph.");
+					assert(false);
+				}
+			}
+		}
 
-void Engine::Renderer::Viewport::SetSceneRef(const Engine::Renderer::SceneType* scene)
-{
-	sceneRef = scene;
-}
+		std::swap(renderGraphTransform, input);
 
-bool Engine::Renderer::IsCompatible(const RenderGraph &renderGraph, const RenderGraphTransform &transforms)
-{
-	if (renderGraph.sprites.size() != transforms.sprites.size())
-		return false;
+		data.PrepareRenderingLate();
+	}
 
-	if (renderGraph.meshes.size() != transforms.meshes.size())
-		return false;
+	void Renderer::Core::Draw()
+	{
+		data->Draw();
+	}
 
-	if (renderGraph.pointLights.size() != transforms.pointLights.size())
-		return false;
+	const Renderer::RenderGraph &Renderer::Core::GetRenderGraph()
+	{
+		return data->renderGraph;
+	}
 
-	return true;
-}
+	const Renderer::RenderGraphTransform &Renderer::Core::GetRenderGraphTransform()
+	{
+		return data->renderGraphTransform;
+	}
 
-void Engine::Renderer::Core::UpdateAssetReferences(Data& data, const RenderGraph& oldRG, const RenderGraph* newRG)
-{
-	// Add new references
-	if (newRG)
+	const Renderer::CameraInfo &Renderer::Core::GetCameraInfo()
 	{
-		// Sprites
-		for(const auto& item : newRG->sprites)
-		{
-			auto& referenceCount = data.spriteReferences[item];
-			referenceCount++;
-			if (referenceCount == 1)
-				data.loadSpriteQueue.emplace_back(item);
-		}
+		return data->cameraInfo;
+	}
 
-		// Meshes
-		for (const auto& item : newRG->meshes)
-		{
-			auto& referenceCount = data.meshReferences[item];
-			referenceCount++;
-			if (referenceCount == 1)
-				data.loadMeshQueue.emplace_back(item);
-		}
+	void Renderer::Core::SetCameraInfo(const CameraInfo &input)
+	{
+		data->cameraInfo = input;
 	}
 
-	// Remove existing references
-	for (const auto& item : oldRG.sprites)
+	Renderer::Viewport::Viewport(Utility::ImgDim dimensions, void* surfaceHandle) :
+		sceneRef(nullptr),
+		cameraIndex(0),
+		dimensions(dimensions),
+		surfaceHandle(surfaceHandle)
 	{
-		auto iterator = data.spriteReferences.find(item);
-		iterator->second--;
-		if (iterator->second <= 0)
+	}
+
+	Utility::ImgDim Renderer::Viewport::GetDimensions() const { return dimensions; }
+
+	size_t Renderer::Viewport::GetCameraIndex() const { return cameraIndex; }
+
+	void* Renderer::Viewport::GetSurfaceHandle() { return surfaceHandle; }
+
+	void Renderer::Viewport::SetSceneRef(const Renderer::SceneType* scene)
+	{
+		sceneRef = scene;
+	}
+
+	bool Renderer::IsCompatible(const RenderGraph &renderGraph, const RenderGraphTransform &transforms)
+	{
+		if (renderGraph.sprites.size() != transforms.sprites.size())
+			return false;
+
+		if (renderGraph.meshes.size() != transforms.meshes.size())
+			return false;
+
+		if (renderGraph.pointLights.size() != transforms.pointLights.size())
+			return false;
+
+		return true;
+	}
+
+	void Renderer::LogDebugMessage(std::string_view message)
+	{
+		if constexpr (Setup::enableDebugging)
 		{
-			data.unloadSpriteQueue.emplace_back(item);
-			data.spriteReferences.erase(iterator);
+			const Core::Data& data = *Core::data;
+			if (data.debugData.useDebugging)
+				data.debugData.errorMessageCallback(message);
 		}
 	}
 
-	for (const auto& item : oldRG.meshes)
+	void Renderer::Core::UpdateAssetReferences(Data& data, const RenderGraph& oldRG, const RenderGraph* newRG)
 	{
-		auto iterator = data.meshReferences.find(item);
-		iterator->second--;
-		if (iterator->second <= 0)
+		// Add new references
+		if (newRG)
+		{
+			// Sprites
+			for (const auto& item : newRG->sprites)
+			{
+				auto& referenceCount = data.spriteReferences[item];
+				referenceCount++;
+				if (referenceCount == 1)
+					data.loadSpriteQueue.emplace_back(item);
+			}
+
+			// Meshes
+			for (const auto& item : newRG->meshes)
+			{
+				auto& referenceCount = data.meshReferences[item];
+				referenceCount++;
+				if (referenceCount == 1)
+					data.loadMeshQueue.emplace_back(item);
+			}
+		}
+
+		// Remove existing references
+		for (const auto& item : oldRG.sprites)
+		{
+			auto iterator = data.spriteReferences.find(item);
+			iterator->second--;
+			if (iterator->second <= 0)
+			{
+				data.unloadSpriteQueue.emplace_back(item);
+				data.spriteReferences.erase(iterator);
+			}
+		}
+
+		for (const auto& item : oldRG.meshes)
 		{
-			data.unloadMeshQueue.emplace_back(item);
-			data.meshReferences.erase(iterator);
+			auto iterator = data.meshReferences.find(item);
+			iterator->second--;
+			if (iterator->second <= 0)
+			{
+				data.unloadMeshQueue.emplace_back(item);
+				data.meshReferences.erase(iterator);
+			}
 		}
 	}
-}
 
-Math::Matrix4x4 Engine::Renderer::CameraInfo::GetModel(float aspectRatio) const
-{
-	using namespace Math::LinTran3D;
-	if (projectMode == ProjectionMode::Perspective)
+	Math::Matrix4x4 Renderer::CameraInfo::GetModel(float aspectRatio) const
 	{
-		switch (GetActiveAPI())
+		using namespace Math::LinTran3D;
+		if (projectMode == ProjectionMode::Perspective)
 		{
+			switch (GetActiveAPI())
+			{
 			case API::OpenGL:
 				return Perspective<float>(Math::API3D::OpenGL, fovY, aspectRatio, zNear, zFar) * transform;
 			case API::Vulkan:
@@ -243,16 +348,16 @@ Math::Matrix4x4 Engine::Renderer::CameraInfo::GetModel(float aspectRatio) const
 			default:
 				assert(false);
 				return {};
+			}
 		}
-	}
-	else if (projectMode == ProjectionMode::Orthographic)
-	{
-		const float& right = orthoWidth / 2;
-		const float& left = -right;
-		const float& top = orthoWidth / aspectRatio / 2;
-		const float& bottom = -top;
-		switch (GetActiveAPI())
+		else if (projectMode == ProjectionMode::Orthographic)
 		{
+			const float& right = orthoWidth / 2;
+			const float& left = -right;
+			const float& top = orthoWidth / aspectRatio / 2;
+			const float& bottom = -top;
+			switch (GetActiveAPI())
+			{
 			case API::OpenGL:
 				return Orthographic<float>(Math::API3D::OpenGL, left, right, bottom, top, zNear, zFar);
 			case API::Vulkan:
@@ -260,10 +365,11 @@ Math::Matrix4x4 Engine::Renderer::CameraInfo::GetModel(float aspectRatio) const
 			default:
 				assert(false);
 				return {};
+			}
 		}
-	}
 
-	// Function should NOT reach here.
-	assert(false);
-	return {};
+		// Function should NOT reach here.
+		assert(false);
+		return {};
+	}
 }
\ No newline at end of file
diff --git a/src/Engine/Renderer/Renderer.hpp b/src/Engine/Renderer/Renderer.hpp
index cdfcf978bf6c55726f887d366c61e161498f1776..a7242b18ca8b3c5c6f8bbbc03d3d4803a8999d4b 100644
--- a/src/Engine/Renderer/Renderer.hpp
+++ b/src/Engine/Renderer/Renderer.hpp
@@ -20,7 +20,7 @@ namespace Engine
 	namespace Renderer
 	{
 		using SceneType = Setup::SceneType;
-
+		
 		Viewport& NewViewport(Utility::ImgDim dimensions, void* surfaceHandle);
 		size_t GetViewportCount();
 		Viewport& GetViewport(size_t index);
@@ -29,9 +29,12 @@ namespace Engine
 
 		bool IsCompatible(const RenderGraph& renderGraph, const RenderGraphTransform& transforms);
 
+		// This call is thread-safe if ErrorMessageCallback supplied to InitInfo is.
+		void LogDebugMessage(std::string_view message);
+
 		namespace Core
 		{
-			bool Initialize(CreateInfo&& createInfo);
+			bool Initialize(const InitInfo& createInfo);
 			void PrepareRenderingEarly(RenderGraph& renderGraphInput);
 			void PrepareRenderingLate(RenderGraphTransform& sceneData);
 			void Draw();
@@ -53,18 +56,26 @@ namespace Engine
 
 	struct Renderer::DebugCreateInfo
 	{
-		std::function<void(std::string_view)> errorMessageCallback;
+		bool useDebugging = false;
+		ErrorMessageCallbackPFN errorMessageCallback = nullptr;
+	};
+
+	struct Renderer::AssetLoadCreateInfo
+	{
+		using MeshLoaderPFN = MeshDocument(*)(size_t);
+		MeshLoaderPFN meshLoader = nullptr;
 	};
 
-	struct Renderer::CreateInfo
+	struct Renderer::InitInfo
 	{
 		API preferredAPI = API::None;
 		Utility::ImgDim surfaceDimensions;
 		void* surfaceHandle = nullptr;
 
-		DebugCreateInfo debugCreateInfo;
+		AssetLoadCreateInfo assetLoadCreateInfo;
+		DebugCreateInfo debugInitInfo;
 
-		OpenGL::CreateInfo openGLCreateInfo;
+		OpenGL::InitInfo openGLInitInfo;
 	};
 
 	struct Renderer::RenderGraph
@@ -83,16 +94,6 @@ namespace Engine
 		std::vector<Math::Vector<3, float>> pointLights;
 	};
 
-	class Renderer::SceneData
-	{
-	public:
-	    SceneData();
-
-        size_t GetSceneID() const;
-	private:
-		size_t sceneID;
-	};
-
 	struct Renderer::CameraInfo
 	{
 		enum class ProjectionMode
diff --git a/src/Engine/Renderer/RendererData.hpp b/src/Engine/Renderer/RendererData.hpp
index 37d25cdc733e0499bbfec92bdc14f7b8afb8330c..f83cdff303c868835f356b30bbdb55325e111172 100644
--- a/src/Engine/Renderer/RendererData.hpp
+++ b/src/Engine/Renderer/RendererData.hpp
@@ -19,8 +19,6 @@ namespace Engine
 				RenderGraphTransform renderGraphTransform;
 				CameraInfo cameraInfo;
 
-				size_t sceneIDCounter = 0;
-
 				API activeAPI = API::None;
 
 				std::unordered_map<MeshID, size_t> meshReferences;
@@ -37,8 +35,10 @@ namespace Engine
 				std::function<void(const std::vector<SpriteID>&, const std::vector<MeshID>&)> PrepareRenderingEarly;
 				std::function<void(void)> PrepareRenderingLate;
 
+				AssetLoadCreateInfo assetLoadData;
 				DebugCreateInfo debugData;
 
+
 				std::any apiData = nullptr;
 			};
 
diff --git a/src/Engine/Renderer/Setup.hpp b/src/Engine/Renderer/Setup.hpp
index c7d6cd402419adf41b14e58ae34c3bc2b47a6f62..a065681f2afa850fcfd0b8fbae4805416a925d0a 100644
--- a/src/Engine/Renderer/Setup.hpp
+++ b/src/Engine/Renderer/Setup.hpp
@@ -12,6 +12,8 @@ namespace Engine
 		{
 			using SceneType = Engine::Scene;
 
+			constexpr bool enableDebugging = true;
+
 			constexpr std::string_view assetPath = "Data/DRenderer";
 		}
 	}
diff --git a/src/Engine/Renderer/Typedefs.hpp b/src/Engine/Renderer/Typedefs.hpp
index 9410bd065c11f7efab678c6859ba7a670eae4233..f2c34df31bf14a605d36ebbcc0fa9674c8dff8d0 100644
--- a/src/Engine/Renderer/Typedefs.hpp
+++ b/src/Engine/Renderer/Typedefs.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <cstdint>
+#include <functional>
 
 namespace Engine
 {
@@ -11,15 +12,21 @@ namespace Engine
 			using AssetIntegerType = uint32_t;
 		}
 
+		using ErrorMessageCallbackPFN = std::function<void(std::string_view)>;
+
 		enum class SpriteID : Core::AssetIntegerType {};
 
 		enum class MeshID : Core::AssetIntegerType {};
 
 		struct DebugCreateInfo;
-		struct CreateInfo;
+		struct AssetLoadCreateInfo;
+		struct InitInfo;
+
+		class MeshDocument;
+
+
 		enum class API;
 		class Viewport;
-		class SceneData;
 		struct RenderGraph;
 		struct RenderGraphTransform;
 		struct CameraInfo;
diff --git a/src/Engine/Utility/ImgDim.hpp b/src/Engine/Utility/ImgDim.hpp
index c5c02f68cc6642fb34033ea0cecc90d5aec4af02..06de4af8121a8692c94573a718f315d12bb4ff0b 100644
--- a/src/Engine/Utility/ImgDim.hpp
+++ b/src/Engine/Utility/ImgDim.hpp
@@ -3,6 +3,7 @@
 #include <string>
 #include <sstream>
 #include <utility>
+#include <cassert>
 
 namespace Utility
 {
@@ -18,6 +19,11 @@ namespace Utility
 		void Swap();
 
 		std::string ToString() const;
+
+		constexpr ValueType& At(size_t i);
+		constexpr const ValueType& At(size_t i) const;
+		constexpr ValueType& operator[](size_t i);
+		constexpr const ValueType& operator[](size_t i) const;
 	};
 
 	constexpr float ImgDim::GetAspectRatio() const { return static_cast<float>(width) / static_cast<float>(height); }
@@ -30,5 +36,35 @@ namespace Utility
 		out << '(' << width << ", " << height << ')';
 		return out.str();
 	}
+
+	constexpr ImgDim::ValueType& ImgDim::At(size_t i)
+	{
+		return const_cast<ValueType&>(std::as_const(*this).At(i));
+	}
+
+	const constexpr ImgDim::ValueType& ImgDim::At(size_t i) const
+	{
+		assert(i >= 0 && i < 2);
+		switch (i)
+		{
+		case 0:
+			return width;
+		case 1:
+			return height;
+		default:
+			assert(false);
+			return width;
+		}
+	}
+
+	constexpr ImgDim::ValueType& ImgDim::operator[](size_t i)
+	{
+		return At(i);
+	}
+
+	constexpr const ImgDim::ValueType& ImgDim::operator[](size_t i) const
+	{
+		return At(i);
+	}
 }