diff --git a/fggl/gfx/ogl4/canvas.cpp b/fggl/gfx/ogl4/canvas.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..66f166f95554e24bc7c89959e25e41911757928b
--- /dev/null
+++ b/fggl/gfx/ogl4/canvas.cpp
@@ -0,0 +1,39 @@
+/*
+ * ${license.title}
+ * Copyright (C) 2022 ${license.owner}
+ * ${license.mailto}
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "fggl/gfx/ogl/common.hpp"
+#include "fggl/gfx/ogl4/canvas.hpp"
+
+#include "fggl/data/model.hpp"
+
+#define FGGL_OPENGL_CORRECTNESS
+
+namespace fggl::gfx::ogl4 {
+
+	static void convert_to_mesh(const gfx::Paint& paint, data::Mesh2D& mesh) {
+	}
+
+	void CanvasRenderer::render(const gfx::Paint &paint) {
+		data::Mesh2D mesh;
+		convert_to_mesh(paint, mesh);
+
+	}
+
+}
\ No newline at end of file
diff --git a/include/fggl/gfx/ogl/models.hpp b/include/fggl/gfx/ogl/models.hpp
deleted file mode 100644
index afcaff86abd52a8a1b5168417565eb7b9cb39fcb..0000000000000000000000000000000000000000
--- a/include/fggl/gfx/ogl/models.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Created by webpigeon on 17/04/22.
-//
-
-#ifndef FGGL_GFX_OGL_MODELS_HPP
-#define FGGL_GFX_OGL_MODELS_HPP
-
-#include <string>
-#include <unordered_map>
-
-#include <fggl/gfx/ogl/backend.hpp>
-#include <fggl/ecs3/ecs.hpp>
-
-namespace fgg::gfx::ogl {
-
-	namespace {
-		using fggl::ecs3::World;
-		using fggl::gfx::Shader;
-	}
-
-	class StaticModelRenderer {
-		public:
-			StaticModelRenderer();
-			~StaticModelRenderer() = default;
-
-			void render(World& world) {
-				resolveModels();
-				renderModels();
-			}
-
-		private:
-			/**
-			 * Attach any missing render tokens to models.
-			 */
-			void resolveModels();
-
-			/**
-			 * Render all visible objects according to their render tokens.
-			 */
-			void renderModels();
-
-		private:
-			std::unordered_map<std::string, std::shared_ptr<Shader>> m_shaders;
-	};
-
-}
-
-#endif //FGGL_INCLUDE_FGGL_GFX_OGL_MODELS_HPP
diff --git a/include/fggl/gfx/ogl/renderer.hpp b/include/fggl/gfx/ogl/renderer.hpp
index c88e9f36ee2eeacb3d3d7a8da42e21ba01696c0f..1f8a60f8136a331986b45ee856cbfa98cf1c2c78 100644
--- a/include/fggl/gfx/ogl/renderer.hpp
+++ b/include/fggl/gfx/ogl/renderer.hpp
@@ -5,8 +5,13 @@
 #include <fggl/ecs3/ecs.hpp>
 #include <fggl/gfx/ogl/backend.hpp>
 #include <fggl/gfx/ogl/shader.hpp>
+
+#include "fggl/gfx/ogl4/models.hpp"
+#include "fggl/gfx/ogl4/canvas.hpp"
+
 #include <fggl/gfx/paint.hpp>
 #include <fggl/gfx/renderer.hpp>
+
 #include <memory>
 #include <vector>
 
@@ -50,6 +55,9 @@ namespace fggl::gfx {
 			void draw2D(const Paint &paint) override;
 
 		private:
+			ogl4::StaticModelRenderer m_modelRenderer;
+			ogl4::CanvasRenderer m_canvasRenderer;
+
 			GlRenderToken m_token2D;
 			std::unique_ptr<ShaderCache> m_cache;
 	};
diff --git a/include/fggl/gfx/ogl/types.hpp b/include/fggl/gfx/ogl/types.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..75917b153024e8bec784898743a7b1afa87ccca2
--- /dev/null
+++ b/include/fggl/gfx/ogl/types.hpp
@@ -0,0 +1,191 @@
+/*
+ * ${license.title}
+ * Copyright (C) 2022 ${license.owner}
+ * ${license.mailto}
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+//
+// Created by webpigeon on 17/04/22.
+//
+
+#ifndef FGGL_GFX_OGL_TYPES_HPP
+#define FGGL_GFX_OGL_TYPES_HPP
+
+#include <cstdint>
+#include <string_view>
+
+#include "fggl/gfx/ogl/common.hpp"
+#include "fggl/math/types.hpp"
+
+namespace fggl::gfx::ogl {
+
+	// reset values into their 'empty' states
+	void deactivate_shader();
+	void deactivate_buffer();
+	void deactivate_vertex_array();
+
+	constexpr GLuint UNIFORM_NOOP = -1;
+	using Location = GLint;
+
+	class Shader {
+		private:
+			GLuint m_obj = 0;
+			void release();
+
+		public:
+			// copy constructor bad
+			Shader(const Shader&) = delete;
+			Shader& operator=(const Shader&) = delete;
+
+			// Move ok - if handled properly
+			Shader(Shader&& other);
+			Shader& operator=(Shader&& other);
+
+			void use();
+
+			Location uniform(const std::string_view& name) const;
+			Location uniform(const std::string& name) const;
+
+			// primatives
+			void setUniform(Location name, GLfloat value);
+			void setUniform(Location name, GLint value);
+			void setUniform(Location name, GLuint value);
+
+			// vector versions (float)
+			void setUniform(Location name, math::vec2f value);
+			void setUniform(Location name, math::vec3f value);
+			void setUniform(Location name, math::vec4f value);
+			void setUniform(Location name, const math::vec2f* value, GLsizei size);
+			void setUniform(Location name, const math::vec3f* value, GLsizei size);
+			void setUniform(Location name, const math::vec4f* value, GLsizei size);
+
+			// vector versions (int)
+			void setUniform(Location name, math::vec2i value);
+			void setUniform(Location name, math::vec3i value);
+			void setUniform(Location name, math::vec4i value);
+			void setUniform(Location name, const math::vec2i* value, GLsizei size);
+			void setUniform(Location name, const math::vec3i* value, GLsizei size);
+			void setUniform(Location name, const math::vec4i* value, GLsizei size);
+
+			// matrix versions
+			void setUniform(Location name, const math::mat2*, GLsizei count);
+			void setUniform(Location name, const math::mat3*, GLsizei count);
+			void setUniform(Location name, const math::mat4*, GLsizei count);
+	};
+
+	enum class BuffAttrF {
+		HALF_FLOAT = GL_HALF_FLOAT,
+		FLOAT = GL_FLOAT,
+		DOUBLE = GL_DOUBLE,
+		FIXED = GL_FIXED
+	};
+
+	enum class BuffAttrI{
+		BYTE = GL_BYTE,
+		UBYTE = GL_UNSIGNED_BYTE,
+		SHORT = GL_SHORT,
+		USHORT = GL_UNSIGNED_SHORT,
+		INT = GL_INT,
+		UINT = GL_UNSIGNED_INT,
+
+		// these ones are oddly spesific...
+		INT_PACKED = GL_INT_2_10_10_10_REV,
+		UINT_PACKED = GL_UNSIGNED_INT_2_10_10_10_REV,
+		UINT_PACKED_F = GL_UNSIGNED_INT_10F_11F_11F_REV
+	};
+
+	enum class Primative {
+			POINT = GL_POINT,
+			LINE = GL_LINES,
+			LINE_STRIP = GL_LINE_STRIP,
+			LINE_LOOP = GL_LINE_LOOP,
+			TRIANGLE = GL_TRIANGLES,
+			TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
+			TRIANGLE_FAN = GL_TRIANGLE_FAN
+	};
+
+	enum class BufType {
+			ARRAY = GL_ARRAY_BUFFER,
+			ELEMENT_ARRAY = GL_ELEMENT_ARRAY_BUFFER,
+			COPY_READ = GL_COPY_READ_BUFFER,
+			COPY_WRITE = GL_COPY_WRITE_BUFFER,
+			PIXEL_UNPACK = GL_PIXEL_UNPACK_BUFFER,
+			PIXEL_PACK = GL_PIXEL_PACK_BUFFER,
+			QUERY = GL_QUERY_BUFFER,
+			TEXTURE = GL_TEXTURE_BUFFER,
+			TRANSFORM_FEEDBACK = GL_TRANSFORM_FEEDBACK_BUFFER,
+			UNIFORM = GL_UNIFORM_BUFFER,
+			DRAW_INDRECT = GL_DRAW_INDIRECT_BUFFER,
+			ATOMIC_COUNTER = GL_ATOMIC_COUNTER_BUFFER,
+			DISPATCH_INDIRECT = GL_DISPATCH_INDIRECT_BUFFER,
+			SHADER_STORAGE = GL_SHADER_STORAGE_BUFFER
+	};
+
+	enum class BufUsage {
+		STATIC_DRAW = GL_STATIC_DRAW,
+		STATIC_READ = GL_STATIC_READ,
+		STATIC_COPY = GL_STATIC_COPY,
+		DYNAMIC_DRAW = GL_DYNAMIC_DRAW,
+		DYNAMIC_READ = GL_DYNAMIC_READ,
+		DYNAMIC_COPY = GL_DYNAMIC_COPY,
+		STREAM_DRAW = GL_STREAM_DRAW,
+		STREAM_READ = GL_STREAM_READ,
+		STREAM_COPY = GL_STREAM_COPY,
+	};
+
+	class Buffer {
+		private:
+			GLuint m_obj = 0;
+			void release();
+
+		public:
+			// copy constructor bad
+			Buffer(const Buffer&) = delete;
+			Buffer& operator=(const Buffer&) = delete;
+
+			Buffer(Buffer&& other);
+			Buffer& operator=(Shader&& other);
+
+			void bind();
+
+			void write(BufType target, GLsizeiptr size, const GLvoid* data, BufUsage usage);
+			void update(BufType target, GLintptr offset, GLsizeiptr size, const void* data);
+
+			// NOTE: size must be between 1 - 4
+			void setAttribute(GLuint idx, GLint size, BuffAttrF attr, bool normalized, GLsizei stride, std::size_t offset);
+			void setAttribute(GLuint idx, GLint size, BuffAttrI attr, GLsizei stride, std::size_t offset);
+			void setAttributeI(GLuint idx, GLint size, BuffAttrI attr, GLsizei stride, std::size_t offset);
+	};
+
+	class VertexArray {
+		private:
+			GLuint obj_ = 0;
+			void Release();
+
+		public:
+			VertexArray(const Buffer&) = delete;
+			VertexArray& operator=(const VertexArray) = delete;
+
+			VertexArray(VertexArray&& other);
+			VertexArray& operator=(VertexArray&& other);
+
+			void bind();
+	};
+
+} // namespace fggl::gfx::ogl
+
+#endif //FGGL_GFX_OGL_TYPES_HPP
diff --git a/include/fggl/gfx/ogl4/canvas.hpp b/include/fggl/gfx/ogl4/canvas.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..20330687dd265879a6d7300d5bf170709826978c
--- /dev/null
+++ b/include/fggl/gfx/ogl4/canvas.hpp
@@ -0,0 +1,23 @@
+//
+// Created by webpigeon on 17/04/22.
+//
+
+#ifndef FGGL_GFX_OGL4_CANVAS_HPP
+#define FGGL_GFX_OGL4_CANVAS_HPP
+
+#include <fggl/gfx/paint.hpp>
+
+
+namespace fggl::gfx::ogl4 {
+
+	class CanvasRenderer {
+		public:
+			CanvasRenderer() = default;
+			void render(const gfx::Paint& paint);
+
+		private:
+	};
+
+} // namespace fggl::gfx::ogl4
+
+#endif //FGGL_GFX_OGL4_CANVAS_HPP
diff --git a/include/fggl/gfx/ogl4/models.hpp b/include/fggl/gfx/ogl4/models.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..baabd3967eb73613094c30d8e91eb40fc18174b8
--- /dev/null
+++ b/include/fggl/gfx/ogl4/models.hpp
@@ -0,0 +1,48 @@
+//
+// Created by webpigeon on 17/04/22.
+//
+
+#ifndef FGGL_GFX_OGL4_MODELS_HPP
+#define FGGL_GFX_OGL4_MODELS_HPP
+
+#include <string>
+#include <unordered_map>
+
+#include "fggl/gfx/ogl/backend.hpp"
+#include "fggl/ecs3/ecs.hpp"
+
+namespace fggl::gfx::ogl4 {
+
+	class StaticModelRenderer {
+		public:
+			StaticModelRenderer() = default;
+			~StaticModelRenderer() = default;
+
+			StaticModelRenderer(const StaticModelRenderer& other) = delete;
+			StaticModelRenderer(StaticModelRenderer&& other) = delete;
+
+			StaticModelRenderer& operator=(const StaticModelRenderer& other) = delete;
+			StaticModelRenderer& operator=(StaticModelRenderer&& other) = delete;
+
+			void render(ecs3::World& world) {
+				resolveModels(world);
+				renderModelsForward(world);
+			}
+
+		private:
+			/**
+			 * Attach any missing rendering components to models.
+			 */
+			void resolveModels(ecs3::World& world);
+
+			/**
+			 * Render all visible objects according to their render tokens.
+			 */
+			void renderModelsForward(const ecs3::World& world);
+
+			std::unordered_map<std::string, std::shared_ptr<gfx::Shader>> m_shaders;
+	};
+
+}
+
+#endif //FGGL_GFX_OGL4_MODELS_HPP
diff --git a/include/fggl/math/types.hpp b/include/fggl/math/types.hpp
index 9c035fe1177d24c93dcca6d1ce3e7a8f57f85b3d..bfce42938b26af8b285d9709f81ecadabdc44984 100644
--- a/include/fggl/math/types.hpp
+++ b/include/fggl/math/types.hpp
@@ -12,15 +12,22 @@ namespace fggl::math {
 
 	// math types (aliased for ease of use)
 	using vec4 = glm::vec4;
+	using vec4f = glm::vec4;
+	using vec4i = glm::ivec4;
+	using vec4ui = glm::ivec4;
 
 	using vec3 = glm::vec3;
 	using vec3i = glm::ivec3;
 	using vec3f = glm::vec3;
+	using vec3ui = glm::ivec3;
 
 	using vec2 = glm::vec2;
-	using vec2i = glm::ivec2;
 	using vec2f = glm::vec2;
+	using vec2i = glm::ivec2;
+	using vec2ui = glm::ivec2;
 
+	using mat2 = glm::mat2;
+	using mat3 = glm::mat3;
 	using mat4 = glm::mat4;
 	using quat = glm::quat;