summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Assets.cpp6
-rw-r--r--src/Assets.hpp8
-rw-r--r--src/Common/Sizes.hpp46
-rw-r--r--src/Compute/Queue.hpp18
-rw-r--r--src/GFX/Binder.cpp20
-rw-r--r--src/GFX/Binder.hpp26
-rw-r--r--src/GFX/Image/PPMParser.cpp24
-rw-r--r--src/GFX/Image/PPMParser.hpp18
-rw-r--r--src/GFX/Image/RawImage.cpp14
-rw-r--r--src/GFX/Image/RawImage.hpp17
-rw-r--r--src/GFX/Mesh.cpp2
-rw-r--r--src/GFX/Mesh.hpp22
-rw-r--r--src/GFX/Mouse.cpp4
-rw-r--r--src/GFX/Mouse.hpp6
-rw-r--r--src/GFX/Shading/Program.cpp6
-rw-r--r--src/GFX/Shading/Program.hpp4
-rw-r--r--src/GFX/Shading/Shader.cpp6
-rw-r--r--src/GFX/Shading/Shader.hpp8
-rw-r--r--src/GFX/Shading/Uniform.cpp4
-rw-r--r--src/GFX/Shading/Uniform.hpp10
-rw-r--r--src/GFX/Texture.hpp2
-rw-r--r--src/GFX/Window.cpp11
-rw-r--r--src/GFX/Window.hpp14
-rw-r--r--src/Math/Common.hpp2
-rw-r--r--src/Math/Constants.hpp6
-rw-r--r--src/Math/Grid.hpp4
-rw-r--r--src/Math/Interpolation.cpp6
-rw-r--r--src/Math/Interpolation.hpp6
-rw-r--r--src/Math/MVP.cpp51
-rw-r--r--src/Math/MVP.hpp59
-rw-r--r--src/Math/Matrix.hpp58
-rw-r--r--src/Math/Perlin.cpp10
-rw-r--r--src/Math/Perlin.hpp26
-rw-r--r--src/Math/Random.cpp16
-rw-r--r--src/Math/Random.hpp22
-rw-r--r--src/Math/Rotation.hpp10
-rw-r--r--src/Math/Tensor.hpp22
-rw-r--r--src/Math/Vector.hpp28
-rw-r--r--src/Util/ImageViewer.cpp30
-rw-r--r--src/Util/ImageViewer.hpp10
-rw-r--r--src/World/BiomeType.hpp6
-rw-r--r--src/World/BlockSide.hpp6
-rw-r--r--src/World/BlockType.hpp8
-rw-r--r--src/World/Chunk.cpp10
-rw-r--r--src/World/Chunk.hpp22
-rw-r--r--src/World/ChunkIndex.hpp12
-rw-r--r--src/World/Generation/ChunkMeshing.cpp54
-rw-r--r--src/World/Generation/Decoration.cpp42
-rw-r--r--src/World/Generation/Decoration.hpp10
-rw-r--r--src/World/Generation/Generator.cpp86
-rw-r--r--src/World/Generation/Generator.hpp49
-rw-r--r--src/World/World.cpp24
-rw-r--r--src/World/World.hpp16
-rw-r--r--src/main.cpp33
54 files changed, 545 insertions, 495 deletions
diff --git a/src/Assets.cpp b/src/Assets.cpp
index ffd09ec..66fdc88 100644
--- a/src/Assets.cpp
+++ b/src/Assets.cpp
@@ -2,15 +2,15 @@
 
 namespace MC::Assets {
 
-const char* Shaders::fragment =
+const Char* Shaders::fragment =
 #include "../assets/generated/shaders/fragment.glsl.includable"
 ;
 
-const char* Shaders::vertex =
+const Char* Shaders::vertex =
 #include "../assets/generated/shaders/vertex.glsl.includable"
 ;
 
-const char* Images::atlas =
+const Char* Images::atlas =
 #include "../assets/generated/images/atlas.ppm.includable"
 ;
 
diff --git a/src/Assets.hpp b/src/Assets.hpp
index 641125a..9ff5c42 100644
--- a/src/Assets.hpp
+++ b/src/Assets.hpp
@@ -1,17 +1,19 @@
 #pragma once
 
+#include "Common/Sizes.hpp"
+
 namespace MC::Assets {
 
 namespace Shaders {
 
-extern const char* vertex;
-extern const char* fragment;
+extern const Char* vertex;
+extern const Char* fragment;
 
 }
 
 namespace Images {
 
-extern const char* atlas;
+extern const Char* atlas;
 
 }
 
diff --git a/src/Common/Sizes.hpp b/src/Common/Sizes.hpp
new file mode 100644
index 0000000..91422e5
--- /dev/null
+++ b/src/Common/Sizes.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <cstdint>
+
+using I8 = int8_t;
+using U8 = uint8_t;
+
+using I16 = int16_t;
+using U16 = uint16_t;
+
+using I32 = int32_t;
+using U32 = uint32_t;
+
+using I64 = int64_t;
+using U64 = uint64_t;
+
+using ISize = I64;
+using USize = U64;
+
+using F32 = float;
+using F64 = double;
+
+using Bool = bool;
+
+using Char = char;
+
+using UInt = USize;
+using Int = ISize;
+using Real = F64;
+
+#define ASSERT_SIZE(type, bytes) \
+    static_assert(sizeof(type) == (bytes), "Type '" #type "' should be exactly " #bytes " bytes.")
+
+ASSERT_SIZE(I8, 1);
+ASSERT_SIZE(U8, 1);
+ASSERT_SIZE(I16, 2);
+ASSERT_SIZE(U16, 2);
+ASSERT_SIZE(I32, 4);
+ASSERT_SIZE(U32, 4);
+ASSERT_SIZE(I64, 8);
+ASSERT_SIZE(U64, 8);
+
+ASSERT_SIZE(F32, 4);
+ASSERT_SIZE(F64, 8);
+
+ASSERT_SIZE(Bool, 1);
\ No newline at end of file
diff --git a/src/Compute/Queue.hpp b/src/Compute/Queue.hpp
index 77aed7f..4035d56 100644
--- a/src/Compute/Queue.hpp
+++ b/src/Compute/Queue.hpp
@@ -1,7 +1,7 @@
 #pragma once
 
+#include "../Common/Sizes.hpp"
 #include <functional>
-#include <sys/types.h>
 #include <mutex>
 #include <vector>
 #include <queue>
@@ -9,17 +9,17 @@
 
 namespace MC::Compute {
 
-template <typename X, typename I = uint>
+template <typename X, typename I = UInt>
 class Queue {
 public:
-    explicit Queue(uint workers) : m_control(std::make_shared<Control>()) {
-        for (uint w = 0; w < workers; w++) {
+    explicit Queue(UInt workers) : m_control(std::make_shared<Control>()) {
+        for (UInt w = 0; w < workers; w++) {
             std::thread thread{[=]{ Queue::run_thread(m_control); }};
             thread.detach();
         }
     }
 
-    void add(I id, float priority, std::function<X()> execute) {
+    void add(I id, Real priority, std::function<X()> execute) {
         std::scoped_lock work_lock(m_control->work.mutex);
         m_control->work.jobs.emplace(id, priority, execute);
     }
@@ -43,13 +43,13 @@ public:
 private:
     struct Job {
         Job() = default;
-        Job(I id, float priority, std::function<X()> execute) : id(id), priority(priority), execute(execute) {}
+        Job(I id, Real priority, std::function<X()> execute) : id(id), priority(priority), execute(execute) {}
 
         I id;
-        float priority;
+        Real priority;
         std::function<X()> execute;
 
-        bool operator>(const Job& other) const { return priority > other.priority; }
+        Bool operator>(const Job& other) const { return priority > other.priority; }
     };
 
     struct Work {
@@ -71,7 +71,7 @@ private:
         using namespace std::chrono_literals;
 
         while (true) {
-            bool nothing_to_do = true;
+            Bool nothing_to_do = true;
             Job job;
             {
                 std::scoped_lock work_lock(control->work.mutex);
diff --git a/src/GFX/Binder.cpp b/src/GFX/Binder.cpp
index e8fc559..905ba24 100644
--- a/src/GFX/Binder.cpp
+++ b/src/GFX/Binder.cpp
@@ -10,7 +10,7 @@ BindableMesh Binder::load(const Mesh& mesh) {
         store_indices(mesh.indices().data(), mesh.indices().size());
     }
 
-    int attribute_index = 0;
+    Int attribute_index = 0;
     for (const auto& attribute : mesh.attributes()) {
         store_in_attribute_list(
             attribute_index++,
@@ -25,7 +25,7 @@ BindableMesh Binder::load(const Mesh& mesh) {
     return {vao, mesh.indices().size(), mesh.attributes().size()};
 }
 
-uint32_t Binder::create_vao() {
+U32 Binder::create_vao() {
     GLuint vao;
     glGenVertexArrays(1, &vao);
     glBindVertexArray(vao);
@@ -37,17 +37,17 @@ void Binder::unbind_vao() {
     glBindVertexArray(0);
 }
 
-void Binder::store_indices(const uint32_t* indices, size_t indices_size) {
+void Binder::store_indices(const U32* indices, USize indices_size) {
     GLuint ebo;
     glGenBuffers(1, &ebo);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_size * sizeof(float), indices, GL_STATIC_DRAW);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_size * sizeof(U32), indices, GL_STATIC_DRAW);
 }
 
 
-void Binder::store_in_attribute_list(uint32_t attribute, int attribute_size, int type_size, const void* data, long data_size) {
-    assert(type_size == sizeof(float));
+void Binder::store_in_attribute_list(U32 attribute, Int attribute_size, Int type_size, const void* data, long data_size) {
+    assert(type_size == sizeof(F32));
 
     GLuint vbo;
     glGenBuffers(1, &vbo);
@@ -60,23 +60,23 @@ void Binder::store_in_attribute_list(uint32_t attribute, int attribute_size, int
 
 void BindableMesh::bind() const {
     glBindVertexArray(m_vao);
-    for (int i = 0; i < m_attribute_count; i++) {
+    for (Int i = 0; i < m_attribute_count; i++) {
         glEnableVertexAttribArray(i);
     }
 }
 
 void BindableMesh::unbind() const {
     glBindVertexArray(0);
-    for (int i = 0; i < m_attribute_count; i++) {
+    for (Int i = 0; i < m_attribute_count; i++) {
         glDisableVertexAttribArray(i);
     }
 }
 
-bool BindableMesh::has_indices() const {
+Bool BindableMesh::has_indices() const {
     return m_has_indices;
 }
 
-size_t BindableMesh::size() const {
+USize BindableMesh::size() const {
     return m_vertex_count;
 }
 
diff --git a/src/GFX/Binder.hpp b/src/GFX/Binder.hpp
index 773518d..6103e09 100644
--- a/src/GFX/Binder.hpp
+++ b/src/GFX/Binder.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <cstdint>
+#include "../Common/Sizes.hpp"
 #include "Mesh.hpp"
 
 namespace MC::GFX {
@@ -10,23 +10,23 @@ public:
     void bind() const;
     void unbind() const;
 
-    bool has_indices() const;
-    size_t size() const;
+    Bool has_indices() const;
+    USize size() const;
 
 private:
     BindableMesh(
-        uint32_t vao,
-        size_t vertex_count,
-        size_t attribute_count
+        U32 vao,
+        USize vertex_count,
+        USize attribute_count
     ) : m_vao(vao),
         m_vertex_count(vertex_count),
         m_has_indices(vertex_count > 0),
         m_attribute_count(attribute_count) {}
 
-    uint32_t m_vao;
-    size_t m_vertex_count;
-    bool m_has_indices;
-    size_t m_attribute_count;
+    U32 m_vao;
+    USize m_vertex_count;
+    Bool m_has_indices;
+    USize m_attribute_count;
 
     friend class Binder;
 };
@@ -38,11 +38,11 @@ public:
     static BindableMesh load(const Mesh& mesh);
 
 private:
-    static uint32_t create_vao();
+    static U32 create_vao();
     static void unbind_vao();
 
-    static void store_in_attribute_list(uint32_t attribute, int attribute_size, int type_size, const void* data, long data_size);
-    static void store_indices(const uint32_t* indices, size_t indices_size);
+    static void store_in_attribute_list(U32 attribute, Int attribute_size, Int type_size, const void* data, long data_size);
+    static void store_indices(const U32* indices, USize indices_size);
 };
 
 }
\ No newline at end of file
diff --git a/src/GFX/Image/PPMParser.cpp b/src/GFX/Image/PPMParser.cpp
index 1f62871..3c95bba 100644
--- a/src/GFX/Image/PPMParser.cpp
+++ b/src/GFX/Image/PPMParser.cpp
@@ -18,7 +18,7 @@ RawImage PPMParser::parse() {
     auto pixel_count = header.width * header.height;
 
     RawImage image(header.width, header.height);
-    for (uint64_t pixel_index = 0; pixel_index < pixel_count; pixel_index++) {
+    for (U64 pixel_index = 0; pixel_index < pixel_count; pixel_index++) {
         RawImage::Pixel pixel = parse_pixel(header.max_color);
         image.add(pixel);
     }
@@ -57,7 +57,7 @@ PPMParser::PPMHeader PPMParser::parse_header() {
     return header;
 }
 
-RawImage::Pixel PPMParser::parse_pixel(uint8_t max_color) {
+RawImage::Pixel PPMParser::parse_pixel(U8 max_color) {
     auto r_sample = parse_sample();
     auto g_sample = parse_sample();
     auto b_sample = parse_sample();
@@ -66,7 +66,7 @@ RawImage::Pixel PPMParser::parse_pixel(uint8_t max_color) {
         throw std::runtime_error("Sample can not be greater than Maxval.");
     }
 
-    auto map_to_range = [=](uint64_t s) -> uint8_t { return s * 255 / max_color; };
+    auto map_to_range = [=](U64 s) -> U8 { return s * 255 / max_color; };
 
     RawImage::Pixel p{
         map_to_range(r_sample),
@@ -82,23 +82,23 @@ RawImage::Pixel PPMParser::parse_pixel(uint8_t max_color) {
     return p;
 }
 
-uint64_t PPMParser::parse_sample() {
+U64 PPMParser::parse_sample() {
     skip_whitespace();
     auto sample = chomp_number();
     skip_whitespace();
     return sample;
 }
 
-uint64_t PPMParser::chomp_number() {
+U64 PPMParser::chomp_number() {
     auto raw = chomp_part();
 
-    uint64_t number = 0;
-    for (uint8_t digit_ascii : raw) {
+    U64 number = 0;
+    for (U8 digit_ascii : raw) {
         if (digit_ascii < '0' || digit_ascii > '9') {
             throw std::runtime_error("Number contains non ASCII digits.");
         }
 
-        uint8_t digit = digit_ascii - '0';
+        U8 digit = digit_ascii - '0';
 
         number *= 10;
         number += digit;
@@ -108,7 +108,7 @@ uint64_t PPMParser::chomp_number() {
 }
 
 std::string_view PPMParser::chomp_part() {
-    uint64_t length = 0;
+    U64 length = 0;
 
     while (!is_eof()) {
         auto c = m_source[m_cursor + length];
@@ -127,7 +127,7 @@ std::string_view PPMParser::chomp_part() {
 
 void PPMParser::skip_whitespace() {
     while (!is_eof()) {
-        uint8_t c = m_source[m_cursor];
+        U8 c = m_source[m_cursor];
         if (c == '#') {
             skip_comment();
             continue;
@@ -142,7 +142,7 @@ void PPMParser::skip_whitespace() {
 }
 
 void PPMParser::skip_comment() {
-    uint8_t c = m_source[m_cursor];
+    U8 c = m_source[m_cursor];
     if (c != '#') {
         return;
     }
@@ -152,7 +152,7 @@ void PPMParser::skip_comment() {
     }
 }
 
-bool PPMParser::is_eof() const {
+Bool PPMParser::is_eof() const {
     return m_cursor >= m_source.size();
 }
 
diff --git a/src/GFX/Image/PPMParser.hpp b/src/GFX/Image/PPMParser.hpp
index a7e9b41..77f1cec 100644
--- a/src/GFX/Image/PPMParser.hpp
+++ b/src/GFX/Image/PPMParser.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <cstdint>
+#include "../../Common/Sizes.hpp"
 #include <string_view>
 #include "RawImage.hpp"
 
@@ -20,27 +20,27 @@ private:
 
     struct PPMHeader {
         PPMType type;
-        uint32_t width;
-        uint32_t height;
-        uint8_t max_color;
+        U32 width;
+        U32 height;
+        U8 max_color;
     };
 
     PPMHeader parse_header();
-    RawImage::Pixel parse_pixel(uint8_t max_color);
-    uint64_t parse_sample();
+    RawImage::Pixel parse_pixel(U8 max_color);
+    U64 parse_sample();
 
-    uint64_t chomp_number();
+    U64 chomp_number();
     std::string_view chomp_part();
 
     void skip_whitespace();
     void skip_comment();
 
-    bool is_eof() const;
+    Bool is_eof() const;
 
     static constexpr RawImage::Pixel alpha_color{192, 0, 255};
 
     std::string_view m_source;
-    uint64_t m_cursor = 0;
+    U64 m_cursor = 0;
 };
 
 }
diff --git a/src/GFX/Image/RawImage.cpp b/src/GFX/Image/RawImage.cpp
index 0bd2947..9f156b8 100644
--- a/src/GFX/Image/RawImage.cpp
+++ b/src/GFX/Image/RawImage.cpp
@@ -7,30 +7,30 @@ void RawImage::add(Pixel pixel) {
     m_pixels.push_back(pixel);
 }
 
-size_t RawImage::size() const {
+USize RawImage::size() const {
     return m_pixels.size();
 }
 
-uint8_t* RawImage::raw() const {
-    return (uint8_t*)m_pixels.data();
+U8* RawImage::raw() const {
+    return (U8*)m_pixels.data();
 }
 
-uint32_t RawImage::width() const {
+U32 RawImage::width() const {
     return m_width;
 }
 
-uint32_t RawImage::height() const {
+U32 RawImage::height() const {
     return m_height;
 }
 
 std::string RawImage::string() const {
     std::stringstream str{};
 
-    bool comma = false;
+    Bool comma = false;
     str << "[";
     for (const auto [r, g, b, a] : m_pixels) {
         if (comma) { str << ", "; }
-        str << "{r=" << (uint)r << ", g=" << (uint)g << ", b=" << (uint)b << ", a=" << (uint)a << "}";
+        str << "{r=" << (UInt)r << ", g=" << (UInt)g << ", b=" << (UInt)b << ", a=" << (UInt)a << "}";
         comma = true;
     }
     str << "]";
diff --git a/src/GFX/Image/RawImage.hpp b/src/GFX/Image/RawImage.hpp
index 809ddd9..5a95dad 100644
--- a/src/GFX/Image/RawImage.hpp
+++ b/src/GFX/Image/RawImage.hpp
@@ -1,7 +1,6 @@
 #pragma once
 
-#include <cstdint>
-#include <cstddef>
+#include "../../Common/Sizes.hpp"
 #include <string>
 #include <vector>
 
@@ -11,26 +10,26 @@ class RawImage {
 public:
     RawImage() : m_width(0), m_height(0) {}
 
-    RawImage(uint32_t width, uint32_t height) : m_width(width), m_height(height) {
+    RawImage(U32 width, U32 height) : m_width(width), m_height(height) {
         m_pixels.reserve(width * height);
     }
 
     struct Pixel {
-        uint8_t r, g, b, a;
+        U8 r, g, b, a;
     };
 
     void add(Pixel pixel);
 
-    size_t size() const;
-    uint8_t* raw() const;
+    USize size() const;
+    U8* raw() const;
 
-    uint32_t width() const;
-    uint32_t height() const;
+    U32 width() const;
+    U32 height() const;
 
     std::string string() const;
 private:
     std::vector<Pixel> m_pixels;
-    uint32_t m_width, m_height;
+    U32 m_width, m_height;
 };
 
 }
diff --git a/src/GFX/Mesh.cpp b/src/GFX/Mesh.cpp
index 1869622..c45b5c9 100644
--- a/src/GFX/Mesh.cpp
+++ b/src/GFX/Mesh.cpp
@@ -2,7 +2,7 @@
 
 namespace MC::GFX {
 
-const std::vector<uint32_t>& Mesh::indices() const {
+const std::vector<U32>& Mesh::indices() const {
     return m_indices;
 }
 
diff --git a/src/GFX/Mesh.hpp b/src/GFX/Mesh.hpp
index ec21e53..1c39941 100644
--- a/src/GFX/Mesh.hpp
+++ b/src/GFX/Mesh.hpp
@@ -2,7 +2,7 @@
 
 #include <utility>
 #include <vector>
-#include <cstdint>
+#include "../Common/Sizes.hpp"
 #include "../Math/Common.hpp"
 
 namespace MC::GFX {
@@ -10,7 +10,7 @@ namespace MC::GFX {
 class Mesh {
 public:
     struct Attribute {
-        template<size_t S = 3, typename T = float>
+        template<uint S = 3, typename T = float>
         Attribute(
             std::vector<Vector<S, T>> v
         ) : data_size(v.size()),
@@ -26,21 +26,21 @@ public:
             attribute_size(other.attribute_size),
             type_size(other.type_size) {}
 
-        static void* copy(void* ptr, uint32_t size) {
-            auto* buffer = new uint8_t[size];
-            std::copy_n((uint8_t*)ptr, size, buffer);
+        static void* copy(void* ptr, U32 size) {
+            auto* buffer = new U8[size];
+            std::copy_n((U8*)ptr, size, buffer);
             return buffer;
         }
 
         void* data;
-        long data_size;
-        int attribute_size;
-        int type_size;
+        USize data_size;
+        USize attribute_size;
+        USize type_size;
     };
 
     Mesh(
         std::vector<Attribute> attributes,
-        std::vector<uint32_t> indices
+        std::vector<U32> indices
     ) : m_attributes(std::move(attributes)),
         m_indices(std::move(indices)) {}
 
@@ -48,12 +48,12 @@ public:
         std::vector<Attribute> attributes
     ) : m_attributes(std::move(attributes)) {}
 
-    const std::vector<uint32_t>& indices() const;
+    const std::vector<U32>& indices() const;
     const std::vector<Attribute>& attributes() const;
 
 private:
     std::vector<Attribute> m_attributes;
-    std::vector<uint32_t> m_indices;
+    std::vector<U32> m_indices;
 };
 
 }
\ No newline at end of file
diff --git a/src/GFX/Mouse.cpp b/src/GFX/Mouse.cpp
index 5cd2698..49f6972 100644
--- a/src/GFX/Mouse.cpp
+++ b/src/GFX/Mouse.cpp
@@ -3,7 +3,7 @@
 namespace MC::GFX {
 
 Vector<2> Mouse::update(GLFWwindow* window) {
-    double x, y;
+    Real x, y;
     glfwGetCursorPos(window, &x, &y);
 
     if (m_first_event) {
@@ -13,7 +13,7 @@ Vector<2> Mouse::update(GLFWwindow* window) {
         m_first_event = false;
     }
 
-    Vector<2> movement{static_cast<float>(x) - m_last_x,  static_cast<float>(y) - m_last_y};
+    Vector<2> movement{static_cast<Real>(x) - m_last_x,  static_cast<Real>(y) - m_last_y};
 
     m_last_x = x;
     m_last_y = y;
diff --git a/src/GFX/Mouse.hpp b/src/GFX/Mouse.hpp
index 1e2111e..ad940d4 100644
--- a/src/GFX/Mouse.hpp
+++ b/src/GFX/Mouse.hpp
@@ -11,10 +11,10 @@ public:
 
     Vector<2> update(GLFWwindow* window);
 private:
-    bool m_first_event = true;
+    Bool m_first_event = true;
 
-    float m_last_x = 0.0f;
-    float m_last_y = 0.0f;
+    Real m_last_x = 0.0f;
+    Real m_last_y = 0.0f;
 };
 
 }
\ No newline at end of file
diff --git a/src/GFX/Shading/Program.cpp b/src/GFX/Shading/Program.cpp
index 6efb30b..ff10012 100644
--- a/src/GFX/Shading/Program.cpp
+++ b/src/GFX/Shading/Program.cpp
@@ -18,7 +18,7 @@ Program::Program(Shader vertex, Shader fragment) {
     GLint success;
     glGetProgramiv(m_program, GL_LINK_STATUS, &success);
     if(!success) {
-        char message[512] = {};
+        Char message[512] = {};
         glGetProgramInfoLog(m_program, 512, nullptr, message);
 
         throw std::runtime_error(message);
@@ -36,10 +36,10 @@ void Program::unbind() const {
 Uniform Program::uniform(const std::string& name) const {
     auto index = glGetUniformLocation(m_program, name.c_str());
 
-    return {name, static_cast<uint32_t>(index)};
+    return {name, static_cast<U32>(index)};
 }
 
-uint32_t Program::get() const {
+U32 Program::get() const {
     return m_program;
 }
 
diff --git a/src/GFX/Shading/Program.hpp b/src/GFX/Shading/Program.hpp
index 8a50617..2f48698 100644
--- a/src/GFX/Shading/Program.hpp
+++ b/src/GFX/Shading/Program.hpp
@@ -10,7 +10,7 @@ class Program {
 public:
     Program(Shader vertex, Shader fragment);
 
-    uint32_t get() const;
+    U32 get() const;
 
     Uniform uniform(const std::string& name) const;
 
@@ -18,7 +18,7 @@ public:
     void unbind() const;
 
 private:
-    uint32_t m_program;
+    U32 m_program;
 };
 
 }
\ No newline at end of file
diff --git a/src/GFX/Shading/Shader.cpp b/src/GFX/Shading/Shader.cpp
index 6dfac34..54f8ad1 100644
--- a/src/GFX/Shading/Shader.cpp
+++ b/src/GFX/Shading/Shader.cpp
@@ -4,8 +4,8 @@
 
 namespace MC::GFX::Shading {
 
-Shader::Shader(Type type, const char* source) {
-    uint32_t gl_type = 0;
+Shader::Shader(Type type, const Char* source) {
+    U32 gl_type = 0;
     switch (type) {
         case Type::Vertex:
             gl_type = GL_VERTEX_SHADER;
@@ -23,7 +23,7 @@ Shader::Shader(Type type, const char* source) {
     GLint success;
     glGetShaderiv(m_shader, GL_COMPILE_STATUS, &success);
     if(!success) {
-        char message[512] = {};
+        Char message[512] = {};
         glGetShaderInfoLog(m_shader, 512, nullptr, message);
 
         throw std::runtime_error(message);
diff --git a/src/GFX/Shading/Shader.hpp b/src/GFX/Shading/Shader.hpp
index 15450cb..21fd899 100644
--- a/src/GFX/Shading/Shader.hpp
+++ b/src/GFX/Shading/Shader.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <cstdint>
+#include "../../Common/Sizes.hpp"
 #include "../../Assets.hpp"
 
 namespace MC::GFX::Shading {
@@ -13,9 +13,9 @@ public:
         Fragment,
     };
 
-    Shader(Type type, const char* source);
+    Shader(Type type, const Char* source);
 
-    uint32_t get() const {
+    U32 get() const {
         return m_shader;
     }
 
@@ -28,7 +28,7 @@ public:
     }
 
 private:
-    uint32_t m_shader;
+    U32 m_shader;
 };
 
 }
\ No newline at end of file
diff --git a/src/GFX/Shading/Uniform.cpp b/src/GFX/Shading/Uniform.cpp
index 71786ef..a9c9854 100644
--- a/src/GFX/Shading/Uniform.cpp
+++ b/src/GFX/Shading/Uniform.cpp
@@ -3,11 +3,11 @@
 
 namespace MC::GFX::Shading {
 
-void Uniform::set(const Matrix<4, 4>& value) const {
+void Uniform::set(const Matrix<4, 4, F32>& value) const {
     glUniformMatrix4fv(m_index, 1, GL_TRUE, value.elements);
 }
 
-void Uniform::set(const Vector<3>& value) const {
+void Uniform::set(const Vector<3, F32>& value) const {
     glUniform3f(m_index, value.x(), value.y(), value.z());
 }
 
diff --git a/src/GFX/Shading/Uniform.hpp b/src/GFX/Shading/Uniform.hpp
index a270e65..c8ab6fe 100644
--- a/src/GFX/Shading/Uniform.hpp
+++ b/src/GFX/Shading/Uniform.hpp
@@ -1,22 +1,22 @@
 #pragma once
 
-#include <cstdint>
 #include <string>
+#include "../../Common/Sizes.hpp"
 #include "../../Math/Common.hpp"
 
 namespace MC::GFX::Shading {
 
 class Uniform {
 public:
-    Uniform(std::string name, uint32_t index)
+    Uniform(std::string name, U32 index)
         : m_name(std::move(name)), m_index(index) {}
 
-    void set(const Matrix<4, 4>& value) const;
-    void set(const Vector<3>& value) const;
+    void set(const Matrix<4, 4, F32>& value) const;
+    void set(const Vector<3, F32>& value) const;
 
 private:
     std::string m_name;
-    uint32_t m_index;
+    U32 m_index;
 };
 
 }
diff --git a/src/GFX/Texture.hpp b/src/GFX/Texture.hpp
index 2981b2c..11fd430 100644
--- a/src/GFX/Texture.hpp
+++ b/src/GFX/Texture.hpp
@@ -11,7 +11,7 @@ public:
     void bind() const;
     void unbind() const;
 private:
-    uint32_t m_texture = 0;
+    U32 m_texture = 0;
 };
 
 }
\ No newline at end of file
diff --git a/src/GFX/Window.cpp b/src/GFX/Window.cpp
index ea1fde4..bbe2ba7 100644
--- a/src/GFX/Window.cpp
+++ b/src/GFX/Window.cpp
@@ -1,9 +1,10 @@
 #include <stdexcept>
+#include "../Common/Sizes.hpp"
 #include "Window.hpp"
 
 namespace MC::GFX {
 
-Window::Window(const char *title, uint32_t width, uint32_t height) {
+Window::Window(const Char* title, U32 width, U32 height) {
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
@@ -23,7 +24,7 @@ Window::~Window() {
     glfwDestroyWindow(m_window);
 }
 
-bool Window::should_close() const {
+Bool Window::should_close() const {
     return glfwWindowShouldClose(m_window);
 }
 
@@ -39,11 +40,11 @@ Vector<2> Window::mouse_delta() {
     return m_mouse.update(m_window);
 }
 
-bool Window::key(int key, int type) const {
+Bool Window::key(I32 key, I32 type) const {
     return glfwGetKey(m_window, key) == type;
 }
 
-bool Window::mouse(int key, int type) const {
+Bool Window::mouse(I32 key, I32 type) const {
     return glfwGetMouseButton(m_window, key) == type;
 }
 
@@ -52,7 +53,7 @@ void Window::start_frame() {
     glfwPollEvents();
 }
 
-void Window::on_size_change(void (callback)(GLFWwindow*, int, int)) {
+void Window::on_size_change(void (callback)(GLFWwindow*, I32, I32)) {
     glfwSetFramebufferSizeCallback(m_window, callback);
 }
 
diff --git a/src/GFX/Window.hpp b/src/GFX/Window.hpp
index 966925c..ac0efd2 100644
--- a/src/GFX/Window.hpp
+++ b/src/GFX/Window.hpp
@@ -1,28 +1,28 @@
 #pragma once
 
-#include <cstdint>
-#include <GLFW/glfw3.h>
+#include "../Common/Sizes.hpp"
 #include "../Math/Vector.hpp"
+#include <GLFW/glfw3.h>
 #include "Mouse.hpp"
 
 namespace MC::GFX {
 
 class Window {
 public:
-    Window(const char* title, uint32_t width, uint32_t height);
+    Window(const Char* title, U32 width, U32 height);
     ~Window();
 
     GLFWwindow* get() const;
 
-    void on_size_change(void (* callback)(GLFWwindow*, int, int));
+    void on_size_change(void (* callback)(GLFWwindow*, I32, I32));
 
     void close();
     void start_frame();
     Vector<2> mouse_delta();
 
-    bool key(int key, int type) const;
-    bool mouse(int key, int type) const;
-    bool should_close() const;
+    Bool key(I32 key, I32 type) const;
+    Bool mouse(I32 key, I32 type) const;
+    Bool should_close() const;
 private:
     GLFWwindow* m_window;
     Mouse m_mouse;
diff --git a/src/Math/Common.hpp b/src/Math/Common.hpp
index 1ea75f2..cf5a2c7 100644
--- a/src/Math/Common.hpp
+++ b/src/Math/Common.hpp
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "../Common/Sizes.hpp"
+
 #include "Vector.hpp"
 #include "Matrix.hpp"
 #include "Rotation.hpp"
diff --git a/src/Math/Constants.hpp b/src/Math/Constants.hpp
index 9c62e94..7a712cc 100644
--- a/src/Math/Constants.hpp
+++ b/src/Math/Constants.hpp
@@ -1,8 +1,10 @@
 #pragma once
 
+#include "../Common/Sizes.hpp"
+
 namespace Math {
 
-constexpr double PI = 3.14159265358979323846;
-constexpr double E = 2.71828182845904523536;
+constexpr Real PI = 3.14159265358979323846;
+constexpr Real E = 2.71828182845904523536;
 
 }
\ No newline at end of file
diff --git a/src/Math/Grid.hpp b/src/Math/Grid.hpp
index e9907a0..8c0c423 100644
--- a/src/Math/Grid.hpp
+++ b/src/Math/Grid.hpp
@@ -5,7 +5,7 @@
 namespace Math {
 
 struct GridCellBoundaries {
-    float x1, x2, y1, y2;
+    Real x1, x2, y1, y2;
 
     [[nodiscard]] Vector<2> top_left() const;
     [[nodiscard]] Vector<2> top_right() const;
@@ -16,7 +16,7 @@ struct GridCellBoundaries {
 GridCellBoundaries grid_cell_for_point(Vector<2> point);
 
 struct CubeCellBoundaries {
-    float x1, x2, y1, y2, z1, z2;
+    Real x1, x2, y1, y2, z1, z2;
 
     [[nodiscard]] Vector<3> front_top_left() const;
     [[nodiscard]] Vector<3> front_top_right() const;
diff --git a/src/Math/Interpolation.cpp b/src/Math/Interpolation.cpp
index d5b2564..ce87435 100644
--- a/src/Math/Interpolation.cpp
+++ b/src/Math/Interpolation.cpp
@@ -3,18 +3,18 @@
 
 namespace Math {
 
-float linear_interpolation(Vector<2> val, float left, float right, float pos) {
+Real linear_interpolation(Vector<2> val, Real left, Real right, Real pos) {
     return val.x() + (pos - left) * (val.y() - val.x()) / (right - left);
 }
 
-float bilinear_interpolation(Matrix<2, 2> val, GridCellBoundaries cell, Vector<2> pos) {
+Real bilinear_interpolation(Matrix<2, 2> val, GridCellBoundaries cell, Vector<2> pos) {
     auto r1 = linear_interpolation(val.row(0), cell.x1, cell.x2, pos.x());
     auto r2 = linear_interpolation(val.row(1), cell.x1, cell.x2, pos.x());
 
     return linear_interpolation({r1, r2}, cell.y1, cell.y2, pos.y());
 }
 
-float trilinear_interpolation(Matrix<2, 2> val_front, Matrix<2, 2> val_back, const CubeCellBoundaries& cell, Vector<3> pos) {
+Real trilinear_interpolation(Matrix<2, 2> val_front, Matrix<2, 2> val_back, const CubeCellBoundaries& cell, Vector<3> pos) {
     auto r1 = bilinear_interpolation(val_front, cell.grid_cell(), {pos.x(), pos.y()});
     auto r2 = bilinear_interpolation(val_back, cell.grid_cell(), {pos.x(), pos.y()});
 
diff --git a/src/Math/Interpolation.hpp b/src/Math/Interpolation.hpp
index eaaa67d..476df5c 100644
--- a/src/Math/Interpolation.hpp
+++ b/src/Math/Interpolation.hpp
@@ -5,8 +5,8 @@
 
 namespace Math {
 
-float linear_interpolation(Vector<2> val, float left, float right, float pos);
-float bilinear_interpolation(Matrix<2, 2> val, GridCellBoundaries cell, Vector<2> pos);
-float trilinear_interpolation(Matrix<2, 2> val_front, Matrix<2, 2> val_back, const CubeCellBoundaries& cell, Vector<3> pos);
+Real linear_interpolation(Vector<2> val, Real left, Real right, Real pos);
+Real bilinear_interpolation(Matrix<2, 2> val, GridCellBoundaries cell, Vector<2> pos);
+Real trilinear_interpolation(Matrix<2, 2> val_front, Matrix<2, 2> val_back, const CubeCellBoundaries& cell, Vector<3> pos);
 
 }
\ No newline at end of file
diff --git a/src/Math/MVP.cpp b/src/Math/MVP.cpp
index de771d3..2f00b8e 100644
--- a/src/Math/MVP.cpp
+++ b/src/Math/MVP.cpp
@@ -4,56 +4,5 @@
 
 namespace Math::MVP {
 
-Matrix<4, 4> model(Vector<3> position, Rotation angles) {
-    auto transformation = Matrix<4, 4>::transformation(position);
-    auto rotation = Matrix<4, 4>::rotation(angles);
-
-    return transformation * rotation;
-}
-
-Matrix<4, 4> view(Vector<3> position, Rotation angles) {
-    auto rotation = Matrix<4, 4>::rotation(angles);
-    auto transformation = Matrix<4, 4>::transformation(-position);
-
-    return rotation * transformation;
-}
-
-Matrix<4, 4> perspective_projection(float aspect, float fov, float near, float far) {
-    auto fov_radians = radians(fov);
-
-    float x_scale = 1.0f / (tan(fov_radians / 2.0f) * aspect);
-    float y_scale = 1.0f / tan(fov_radians / 2.0f);
-
-    float frustum_length = far - near;
-    float z_near = -(far + near) / frustum_length;
-    float z_far = -(2 * far * near) / frustum_length;
-
-    Matrix<4, 4> projection{
-        x_scale, 0.0f,    0.0f,   0.0f,
-        0.0f,    y_scale, 0.0f,   0.0f,
-        0.0f,    0.0f,    z_near, z_far,
-        0.0f,    0.0f,    -1.0f,   0.0f,
-    };
-
-    return projection;
-}
-
-Matrix<4, 4> orthographic_projection(float width, float height, float near, float far) {
-    float x_scale = 2.0f / width;
-    float y_scale = 2.0f / -height;
-
-    float frustum_length = far - near;
-    float z_near = -(far + near) / frustum_length;
-    float z_far = -2 / frustum_length;
-
-    Matrix<4, 4> projection{
-            x_scale, 0.0f,    0.0f,   -1.0f,
-            0.0f,    y_scale, 0.0f,   1.0f,
-            0.0f,    0.0f,    z_near, z_far,
-            0.0f,    0.0f,    0.0f,   1.0f,
-    };
-
-    return projection;
-}
 
 }
diff --git a/src/Math/MVP.hpp b/src/Math/MVP.hpp
index af4fbbc..4046a50 100644
--- a/src/Math/MVP.hpp
+++ b/src/Math/MVP.hpp
@@ -4,9 +4,60 @@
 
 namespace Math::MVP {
 
-Matrix<4, 4> model(Vector<3> position, Rotation angles);
-Matrix<4, 4> view(Vector<3> position, Rotation angles);
-Matrix<4, 4> perspective_projection(float aspect, float fov, float near, float far);
-Matrix<4, 4> orthographic_projection(float width, float height, float near, float far);
+template<typename T = Real>
+Matrix<4, 4, T> model(Vector<3> position, Rotation angles) {
+    auto transformation = Matrix<4, 4, T>::transformation(position);
+    auto rotation = Matrix<4, 4, T>::rotation(angles);
+
+    return transformation * rotation;
+}
+
+template<typename T = Real>
+Matrix<4, 4, T> view(Vector<3> position, Rotation angles) {
+    auto rotation = Matrix<4, 4, T>::rotation(angles);
+    auto transformation = Matrix<4, 4, T>::transformation(-position);
+
+    return rotation * transformation;
+}
+
+template<typename T = Real>
+Matrix<4, 4, T> perspective_projection(Real aspect, Real fov, Real near, Real far) {
+    auto fov_radians = radians(fov);
+
+    Real x_scale = 1.0 / (tan(fov_radians / 2.0) * aspect);
+    Real y_scale = 1.0 / tan(fov_radians / 2.0);
+
+    Real frustum_length = far - near;
+    Real z_near = -(far + near) / frustum_length;
+    Real z_far = -(2 * far * near) / frustum_length;
+
+    Matrix<4, 4, T> projection{
+        x_scale, 0.0f,    0.0f,   0.0f,
+        0.0f,    y_scale, 0.0f,   0.0f,
+        0.0f,    0.0f,    z_near, z_far,
+        0.0f,    0.0f,    -1.0f,   0.0f,
+    };
+
+    return projection;
+}
+
+template<typename T = Real>
+Matrix<4, 4, T> orthographic_projection(Real width, Real height, Real near, Real far) {
+    Real x_scale = 2.0f / width;
+    Real y_scale = 2.0f / -height;
+
+    Real frustum_length = far - near;
+    Real z_near = -(far + near) / frustum_length;
+    Real z_far = -2 / frustum_length;
+
+    Matrix<4, 4, T> projection{
+        x_scale, 0.0f,    0.0f,   -1.0f,
+        0.0f,    y_scale, 0.0f,   1.0f,
+        0.0f,    0.0f,    z_near, z_far,
+        0.0f,    0.0f,    0.0f,   1.0f,
+    };
+
+    return projection;
+}
 
 }
diff --git a/src/Math/Matrix.hpp b/src/Math/Matrix.hpp
index 56663e0..d51d171 100644
--- a/src/Math/Matrix.hpp
+++ b/src/Math/Matrix.hpp
@@ -1,11 +1,11 @@
 #pragma once
 
 #include <sstream>
-#include <cstddef>
+#include "../Common/Sizes.hpp"
 #include "Rotation.hpp"
 #include "Trig.hpp"
 
-template <size_t R, size_t C, typename T = float>
+template <uint R, uint C, typename T = Real>
 struct Matrix {
     Matrix() : elements{} {}
 
@@ -13,8 +13,8 @@ struct Matrix {
         std::fill(elements, elements + R * C, scalar);
     }
 
-    template<typename ...Args, std::enable_if_t<sizeof...(Args) == R * C, int> = 0>
-    Matrix(Args... args): elements{ args... } {}
+    template<typename ...Args, std::enable_if_t<sizeof...(Args) == R * C, Int> = 0>
+    Matrix(Args... args): elements{ static_cast<T>(args)... } {}
 
     explicit Matrix(const T values[R * C]) {
         std::copy(values, values + R * C, elements);
@@ -22,42 +22,42 @@ struct Matrix {
 
     static Matrix<R, R, T> identity() {
         Matrix<R, R, T> result{};
-        for (int i = 0; i < R; i++) {
+        for (Int i = 0; i < R; i++) {
             result(i, i) = 1;
         }
         return result;
     }
 
-    static Matrix<4, 4> transformation(Vector<3> position) {
+    static Matrix<4, 4, T> transformation(Vector<3> position) {
         return {
-            1.0f, 0.0f, 0.0f, position.x(),
-            0.0f, 1.0f, 0.0f, position.y(),
-            0.0f, 0.0f, 1.0f, position.z(),
-            0.0f, 0.0f, 0.0f, 1.0f
+            1.0, 0.0, 0.0, position.x(),
+            0.0, 1.0, 0.0, position.y(),
+            0.0, 0.0, 1.0, position.z(),
+            0.0, 0.0, 0.0, 1.0
         };
     }
 
-    static Matrix<4, 4> rotation(Rotation angles) {
+    static Matrix<4, 4, T> rotation(Rotation angles) {
         auto radians = angles.vector.map([](auto a) { return Math::radians(a); });
 
         auto c = radians.map([](auto a) { return cos(a); });
         auto s = radians.map([](auto a) { return sin(a); });
 
-        Matrix<4, 4> rotation_x{
+        Matrix<4, 4, T> rotation_x{
             1.0f, 0.0f,  0.0f,   0.0f,
             0.0f, c.x(), -s.x(), 0.0f,
             0.0f, s.x(), c.x(),  0.0f,
             0.0f, 0.0f,  0.0f,   1.0f,
         };
 
-        Matrix<4, 4> rotation_y{
+        Matrix<4, 4, T> rotation_y{
             c.y(),  0.0f, s.y(),  0.0f,
             0.0f,   1.0f, 0.0f,   0.0f,
             -s.y(), 0.0f, c.y(),  0.0f,
             0.0f,   0.0f, 0.0f,   1.0f,
         };
 
-        Matrix<4, 4> rotation_z{
+        Matrix<4, 4, T> rotation_z{
             c.z(), -s.z(), 0.0f,  0.0f,
             s.z(), c.z(),  0.0f,  0.0f,
             0.0f,  0.0f,   1.0f,  0.0f,
@@ -67,13 +67,13 @@ struct Matrix {
         return rotation_x * rotation_y * rotation_z;
     }
 
-    Vector<C, T> row(size_t index) const {
+    Vector<C, T> row(USize index) const {
         return Vector<C, T>{ &elements[index * C] };
     }
 
-    Vector<R, T> col(size_t index) const {
+    Vector<R, T> col(USize index) const {
         Vector<R, T> result{};
-        for (int i = 0; i < R; i++) {
+        for (Int i = 0; i < R; i++) {
             result[i] = this->operator()(index, i);
         }
         return result;
@@ -81,8 +81,8 @@ struct Matrix {
 
     Matrix transpose() const {
         Matrix result{};
-        for (int y = 0; y < R; y++) {
-            for (int x = 0; x < C; x++) {
+        for (Int y = 0; y < R; y++) {
+            for (Int x = 0; x < C; x++) {
                 result(x, y) = this->operator()(y, x);
             }
         }
@@ -91,25 +91,25 @@ struct Matrix {
 
     Matrix operator+(const Matrix other) const {
         Matrix result{};
-        for (int i = 0; i < R * C; i++) {
+        for (Int i = 0; i < R * C; i++) {
             result.elements[i] = elements[i] + other.elements[i];
         }
         return result;
     }
 
-    Matrix operator*(float scalar) {
+    Matrix operator*(Real scalar) {
         Matrix result{};
-        for (int i = 0; i < R * C; i++) {
+        for (Int i = 0; i < R * C; i++) {
             result.elements[i] = elements[i] * scalar;
         }
         return result;
     }
 
-    template<size_t N>
+    template<uint N>
     Matrix<R, N, T> operator*(const Matrix<C, N, T> other) const {
         Matrix<R, N, T> result{};
-        for (int y = 0; y < R; y++) {
-            for (int x = 0; x < N; x++) {
+        for (Int y = 0; y < R; y++) {
+            for (Int x = 0; x < N; x++) {
                 auto r = row(y);
                 auto c = other.col(x);
 
@@ -127,17 +127,17 @@ struct Matrix {
         return Vector<R, T>{ matrix.elements };
     }
 
-    const T& operator()(const size_t x, const size_t y) const {
+    const T& operator()(const USize x, const USize y) const {
         return elements[y * C + x];
     }
-    T& operator()(const size_t x, const size_t y) {
+    T& operator()(const USize x, const USize y) {
         return elements[y * C + x];
     }
 
     std::string string() {
         std::stringstream str{};
-        for (int x = 0; x < R; x++) {
-            for (int y = 0; y < C; y++) {
+        for (Int x = 0; x < R; x++) {
+            for (Int y = 0; y < C; y++) {
                 str << this->operator()(x, y) << " ";
             }
 
diff --git a/src/Math/Perlin.cpp b/src/Math/Perlin.cpp
index 5614bb6..992a08e 100644
--- a/src/Math/Perlin.cpp
+++ b/src/Math/Perlin.cpp
@@ -4,11 +4,11 @@
 
 namespace Math::Perlin {
 
-float ease(float t) {
+Real ease(Real t) {
     return t * t * t * ((6 * t - 15) * t + 10);
 }
 
-uint8_t hash(uint8_t x) {
+U8 hash(U8 x) {
     auto rot = x * 5 % 8;
     return x << rot | x >> (8 - rot);
 }
@@ -23,7 +23,7 @@ Vector<2> gradient(Vector<2> pos) {
     return gradients[x % 4].normalize();
 }
 
-float raw(Vector<2> pos) {
+Real raw(Vector<2> pos) {
     auto cell = grid_cell_for_point(pos);
     auto uv = pos - cell.top_left();
 
@@ -47,7 +47,7 @@ float raw(Vector<2> pos) {
 }
 
 Vector<3> gradient(Vector<3> pos) {
-    constexpr float e = 0.5773502692;
+    constexpr Real e = 0.5773502692;
     static Vector<3> gradients[] = {
         {e, e, e}, {-e, e, e}, {e, -e, e}, {-e, -e, e},
         {e, e, -e}, {-e, e, -e}, {e, -e, -e}, {-e, -e, -e},
@@ -57,7 +57,7 @@ Vector<3> gradient(Vector<3> pos) {
     return gradients[x % 8];
 }
 
-float raw(Vector<3> pos) {
+Real raw(Vector<3> pos) {
     auto cell = cube_cell_for_point(pos);
     auto uv = pos - cell.front_top_left();
 
diff --git a/src/Math/Perlin.hpp b/src/Math/Perlin.hpp
index 17d33fd..b28f992 100644
--- a/src/Math/Perlin.hpp
+++ b/src/Math/Perlin.hpp
@@ -4,27 +4,27 @@
 
 namespace Math::Perlin {
 
-float raw(Vector<2> pos);
-float raw(Vector<3> pos);
+Real raw(Vector<2> pos);
+Real raw(Vector<3> pos);
 
-template <size_t D>
+template <USize D>
 struct Noise {
     static_assert(D > 1 && D < 4);
 
     Vector<D> offset{20000.0f};
-    float scale = 15.0f;
+    Real scale = 15.0f;
 
-    uint octaves = 3;
-    float persistence = 0.3f;
-    float lacunarity = 2.0f;
+    UInt octaves = 3;
+    Real persistence = 0.3f;
+    Real lacunarity = 2.0f;
 
-    float at(Vector<D> pos) const {
-        float result = 0;
-        float max = 0;
-        float frequency = 1;
-        float amplitude = 1;
+    Real at(Vector<D> pos) const {
+        Real result = 0;
+        Real max = 0;
+        Real frequency = 1;
+        Real amplitude = 1;
 
-        for (uint octave = 0; octave < octaves; octave++) {
+        for (UInt octave = 0; octave < octaves; octave++) {
             result += raw((pos + offset).abs() / scale * frequency) * amplitude;
             max += amplitude;
 
diff --git a/src/Math/Random.cpp b/src/Math/Random.cpp
index aa0ff55..cf3bbad 100644
--- a/src/Math/Random.cpp
+++ b/src/Math/Random.cpp
@@ -2,10 +2,8 @@
 
 namespace Math::Random {
 
-std::array<uint8_t, 4> break_float(const float f) {
-    static_assert(sizeof(float) == 4);
-
-    union { float f; uint8_t u[4]; } t{};
+std::array<U8, 4> break_float(const F32 f) {
+    union { F32 f; U8 u[4]; } t{};
     t.f = f;
 
     return {
@@ -13,18 +11,18 @@ std::array<uint8_t, 4> break_float(const float f) {
     };
 }
 
-float to_float(uint8_t u) {
-    return (float)u / (float)255;
+F32 to_float(U8 u) {
+    return (F32)u / (F32)255;
 }
 
-uint8_t hash(uint8_t x) {
+U8 hash(U8 x) {
     auto o = (x ^ 0xAA) * 5;
     auto rot = o % 8;
     return o << rot | o >> (8 - rot);
 }
 
-float random() {
-    uint8_t r = std::rand() % 255;
+Real random() {
+    U8 r = std::rand() % 255;
     return to_float(hash(r));
 }
 
diff --git a/src/Math/Random.hpp b/src/Math/Random.hpp
index ab94871..d363694 100644
--- a/src/Math/Random.hpp
+++ b/src/Math/Random.hpp
@@ -1,27 +1,27 @@
 #pragma once
 
-#include "array"
+#include <array>
 #include "Common.hpp"
 
 namespace Math::Random {
 
-std::array<uint8_t, 4> break_float(float f);
-float to_float(uint8_t u);
+std::array<U8, 4> break_float(F32 f);
+F32 to_float(U8 u);
 
-uint8_t hash(uint8_t x);
+U8 hash(U8 x);
 
-float random();
+Real random();
 
-template <size_t D>
+template <USize D>
 struct Noise {
-    float at(Vector<D> pos) const {
-        uint8_t to_hash[D * 4];
-        for (int i = 0; i < D; i++) {
+    Real at(Vector<D> pos) const {
+        U8 to_hash[D * 4];
+        for (Int i = 0; i < D; i++) {
             auto b = break_float(pos[i]);
             to_hash[i*4] = b[0]; to_hash[i*4+1] = b[1]; to_hash[i*4+2] = b[2]; to_hash[i*4+3] = b[3];
         }
-        uint8_t h = 0;
-        for (int i = 0; i < D * 4; i++) {
+        U8 h = 0;
+        for (Int i = 0; i < D * 4; i++) {
             h = hash(h) + to_hash[i];
         }
         return to_float(h);
diff --git a/src/Math/Rotation.hpp b/src/Math/Rotation.hpp
index a3420ed..83c1109 100644
--- a/src/Math/Rotation.hpp
+++ b/src/Math/Rotation.hpp
@@ -8,9 +8,9 @@ struct Rotation {
 
     Rotation(Vector<3> vector) : vector{ wrap(vector) } {}
 
-    explicit Rotation(float angles[3]) : Rotation(angles[0], angles[1], angles[2]) {}
+    explicit Rotation(Real angles[3]) : Rotation(angles[0], angles[1], angles[2]) {}
 
-    Rotation(float pitch, float yaw, float roll) {
+    Rotation(Real pitch, Real yaw, Real roll) {
         vector = wrap({pitch, yaw, roll });
     }
 
@@ -26,15 +26,15 @@ struct Rotation {
         return v.map([](auto a) { return fmod(a, 360.0f); });
     }
 
-    float& pitch() {
+    Real& pitch() {
         return vector[0];
     }
 
-    float& yaw() {
+    Real& yaw() {
         return vector[1];
     }
 
-    float& roll() {
+    Real& roll() {
         return vector[2];
     }
 
diff --git a/src/Math/Tensor.hpp b/src/Math/Tensor.hpp
index e373c1f..95c4548 100644
--- a/src/Math/Tensor.hpp
+++ b/src/Math/Tensor.hpp
@@ -1,14 +1,14 @@
 #pragma once
 
-template<size_t O, typename T, size_t ...S>
+template<uint O, typename T, uint ...S>
 struct Tensor {
-    static constexpr size_t element_size = (S*...);
+    static constexpr USize element_size = (S*...);
 
     template<typename ...Args>
-    using EnableArgs = std::enable_if_t<sizeof...(Args) == O, bool>;
+    using EnableArgs = std::enable_if_t<sizeof...(Args) == O, Bool>;
     template<typename ...Args>
-    using EnableArgsPerElement = std::enable_if_t<sizeof...(Args) == element_size, bool>;
-    using Enable = std::enable_if_t<sizeof...(S) == O, bool>;
+    using EnableArgsPerElement = std::enable_if_t<sizeof...(Args) == element_size, Bool>;
+    using Enable = std::enable_if_t<sizeof...(S) == O, Bool>;
 
     template<Enable = true>
     Tensor() : elements{} {}
@@ -19,7 +19,7 @@ struct Tensor {
     }
 
     template<Enable = true, typename ...Args, EnableArgsPerElement<Args...> = true>
-    Tensor(Args... args) : elements{ args... } {}
+    Tensor(Args... args) : elements{ static_cast<T>(args)... } {}
 
     template<typename ...Args, EnableArgs<Args...> = true>
     auto& operator()(Args... args) {
@@ -27,12 +27,12 @@ struct Tensor {
     }
 
     template<typename ...Args, EnableArgs<Args...> = true>
-    static constexpr size_t pos(Args... args) {
-        size_t positions[O] = {static_cast<size_t>(args)...};
-        size_t dimensions[O] = {S...};
+    static constexpr USize pos(Args... args) {
+        USize positions[O] = {static_cast<USize>(args)...};
+        USize dimensions[O] = {S...};
 
-        size_t p = 0;
-        for (int i = 0; i < O; i++) {
+        USize p = 0;
+        for (Int i = 0; i < O; i++) {
             p *= dimensions[i];
             p += positions[i];
         }
diff --git a/src/Math/Vector.hpp b/src/Math/Vector.hpp
index f6bdd7a..3d5a5be 100644
--- a/src/Math/Vector.hpp
+++ b/src/Math/Vector.hpp
@@ -1,15 +1,15 @@
 #pragma once
 
-#include <cstddef>
+#include "../Common/Sizes.hpp"
 #include <sstream>
 #include <cmath>
 
-template <size_t S, typename T = float>
+template <uint S, typename T = Real>
 struct Vector {
     Vector(): elements{} {}
 
-    template<typename ...Args, std::enable_if_t<sizeof...(Args) == S, int> = 0>
-    Vector(Args... args) : elements{ args... } {}
+    template<typename ...Args, std::enable_if_t<sizeof...(Args) == S, Int> = 0>
+    Vector(Args... args) : elements{ static_cast<T>(args)... } {}
 
     explicit Vector(const T values[S]) {
         std::copy(values, values + S, elements);
@@ -24,7 +24,7 @@ struct Vector {
         elements[S - 1] = scalar;
     }
 
-    template<size_t N, std::enable_if_t<(N > S), int> = 0>
+    template<uint N, std::enable_if_t<(N > S), Int> = 0>
     explicit Vector(const Vector<N, T> vector) {
         std::copy(vector.elements, vector.elements + S, elements);
     }
@@ -32,7 +32,7 @@ struct Vector {
     template<typename F>
     Vector map(F f) const {
         Vector result{};
-        for (int i = 0; i < S; i++) {
+        for (Int i = 0; i < S; i++) {
             result[i] = f(elements[i]);
         }
         return result;
@@ -41,7 +41,7 @@ struct Vector {
     template<typename F>
     Vector map_indexed(F f) const {
         Vector result{};
-        for (int i = 0; i < S; i++) {
+        for (Int i = 0; i < S; i++) {
             result[i] = f(i, elements[i]);
         }
         return result;
@@ -50,7 +50,7 @@ struct Vector {
     template<typename F>
     T reduce(F f) const {
         T result = elements[0];
-        for (int i = 1; i < S; i++) {
+        for (Int i = 1; i < S; i++) {
             result = f(result, elements[i]);
         }
         return result;
@@ -92,11 +92,11 @@ struct Vector {
         };
     }
 
-    T operator[](size_t index) const {
+    T operator[](USize index) const {
         return elements[index];
     }
 
-    T& operator[](size_t index) {
+    T& operator[](USize index) {
         return elements[index];
     }
 
@@ -128,8 +128,8 @@ struct Vector {
         return map([=](auto x) { return x / scalar; });
     }
 
-    bool operator==(const Vector& other) {
-        for (int i = 0; i < S; i++) {
+    Bool operator==(const Vector& other) {
+        for (Int i = 0; i < S; i++) {
             if (elements[i] != other[i]) {
                 return false;
             }
@@ -137,7 +137,7 @@ struct Vector {
         return true;
     }
 
-    bool operator!=(const Vector& other) {
+    Bool operator!=(const Vector& other) {
         return !this->operator==(other);
     }
 
@@ -162,7 +162,7 @@ struct Vector {
         std::stringstream str{};
 
         str << "[ ";
-        for (int i = 0; i < S; i++) {
+        for (Int i = 0; i < S; i++) {
             str << elements[i] << " ";
         }
         str << "]";
diff --git a/src/Util/ImageViewer.cpp b/src/Util/ImageViewer.cpp
index 9720408..8ff8c57 100644
--- a/src/Util/ImageViewer.cpp
+++ b/src/Util/ImageViewer.cpp
@@ -6,7 +6,7 @@ namespace MC::Util {
 
 ImageViewer::ImageViewer(
         const GFX::Image::RawImage& image,
-        float window_aspect
+        Real window_aspect
 ) : m_texture(image),
     m_program(
         {GFX::Shading::Shader::Type::Vertex, vertex},
@@ -18,9 +18,9 @@ ImageViewer::ImageViewer(
     auto view_uniform = m_program.uniform("view_matrix");
     auto projection_uniform = m_program.uniform("projection_matrix");
 
-    model_uniform.set(Math::MVP::model({}, {}));
-    view_uniform.set(Math::MVP::view({}, {}));
-    projection_uniform.set(Math::MVP::orthographic_projection(view_size * window_aspect, view_size, 0.0f, 100.0f));
+    model_uniform.set(Math::MVP::model<F32>({}, {}));
+    view_uniform.set(Math::MVP::view<F32>({}, {}));
+    projection_uniform.set(Math::MVP::orthographic_projection<F32>(view_size * window_aspect, view_size, 0.0f, 100.0f));
 
     m_program.unbind();
 }
@@ -35,23 +35,23 @@ void ImageViewer::render() const {
     m_program.unbind();
 }
 
-GFX::Mesh ImageViewer::create_mesh(float window_aspect, uint32_t image_width, uint32_t image_height) {
-    auto aspect = (float)image_width / image_height;
-    float max_size = view_size * 0.8f;
-    float width = max_size * std::min(1.0f, aspect);
-    float height = max_size * std::min(1.0f, 1/aspect);
+GFX::Mesh ImageViewer::create_mesh(Real window_aspect, U32 image_width, U32 image_height) {
+    auto aspect = (Real)image_width / image_height;
+    Real max_size = view_size * 0.8;
+    Real width = max_size * std::min(1.0, aspect);
+    Real height = max_size * std::min(1.0, 1/aspect);
 
-    float x = (view_size * window_aspect - width) / 2.0f;
-    float y = (view_size - height) / 2.0f;
+    Real x = (view_size * window_aspect - width) / 2.0f;
+    Real y = (view_size - height) / 2.0f;
 
     return {{
-        std::vector<Vector<3>>{
+        std::vector<Vector<3, F32>>{
             {x, y, 0.0f}, // top left
             {x, y + height, 0.0f}, // bottom left
             {x + width, y + height, 0.0f}, // bottom right
             {x + width, y, 0.0f}  // top right
         },
-        std::vector<Vector<2>>{
+        std::vector<Vector<2, F32>>{
             {0.0f, 0.0f},
             {0.0f, 1.0f},
             {1.0f, 1.0f},
@@ -60,7 +60,7 @@ GFX::Mesh ImageViewer::create_mesh(float window_aspect, uint32_t image_width, ui
     }, {0, 1, 2, 0, 2, 3}};
 }
 
-const char* ImageViewer::vertex = R"v(
+const Char* ImageViewer::vertex = R"v(
 #version 330 core
 
 uniform mat4 model_matrix;
@@ -77,7 +77,7 @@ void main() {
     frag_tex_coord = tex_coord;
 })v";
 
-const char* ImageViewer::fragment = R"f(
+const Char* ImageViewer::fragment = R"f(
 #version 330 core
 
 uniform sampler2D image;
diff --git a/src/Util/ImageViewer.hpp b/src/Util/ImageViewer.hpp
index 16ef2dd..1e18103 100644
--- a/src/Util/ImageViewer.hpp
+++ b/src/Util/ImageViewer.hpp
@@ -10,16 +10,16 @@ namespace MC::Util {
 
 class ImageViewer {
 public:
-    explicit ImageViewer(const GFX::Image::RawImage& image, float window_aspect);
+    explicit ImageViewer(const GFX::Image::RawImage& image, Real window_aspect);
 
     void render() const;
 private:
-    static GFX::Mesh create_mesh(float window_aspect, uint32_t image_width, uint32_t image_height);
+    static GFX::Mesh create_mesh(Real window_aspect, U32 image_width, U32 image_height);
 
-    static constexpr float view_size = 1000.0f;
+    static constexpr Real view_size = 1000.0f;
 
-    static const char* vertex;
-    static const char* fragment;
+    static const Char* vertex;
+    static const Char* fragment;
 
     GFX::BindableMesh m_mesh;
     GFX::Shading::Program m_program;
diff --git a/src/World/BiomeType.hpp b/src/World/BiomeType.hpp
index 40583d9..2380b60 100644
--- a/src/World/BiomeType.hpp
+++ b/src/World/BiomeType.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <cstdint>
+#include "../Common/Sizes.hpp"
 #include <vector>
 #include <string>
 
@@ -8,7 +8,7 @@ namespace MC::World {
 
 class BiomeType {
 public:
-    enum Value : uint8_t {
+    enum Value : U8 {
         Plains,
         Forest,
         Alpine,
@@ -21,7 +21,7 @@ public:
         Ocean,
     };
 
-    static constexpr uint8_t Size = Ocean + 1;
+    static constexpr U8 Size = Ocean + 1;
 
     BiomeType() : m_biome(Plains) {}
     BiomeType(const Value biome) : m_biome(biome) {}
diff --git a/src/World/BlockSide.hpp b/src/World/BlockSide.hpp
index 57d3c68..69df159 100644
--- a/src/World/BlockSide.hpp
+++ b/src/World/BlockSide.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <cstdint>
+#include "../Common/Sizes.hpp"
 #include <vector>
 #include <array>
 #include "../Math/Vector.hpp"
@@ -9,7 +9,7 @@ namespace MC::World {
 
 class BlockSide {
 public:
-    enum Value : uint8_t {
+    enum Value : U8 {
         Front,
         Back,
 
@@ -25,7 +25,7 @@ public:
 
     operator Value() const { return m_side; }
 
-    std::array<Vector<3>, 4> face() {
+    std::array<Vector<3, F32>, 4> face() {
         switch (m_side) {
             case Front:
                 return {{
diff --git a/src/World/BlockType.hpp b/src/World/BlockType.hpp
index 82c63d3..dbf6f78 100644
--- a/src/World/BlockType.hpp
+++ b/src/World/BlockType.hpp
@@ -1,13 +1,13 @@
 #pragma once
 
-#include <cstdint>
+#include "../Common/Sizes.hpp"
 #include <vector>
 
 namespace MC::World {
 
 class BlockType {
 public:
-    enum Value : uint8_t {
+    enum Value : U8 {
         Air,
         Dirt,
         Grass,
@@ -19,14 +19,14 @@ public:
         Water,
     };
 
-    static constexpr uint8_t Size = Water + 1;
+    static constexpr U8 Size = Water + 1;
 
     BlockType() : m_block(Air) {}
     BlockType(Value block) : m_block(block) {}
 
     operator Value() const { return m_block; }
 
-    bool is_transparent() const {
+    Bool is_transparent() const {
         switch (m_block) {
         case Air:
         case Leaves:
diff --git a/src/World/Chunk.cpp b/src/World/Chunk.cpp
index 079575a..94e757e 100644
--- a/src/World/Chunk.cpp
+++ b/src/World/Chunk.cpp
@@ -3,15 +3,15 @@
 
 namespace MC::World {
 
-void Chunk::set(uint32_t x, uint32_t y, uint32_t z, BlockData data) {
+void Chunk::set(U32 x, U32 y, U32 z, BlockData data) {
     m_blocks.at(pos(x, y, z)) = data;
 }
 
-Chunk::BlockData Chunk::get(uint32_t x, uint32_t y, uint32_t z) const {
+Chunk::BlockData Chunk::get(U32 x, U32 y, U32 z) const {
     return m_blocks.at(pos(x, y, z));
 }
 
-bool Chunk::is_empty(uint32_t x, uint32_t y, uint32_t z) const {
+Bool Chunk::is_empty(U32 x, U32 y, U32 z) const {
     return get(x, y, z).empty();
 }
 
@@ -19,11 +19,11 @@ Vector<3> Chunk::position() const {
     return m_position;
 }
 
-bool Chunk::is_valid_position(uint32_t x, uint32_t y, uint32_t z) {
+Bool Chunk::is_valid_position(U32 x, U32 y, U32 z) {
     return x < Width && y < Height && z < Width;
 }
 
-uint64_t Chunk::pos(uint32_t x, uint32_t y, uint32_t z) {
+U64 Chunk::pos(U32 x, U32 y, U32 z) {
     return x + Width * y + Width * Height * z;
 }
 
diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp
index b3eb06f..bc44137 100644
--- a/src/World/Chunk.hpp
+++ b/src/World/Chunk.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <cstdint>
+#include "../Common/Sizes.hpp"
 #include "BiomeType.hpp"
 #include "BlockType.hpp"
 #include "../GFX/Mesh.hpp"
@@ -10,22 +10,22 @@ namespace MC::World {
 
 class Chunk {
 public:
-    static constexpr uint32_t Width = 16;
-    static constexpr uint32_t Height = 128;
+    static constexpr U32 Width = 16;
+    static constexpr U32 Height = 128;
 
-    Chunk(int64_t x, int64_t y)
+    Chunk(I64 x, I64 y)
         : m_blocks{Width * Height * Width, {BlockType::Air}},
-        m_position{(float)x * Width, 0.0f, (float)y * Width} {}
+        m_position{(Real)x * Width, 0.0f, (Real)y * Width} {}
 
     struct BlockData {
         BlockType type;
 
-        bool empty() const { return type == BlockType::Air; }
+        Bool empty() const { return type == BlockType::Air; }
     };
 
-    void set(uint32_t x, uint32_t y, uint32_t z, BlockData data);
-    BlockData get(uint32_t x, uint32_t y, uint32_t z) const;
-    bool is_empty(uint32_t x, uint32_t y, uint32_t z) const;
+    void set(U32 x, U32 y, U32 z, BlockData data);
+    BlockData get(U32 x, U32 y, U32 z) const;
+    Bool is_empty(U32 x, U32 y, U32 z) const;
 
     struct Details {
         Matrix<Width, Width> landmass_values{};
@@ -41,9 +41,9 @@ public:
 
     Vector<3> position() const;
 
-    static bool is_valid_position(uint32_t x, uint32_t y, uint32_t z);
+    static Bool is_valid_position(U32 x, U32 y, U32 z);
 private:
-    static uint64_t pos(uint32_t x, uint32_t y, uint32_t z);
+    static U64 pos(U32 x, U32 y, U32 z);
 
     Vector<3> m_position;
     std::vector<BlockData> m_blocks;
diff --git a/src/World/ChunkIndex.hpp b/src/World/ChunkIndex.hpp
index ef61f24..7d6fdbf 100644
--- a/src/World/ChunkIndex.hpp
+++ b/src/World/ChunkIndex.hpp
@@ -1,30 +1,30 @@
 #pragma once
 
-#include <cstdint>
+#include "../Common/Sizes.hpp"
 
 namespace MC::World {
 
 struct ChunkIndex {
     ChunkIndex() : x(0), y(0) {}
-    ChunkIndex(int32_t x, int32_t y) : x(x), y(y) {}
+    ChunkIndex(I32 x, I32 y) : x(x), y(y) {}
 
     Vector<3> middle() const {
         return {(x + 0.5f) * Chunk::Width, Chunk::Height / 2.0f, (y + 0.5f) * Chunk::Width};
     }
 
-    int32_t x, y;
+    I32 x, y;
 };
 
 }
 
 template<> struct std::equal_to<MC::World::ChunkIndex> {
-    bool operator()(const MC::World::ChunkIndex& i1, const MC::World::ChunkIndex& i2) const noexcept {
+    Bool operator()(const MC::World::ChunkIndex& i1, const MC::World::ChunkIndex& i2) const noexcept {
         return i1.x == i2.x && i1.y == i2.y;
     }
 };
 
 template<> struct std::hash<MC::World::ChunkIndex> {
-    size_t operator()(const MC::World::ChunkIndex& i) const noexcept {
-        return (int64_t)i.x << 32 | i.y;
+    USize operator()(const MC::World::ChunkIndex& i) const noexcept {
+        return (I64)i.x << 32 | i.y;
     }
 };
\ No newline at end of file
diff --git a/src/World/Generation/ChunkMeshing.cpp b/src/World/Generation/ChunkMeshing.cpp
index e065987..8996169 100644
--- a/src/World/Generation/ChunkMeshing.cpp
+++ b/src/World/Generation/ChunkMeshing.cpp
@@ -2,20 +2,20 @@
 
 namespace MC::World::Generation {
 
-std::array<Vector<2>, 4> face_tex_coords(BlockType type, BlockSide side) {
-    uint8_t atlas_width = 4;
-    uint8_t atlas_height = 4;
+std::array<Vector<2, F32>, 4> face_tex_coords(BlockType type, BlockSide side) {
+    U8 atlas_width = 4;
+    U8 atlas_height = 4;
 
-    float width_step = 1.0f / atlas_width;
-    float height_step = 1.0f / atlas_height;
+    Real width_step = 1.0f / atlas_width;
+    Real height_step = 1.0f / atlas_height;
 
-    auto block_coords = [=](uint8_t x, uint8_t y) {
+    auto block_coords = [=](U8 x, U8 y) {
         auto t = y * height_step;
         auto l = x * width_step;
         auto b = t + height_step;
         auto r = l + width_step;
 
-        return std::array<Vector<2>, 4>{{
+        return std::array<Vector<2, F32>, 4>{{
             {l, b}, {r, b}, {r, t}, {l, t},
         }};
     };
@@ -71,10 +71,10 @@ std::array<Vector<2>, 4> face_tex_coords(BlockType type, BlockSide side) {
     }
 }
 
-std::array<Vector<3>, 4> face_normals(BlockSide side) {
-    auto is_side = [=](BlockSide s) -> float { return s == side; };
+std::array<Vector<3, F32>, 4> face_normals(BlockSide side) {
+    auto is_side = [=](BlockSide s) -> Real { return s == side; };
 
-    Vector<3> normal = {
+    Vector<3, F32> normal = {
         is_side(BlockSide::Right) - is_side(BlockSide::Left),
         is_side(BlockSide::Top) - is_side(BlockSide::Bottom),
         is_side(BlockSide::Front) - is_side(BlockSide::Back),
@@ -83,8 +83,8 @@ std::array<Vector<3>, 4> face_normals(BlockSide side) {
     return {normal, normal, normal, normal};
 }
 
-bool is_face_visible(Chunk& chunk, const ChunkMeshing::ChunkNeighbors& neighbors, uint32_t x, uint32_t y, uint32_t z, BlockSide side) {
-    Vector<3, int32_t> offset{};
+Bool is_face_visible(Chunk& chunk, const ChunkMeshing::ChunkNeighbors& neighbors, U32 x, U32 y, U32 z, BlockSide side) {
+    Vector<3, I32> offset{};
     switch (side) {
         case BlockSide::Front:
             offset[2] = 1;
@@ -106,8 +106,8 @@ bool is_face_visible(Chunk& chunk, const ChunkMeshing::ChunkNeighbors& neighbors
             break;
     }
 
-    Vector<3, int32_t> neighbor_pos{
-        (int32_t)x + offset.x(), (int32_t)y + offset.y(), (int32_t)z + offset.z(),
+    Vector<3, I32> neighbor_pos{
+        (I32)x + offset.x(), (I32)y + offset.y(), (I32)z + offset.z(),
     };
 
     Chunk* chunk_to_ask;
@@ -115,10 +115,10 @@ bool is_face_visible(Chunk& chunk, const ChunkMeshing::ChunkNeighbors& neighbors
     if (neighbor_pos.z() < 0) {
         chunk_to_ask = &neighbors.north;
         neighbor_pos.z() += Chunk::Width;
-    } else if (neighbor_pos.x() >= (int32_t)Chunk::Width) {
+    } else if (neighbor_pos.x() >= (I32)Chunk::Width) {
         chunk_to_ask = &neighbors.east;
         neighbor_pos.x() -= Chunk::Width;
-    } else if (neighbor_pos.z() >= (int32_t)Chunk::Width) {
+    } else if (neighbor_pos.z() >= (I32)Chunk::Width) {
         chunk_to_ask = &neighbors.south;
         neighbor_pos.z() -= Chunk::Width;
     } else if (neighbor_pos.x() < 0) {
@@ -133,14 +133,14 @@ bool is_face_visible(Chunk& chunk, const ChunkMeshing::ChunkNeighbors& neighbors
 }
 
 GFX::Mesh ChunkMeshing::create_mesh_for_chunk(Chunk& chunk, const ChunkNeighbors& neighbors) {
-    std::vector<Vector<3>> positions{};
-    std::vector<Vector<3>> normals{};
-    std::vector<Vector<2>> tex_coords{};
-    std::vector<uint32_t> indices{};
-
-    for (int x = 0; x < Chunk::Width; x++) {
-        for (int y = 0; y < Chunk::Height; y++) {
-            for (int z = 0; z < Chunk::Width; z++) {
+    std::vector<Vector<3, F32>> positions{};
+    std::vector<Vector<3, F32>> normals{};
+    std::vector<Vector<2, F32>> tex_coords{};
+    std::vector<U32> indices{};
+
+    for (Int x = 0; x < Chunk::Width; x++) {
+        for (Int y = 0; y < Chunk::Height; y++) {
+            for (Int z = 0; z < Chunk::Width; z++) {
                 auto type = chunk.get(x, y, z).type;
                 if (type == BlockType::Air) {
                     continue;
@@ -156,10 +156,10 @@ GFX::Mesh ChunkMeshing::create_mesh_for_chunk(Chunk& chunk, const ChunkNeighbors
                     auto side_tex_coords = face_tex_coords(type, side);
 
                     for (auto& position : side_positions) {
-                        position = position + Vector<3>{static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)};
+                        position = position + Vector<3, F32>{x, y, z};
                     }
 
-                    uint32_t s = positions.size();
+                    U32 s = positions.size();
 
                     positions.insert(positions.end(), side_positions.begin(), side_positions.end());
                     normals.insert(normals.end(), side_normals.begin(), side_normals.end());
@@ -170,7 +170,7 @@ GFX::Mesh ChunkMeshing::create_mesh_for_chunk(Chunk& chunk, const ChunkNeighbors
         }
     }
 
-    return GFX::Mesh{
+    return {
         {positions, normals, tex_coords},
         indices,
     };
diff --git a/src/World/Generation/Decoration.cpp b/src/World/Generation/Decoration.cpp
index 26eb397..f3f7c46 100644
--- a/src/World/Generation/Decoration.cpp
+++ b/src/World/Generation/Decoration.cpp
@@ -12,26 +12,26 @@ void Decorator::put_block(Chunk& chunk, Pos pos, BlockType block) {
     }
 }
 
-void Decorator::draw_column(Chunk& chunk, Pos pos, uint height, BlockType block) {
+void Decorator::draw_column(Chunk& chunk, Pos pos, UInt height, BlockType block) {
     Pos current_pos = pos;
-    for (uint i = 0; i < height; i++) {
+    for (UInt i = 0; i < height; i++) {
         put_block(chunk, current_pos, block);
         current_pos += Pos::up();
     }
 }
 
-void Decorator::draw_circle(Chunk& chunk, Pos pos, Vector<3> axis, float radius, BlockType block) {
+void Decorator::draw_circle(Chunk& chunk, Pos pos, Vector<3> axis, Real radius, BlockType block) {
     auto normalized_axis = axis.normalize();
 
     auto ortho1 = normalized_axis.any_orthogonal();
     auto ortho2 = normalized_axis.cross(ortho1);
 
-    auto r = [](const float x) { return static_cast<uint>(std::round(x)); };
+    auto r = [](const Real x) { return static_cast<UInt>(std::round(x)); };
 
-    int radius_round = std::round(radius);
-    for (int32_t d1 = -radius_round; d1 <= radius_round; d1++) {
-        float height = std::sqrt(radius * radius - d1 * d1);
-        for (int32_t d2 = -height; d2 <= (int)height; d2++) {
+    Int radius_round = std::round(radius);
+    for (I32 d1 = -radius_round; d1 <= radius_round; d1++) {
+        Real height = std::sqrt(radius * radius - d1 * d1);
+        for (I32 d2 = -height; d2 <= (Int)height; d2++) {
             auto p = ortho1 * d1 + ortho2 * d2;
             Pos block_pos = pos + Pos{r(p.x()), r(p.y()), r(p.z())};
             put_block(chunk, block_pos, block);
@@ -41,9 +41,9 @@ void Decorator::draw_circle(Chunk& chunk, Pos pos, Vector<3> axis, float radius,
 
 void TreeDecorator::decorate_chunk(Chunk& chunk) {
     Pos last_tree = Pos::max();
-    for (uint x = 0; x < Chunk::Width; x++) {
-        for (uint z = 0; z < Chunk::Width; z++) {
-            for (uint y = Chunk::Height; y > 1; y--) {
+    for (UInt x = 0; x < Chunk::Width; x++) {
+        for (UInt z = 0; z < Chunk::Width; z++) {
+            for (UInt y = Chunk::Height; y > 1; y--) {
                 Pos pos{x, y, z};
                 if (!is_valid_position(pos))
                     continue;
@@ -56,7 +56,7 @@ void TreeDecorator::decorate_chunk(Chunk& chunk) {
                 if (type != BlockType::Snow && type != BlockType::Grass && type != BlockType::Dirt)
                     break;
 
-                auto noise = m_tree_noise.at({(float)x, (float)z});
+                auto noise = m_tree_noise.at({(Real)x, (Real)z});
                 if (noise < 0.8f)
                     continue;
 
@@ -73,24 +73,24 @@ void TreeDecorator::decorate_chunk(Chunk& chunk) {
 }
 
 void TreeDecorator::draw_tree(Chunk& chunk, Pos pos) const {
-    auto noise = m_tree_noise.at({(float)pos.x(), (float)pos.z()});
-    uint height = std::round(10 * noise - 4.75f);
+    auto noise = m_tree_noise.at({(Real)pos.x(), (Real)pos.z()});
+    UInt height = std::round(10 * noise - 4.75f);
 
     draw_column(chunk, pos, height, BlockType::Wood);
 
-    uint max_leaf_height = 4;
-    for (int x = 0; x < max_leaf_height; x++) {
+    UInt max_leaf_height = 4;
+    for (Int x = 0; x < max_leaf_height; x++) {
         Pos p{pos.x(), pos.y() + height + x - 2, pos.z()};
-        float radius = s_tree_radius - 0.5f + x * ((0.3f * x - 1.45f) * x + 1.25f);
+        Real radius = s_tree_radius - 0.5f + x * ((0.3f * x - 1.45f) * x + 1.25f);
         draw_circle(chunk, p, Vector<3>::up(), radius, BlockType::Leaves);
     }
 }
 
-bool TreeDecorator::is_valid_position(Vector<3, uint> pos) {
-    int tree_radius = s_tree_radius;
-    return (int)pos.x() - tree_radius >= 0
+Bool TreeDecorator::is_valid_position(Vector<3, UInt> pos) {
+    Int tree_radius = s_tree_radius;
+    return (Int)pos.x() - tree_radius >= 0
         && pos.x() + tree_radius <= Chunk::Width
-        && (int)pos.z() - tree_radius >= 0
+        && (Int)pos.z() - tree_radius >= 0
         && pos.z() + tree_radius <= Chunk::Width;
 }
 
diff --git a/src/World/Generation/Decoration.hpp b/src/World/Generation/Decoration.hpp
index a592e72..b7a839b 100644
--- a/src/World/Generation/Decoration.hpp
+++ b/src/World/Generation/Decoration.hpp
@@ -7,15 +7,15 @@ namespace MC::World::Generation {
 
 class Decorator {
 public:
-    using Pos = Vector<3, uint>;
+    using Pos = Vector<3, UInt>;
 
     virtual ~Decorator() = default;
 
     virtual void decorate_chunk(Chunk& chunk) = 0;
 
     static void put_block(Chunk& chunk, Pos pos, BlockType block);
-    static void draw_column(Chunk& chunk, Pos pos, uint height, BlockType block);
-    static void draw_circle(Chunk& chunk, Pos pos, Vector<3> axis, float radius, BlockType block);
+    static void draw_column(Chunk& chunk, Pos pos, UInt height, BlockType block);
+    static void draw_circle(Chunk& chunk, Pos pos, Vector<3> axis, Real radius, BlockType block);
 };
 
 class TreeDecorator final : public Decorator {
@@ -24,9 +24,9 @@ public:
 private:
     void draw_tree(Chunk& chunk, Pos pos) const;
 
-    static bool is_valid_position(Pos pos);
+    static Bool is_valid_position(Pos pos);
 
-    static constexpr uint s_tree_radius = 3;
+    static constexpr UInt s_tree_radius = 3;
 
     Math::Random::Noise<2> m_tree_noise;
 };
diff --git a/src/World/Generation/Generator.cpp b/src/World/Generation/Generator.cpp
index 19a3dc8..88e69a7 100644
--- a/src/World/Generation/Generator.cpp
+++ b/src/World/Generation/Generator.cpp
@@ -4,7 +4,7 @@
 
 namespace MC::World::Generation {
 
-Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) {
+Chunk Generator::generate(I64 chunk_x, I64 chunk_y) {
     Chunk chunk(chunk_x, chunk_y);
 
     auto landmass_map = generate_landmass_map(chunk_x, chunk_y);
@@ -24,10 +24,10 @@ Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) {
 }
 
 #define SIMPLE_MAP_GENERATOR(name, getter)                                      \
-Generator::Map2D<float> Generator::name(int64_t chunk_x, int64_t chunk_y) {     \
+Generator::Map2D<Real> Generator::name(I64 chunk_x, I64 chunk_y) {     \
     Matrix<Chunk::Width, Chunk::Width> map{};                                   \
-    for (uint x = 0; x < Chunk::Width; x++) {                                   \
-        for (uint y = 0; y < Chunk::Width; y++) {                               \
+    for (UInt x = 0; x < Chunk::Width; x++) {                                   \
+        for (UInt y = 0; y < Chunk::Width; y++) {                               \
             auto pos = chunk_position_to_world_vector(chunk_x, chunk_y, x, y);  \
             map(x, y) = getter(pos);                                            \
         }                                                                       \
@@ -38,11 +38,11 @@ Generator::Map2D<float> Generator::name(int64_t chunk_x, int64_t chunk_y) {
 SIMPLE_MAP_GENERATOR(generate_landmass_map, get_landmass)
 SIMPLE_MAP_GENERATOR(generate_hill_map, get_hill)
 
-Generator::Map2D<float> Generator::generate_height_map(Map2D<float>& landmass_map, Map2D<float>& hill_map) {
-    Map2D<float> height_map{};
+Generator::Map2D<Real> Generator::generate_height_map(Map2D<Real>& landmass_map, Map2D<Real>& hill_map) {
+    Map2D<Real> height_map{};
 
-    for (uint x = 0; x < Chunk::Width; x++) {
-        for (uint y = 0; y < Chunk::Width; y++) {
+    for (UInt x = 0; x < Chunk::Width; x++) {
+        for (UInt y = 0; y < Chunk::Width; y++) {
             auto landmass_effect = landmass_map(x, y);
             auto hill_effect = hill_map(x, y);
 
@@ -62,18 +62,18 @@ SIMPLE_MAP_GENERATOR(generate_temperature_map, get_temperature)
 SIMPLE_MAP_GENERATOR(generate_humidity_map, get_humidity)
 
 Generator::Map2D<BiomeType> Generator::generate_biome_map(
-    Map2D<float>& landmass_map, Map2D<float>& hill_map,
-    Map2D<float>& temperature_map, Map2D<float>& humidity_map
+    Map2D<Real>& landmass_map, Map2D<Real>& hill_map,
+    Map2D<Real>& temperature_map, Map2D<Real>& humidity_map
 ) {
     Map2D<BiomeType> biome_map{};
 
-    for (uint x = 0; x < Chunk::Width; x++) {
-        for (uint y = 0; y < Chunk::Width; y++) {
-            float landmass = landmass_map(x, y);
-            float hill = hill_map(x, y);
+    for (UInt x = 0; x < Chunk::Width; x++) {
+        for (UInt y = 0; y < Chunk::Width; y++) {
+            Real landmass = landmass_map(x, y);
+            Real hill = hill_map(x, y);
 
-            float temperature = temperature_map(x, y);
-            float humidity = humidity_map(x, y);
+            Real temperature = temperature_map(x, y);
+            Real humidity = humidity_map(x, y);
 
             HillSlice hill_slice;
             if (hill > 0.55) { hill_slice = HillSlice::Mountain; }
@@ -103,17 +103,17 @@ Generator::Map2D<BiomeType> Generator::generate_biome_map(
     return biome_map;
 }
 
-Generator::Map3D<bool> Generator::generate_terrain(Map2D<float>& height_map, int64_t chunk_x, int64_t chunk_y) {
-    float jaggedness = 0.10f;
+Generator::Map3D<Bool> Generator::generate_terrain(Map2D<Real>& height_map, I64 chunk_x, I64 chunk_y) {
+    Real jaggedness = 0.10f;
 
-    Map3D<bool> terrain_map{};
-    for (uint x = 0; x < Chunk::Width; x++) {
-        for (uint z = 0; z < Chunk::Width; z++) {
+    Map3D<Bool> terrain_map{};
+    for (UInt x = 0; x < Chunk::Width; x++) {
+        for (UInt z = 0; z < Chunk::Width; z++) {
             auto height = height_map(x, z);
 
-            for (uint y = 0; y < Chunk::Height; y++) {
-                float density = get_density({Chunk::Width * chunk_x + (float)x, (float)y, Chunk::Width * chunk_y + (float)z});
-                float threshold = Math::sigmoid(((float)y / (Chunk::Height * height * 2) - 0.5f) / jaggedness);
+            for (UInt y = 0; y < Chunk::Height; y++) {
+                Real density = get_density({Chunk::Width * chunk_x + (Real)x, (Real)y, Chunk::Width * chunk_y + (Real)z});
+                Real threshold = Math::sigmoid(((Real)y / (Chunk::Height * height * 2) - 0.5f) / jaggedness);
 
                 if (density > threshold) {
                     terrain_map(x, y, z) = true;
@@ -125,12 +125,12 @@ Generator::Map3D<bool> Generator::generate_terrain(Map2D<float>& height_map, int
     return terrain_map;
 }
 
-void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<bool>& terrain_map) {
-    constexpr uint dirt_depth = 4;
-    constexpr uint water_height = 40;
+void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<Bool>& terrain_map) {
+    constexpr UInt dirt_depth = 4;
+    constexpr UInt water_height = 40;
 
-    for (uint x = 0; x < Chunk::Width; x++) {
-        for (uint z = 0; z < Chunk::Width; z++) {
+    for (UInt x = 0; x < Chunk::Width; x++) {
+        for (UInt z = 0; z < Chunk::Width; z++) {
             auto biome = biome_map(x, z);
 
             BlockType top_block{};
@@ -160,7 +160,7 @@ void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<b
             }
 
             auto column_depth = 0;
-            for (uint y = Chunk::Height - 1; y > 0; y--) {
+            for (UInt y = Chunk::Height - 1; y > 0; y--) {
                 auto block = terrain_map(x, y, z);
                 if (block) {
                     if (column_depth == 0 && y >= water_height - 1) {
@@ -186,11 +186,11 @@ void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<b
     }
 }
 
-#define CURVE_START(y) constexpr auto lerp = Math::linear_interpolation; float _py = (y); float _px = 0.0f;
+#define CURVE_START(y) constexpr auto lerp = Math::linear_interpolation; Real _py = (y); Real _px = 0.0f;
 #define CURVE_POINT(x, y) if (v < (x)) return lerp({_py, (y)}, _px, (x), v); _py = y; _px = (x)
 #define CURVE_END(y) return lerp({_py, (y)}, _px, 1.0f, v);
 
-float Generator::get_landmass(Vector<2> pos) const {
+Real Generator::get_landmass(Vector<2> pos) const {
     auto v = m_landmass_noise.at(pos);
 
     CURVE_START(1.0f);
@@ -205,7 +205,7 @@ float Generator::get_landmass(Vector<2> pos) const {
     CURVE_END(1.0f);
 }
 
-float Generator::get_hill(Vector<2> pos) const {
+Real Generator::get_hill(Vector<2> pos) const {
     auto v = m_hill_noise.at(pos);
 
     CURVE_START(0.33f);
@@ -219,30 +219,30 @@ float Generator::get_hill(Vector<2> pos) const {
     CURVE_END(0.33f);
 }
 
-float Generator::get_humidity(Vector<2> pos) const {
+Real Generator::get_humidity(Vector<2> pos) const {
     auto v = m_humidity_noise.at(pos);
     return v;
 }
 
-float Generator::get_temperature(Vector<2> pos) const {
+Real Generator::get_temperature(Vector<2> pos) const {
     auto v = m_temperature_noise.at(pos);
     return v;
 }
 
-float Generator::get_density(Vector<3> pos) const {
+Real Generator::get_density(Vector<3> pos) const {
     auto v = m_density_noise.at(pos);
     return v;
 }
 
-Vector<2> Generator::chunk_position_to_world_vector(int64_t chunk_x, int64_t chunk_y, uint x, uint y) {
-    return {(float)x + chunk_x * Chunk::Width, (float)y + chunk_y * Chunk::Width};
+Vector<2> Generator::chunk_position_to_world_vector(I64 chunk_x, I64 chunk_y, UInt x, UInt y) {
+    return {(Real)x + chunk_x * Chunk::Width, (Real)y + chunk_y * Chunk::Width};
 }
 
 std::array<BiomeType, Generator::biome_lookup_table_size> Generator::create_biome_lookup_table() {
     std::array<BiomeType, biome_lookup_table_size> table{};
 
-    auto inc = [](auto& x) { x = (std::remove_reference_t<decltype(x)>)((uint)x + 1); };
-    auto cmp = [](auto x, auto s) { return (uint)x < (uint)s; };
+    auto inc = [](auto& x) { x = (std::remove_reference_t<decltype(x)>)((UInt)x + 1); };
+    auto cmp = [](auto x, auto s) { return (UInt)x < (UInt)s; };
 
     for (HillSlice hill_slice{}; cmp(hill_slice, HillSliceSize); inc(hill_slice)) {
         for (LandmassSlice landmass_slice{}; cmp(landmass_slice, LandmassSliceSize); inc(landmass_slice)) {
@@ -317,9 +317,9 @@ std::array<BiomeType, Generator::biome_lookup_table_size> Generator::create_biom
     return table;
 }
 
-size_t Generator::biome_lookup_table_index(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone) {
-    auto hs = (uint8_t)hill_slice; auto ls = (uint8_t)landmass_slice; auto tz = (uint8_t)temperature_zone; auto hz = (uint8_t)humidity_zone;
-    auto LS_S = (uint8_t)LandmassSliceSize; auto TZ_S = (uint8_t)TemperatureZoneSize; auto HZ_S = (uint8_t)HumidityZoneSize;
+USize Generator::biome_lookup_table_index(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone) {
+    auto hs = (U8)hill_slice; auto ls = (U8)landmass_slice; auto tz = (U8)temperature_zone; auto hz = (U8)humidity_zone;
+    auto LS_S = (U8)LandmassSliceSize; auto TZ_S = (U8)TemperatureZoneSize; auto HZ_S = (U8)HumidityZoneSize;
     return (hs * LS_S * TZ_S * HZ_S) + (ls * TZ_S * HZ_S) + (tz * HZ_S) + hz;
 }
 
diff --git a/src/World/Generation/Generator.hpp b/src/World/Generation/Generator.hpp
index c18de45..ee78dc5 100644
--- a/src/World/Generation/Generator.hpp
+++ b/src/World/Generation/Generator.hpp
@@ -1,48 +1,47 @@
 #pragma once
 
-#include <cstdint>
-
-#include "Decoration.hpp"
+#include "../../Common/Sizes.hpp"
 #include "../Chunk.hpp"
 #include "../BiomeType.hpp"
 #include "../../Math/Perlin.hpp"
 #include "../../Math/Tensor.hpp"
+#include "Decoration.hpp"
 
 namespace MC::World::Generation {
 
 class Generator {
 public:
     Generator() = default;
-    Chunk generate(int64_t chunk_x, int64_t chunk_y);
+    Chunk generate(I64 chunk_x, I64 chunk_y);
 private:
     template <typename V> using Map2D = Matrix<Chunk::Width, Chunk::Width, V>;
     template <typename V> using Map3D = Tensor<3, V, Chunk::Width, Chunk::Height, Chunk::Width>;
 
-    Map2D<float> generate_landmass_map(int64_t chunk_x, int64_t chunk_y);
-    Map2D<float> generate_hill_map(int64_t chunk_x, int64_t chunk_y);
-    Map2D<float> generate_height_map(Map2D<float>& landmass_map, Map2D<float>& hill_map);
+    Map2D<Real> generate_landmass_map(I64 chunk_x, I64 chunk_y);
+    Map2D<Real> generate_hill_map(I64 chunk_x, I64 chunk_y);
+    Map2D<Real> generate_height_map(Map2D<Real>& landmass_map, Map2D<Real>& hill_map);
 
-    Map2D<float> generate_temperature_map(int64_t chunk_x, int64_t chunk_y);
-    Map2D<float> generate_humidity_map(int64_t chunk_x, int64_t chunk_y);
+    Map2D<Real> generate_temperature_map(I64 chunk_x, I64 chunk_y);
+    Map2D<Real> generate_humidity_map(I64 chunk_x, I64 chunk_y);
 
     Map2D<BiomeType> generate_biome_map(
-        Map2D<float>& landmass_map, Map2D<float>& hill_map,
-        Map2D<float>& temperature_map, Map2D<float>& humidity_map
+        Map2D<Real>& landmass_map, Map2D<Real>& hill_map,
+        Map2D<Real>& temperature_map, Map2D<Real>& humidity_map
     );
 
-    Map3D<bool> generate_terrain(Map2D<float>& height_map, int64_t chunk_x, int64_t chunk_y);
+    Map3D<Bool> generate_terrain(Map2D<Real>& height_map, I64 chunk_x, I64 chunk_y);
 
-    void decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<bool>& terrain_map);
+    void decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<Bool>& terrain_map);
 
-    [[nodiscard]] float get_landmass(Vector<2> pos) const;
-    [[nodiscard]] float get_hill(Vector<2> pos) const;
+    [[nodiscard]] Real get_landmass(Vector<2> pos) const;
+    [[nodiscard]] Real get_hill(Vector<2> pos) const;
 
-    [[nodiscard]] float get_humidity(Vector<2> pos) const;
-    [[nodiscard]] float get_temperature(Vector<2> pos) const;
+    [[nodiscard]] Real get_humidity(Vector<2> pos) const;
+    [[nodiscard]] Real get_temperature(Vector<2> pos) const;
 
-    [[nodiscard]] float get_density(Vector<3> pos) const;
+    [[nodiscard]] Real get_density(Vector<3> pos) const;
 
-    static Vector<2> chunk_position_to_world_vector(int64_t chunk_x, int64_t chunk_y, uint x, uint y);
+    static Vector<2> chunk_position_to_world_vector(I64 chunk_x, I64 chunk_y, UInt x, UInt y);
 
     static inline std::vector<Decorator*> s_decorators = {
         new TreeDecorator(),
@@ -60,14 +59,14 @@ private:
     enum class LandmassSlice { Land, Beach, Ocean };
     enum class TemperatureZone { Hot, Fair, Cold };
     enum class HumidityZone { Wet, Lush, Temperate, Dry };
-    static constexpr uint HillSliceSize = (uint)HillSlice::Valley + 1;
-    static constexpr uint LandmassSliceSize = (uint)LandmassSlice::Ocean + 1;
-    static constexpr uint TemperatureZoneSize = (uint)TemperatureZone::Cold + 1;
-    static constexpr uint HumidityZoneSize = (uint)HumidityZone::Dry + 1;
+    static constexpr UInt HillSliceSize = (UInt)HillSlice::Valley + 1;
+    static constexpr UInt LandmassSliceSize = (UInt)LandmassSlice::Ocean + 1;
+    static constexpr UInt TemperatureZoneSize = (UInt)TemperatureZone::Cold + 1;
+    static constexpr UInt HumidityZoneSize = (UInt)HumidityZone::Dry + 1;
 
-    static constexpr size_t biome_lookup_table_size = (size_t)HillSliceSize * (size_t)LandmassSliceSize * (size_t)TemperatureZoneSize * (size_t)HumidityZoneSize;
+    static constexpr USize biome_lookup_table_size = (USize)HillSliceSize * (USize)LandmassSliceSize * (USize)TemperatureZoneSize * (USize)HumidityZoneSize;
     static std::array<BiomeType, biome_lookup_table_size> create_biome_lookup_table();
-    static size_t biome_lookup_table_index(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone);
+    static USize biome_lookup_table_index(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone);
     static BiomeType lookup_biome(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone);
     static inline std::array<BiomeType, biome_lookup_table_size> biome_lookup_table = create_biome_lookup_table();
 };
diff --git a/src/World/World.cpp b/src/World/World.cpp
index 7570d8c..a0b2b0d 100644
--- a/src/World/World.cpp
+++ b/src/World/World.cpp
@@ -36,8 +36,8 @@ std::vector<World::ChunkData*> World::get_visible_chunks(Vector<3> position) {
 }
 
 Chunk* World::get_chunk_for_position(Vector<3> position) {
-    int32_t x = std::round(position.x() / Chunk::Width);
-    int32_t y = std::round(position.z() / Chunk::Width);
+    I32 x = std::round(position.x() / Chunk::Width);
+    I32 y = std::round(position.z() / Chunk::Width);
     auto& data = get({x, y});
     if (data.chunk.has_value()) {
         return &data.chunk.value();
@@ -56,15 +56,15 @@ void World::process_chunk_visibility_updates(const std::unordered_set<ChunkIndex
 }
 
 std::unordered_set<ChunkIndex> World::get_visible_chunk_indices(const Vector<3> position) const {
-    int32_t center_x = std::round(position.x() / Chunk::Width);
-    int32_t center_y = std::round(position.z() / Chunk::Width);
+    I32 center_x = std::round(position.x() / Chunk::Width);
+    I32 center_y = std::round(position.z() / Chunk::Width);
 
     std::unordered_set<ChunkIndex> indices{};
     indices.reserve(m_view_distance_radius * m_view_distance_radius * 4);
     auto radius = m_view_distance_radius;
-    for (int32_t x = -radius; x <= radius; x++) {
-        int32_t height = std::round(std::sqrt(radius * radius - x * x) + 0.5);
-        for (int32_t y = -height; y <= height; y++) {
+    for (I32 x = -radius; x <= radius; x++) {
+        I32 height = std::round(std::sqrt(radius * radius - x * x) + 0.5);
+        for (I32 y = -height; y <= height; y++) {
             indices.emplace(x + center_x, y + center_y);
         }
     }
@@ -85,7 +85,7 @@ std::unordered_set<ChunkIndex> World::load_finished_chunks_from_queue() {
     return indices;
 }
 
-void World::request_generation(ChunkIndex index, float priority) {
+void World::request_generation(ChunkIndex index, Real priority) {
     m_queue.add(index, priority, [=]() -> GenerationResult {
         auto start = timestamp();
         auto chunk = m_generator.generate(index.x, index.y);
@@ -105,7 +105,7 @@ World::ChunkData& World::get(ChunkIndex index) {
     return entry->second;
 }
 
-uint64_t World::timestamp() {
+U64 World::timestamp() {
     auto time = std::chrono::system_clock::now().time_since_epoch();
     auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(time);
     return ms.count();
@@ -135,12 +135,12 @@ void World::try_to_create_mesh_for_chunk(ChunkData& data) {
     data.status = ChunkStatus::Done;
 }
 
-void World::log_chunk_time(uint64_t chunk_time_ms) {
+void World::log_chunk_time(U64 chunk_time_ms) {
     m_statistics.chunk_time_sample_count++;
-    m_statistics.average_chunk_time_ms += ((float)chunk_time_ms - m_statistics.average_chunk_time_ms) / m_statistics.chunk_time_sample_count;
+    m_statistics.average_chunk_time_ms += ((Real)chunk_time_ms - m_statistics.average_chunk_time_ms) / m_statistics.chunk_time_sample_count;
 }
 
-float World::get_average_chunk_time() const {
+Real World::get_average_chunk_time() const {
     return m_statistics.average_chunk_time_ms;
 }
 
diff --git a/src/World/World.hpp b/src/World/World.hpp
index bc008b3..ae9f2a4 100644
--- a/src/World/World.hpp
+++ b/src/World/World.hpp
@@ -32,25 +32,25 @@ public:
     std::vector<ChunkData*> get_visible_chunks(Vector<3> position);
     Chunk* get_chunk_for_position(Vector<3> position);
 
-    float get_average_chunk_time() const;
+    Real get_average_chunk_time() const;
 private:
     std::unordered_set<ChunkIndex> get_visible_chunk_indices(Vector<3> position) const;
     std::unordered_set<ChunkIndex> load_finished_chunks_from_queue();
     void process_chunk_visibility_updates(const std::unordered_set<ChunkIndex>& new_chunks, Vector<3> player);
-    void request_generation(ChunkIndex index, float priority);
+    void request_generation(ChunkIndex index, Real priority);
     void try_to_create_mesh_for_chunk(ChunkData& data);
 
-    void log_chunk_time(uint64_t chunk_time_ms);
+    void log_chunk_time(U64 chunk_time_ms);
 
     ChunkData& get(ChunkIndex index);
 
-    static uint64_t timestamp();
+    static U64 timestamp();
 
-    uint8_t m_view_distance_radius = 13;
+    U8 m_view_distance_radius = 13;
 
     struct GenerationResult {
         Chunk chunk;
-        uint64_t generation_duration;
+        U64 generation_duration;
     };
     Compute::Queue<GenerationResult, ChunkIndex> m_queue;
     Generation::Generator m_generator;
@@ -59,8 +59,8 @@ private:
     std::unordered_set<ChunkIndex> m_visible_chunks;
 
     struct Statistics {
-        uint chunk_time_sample_count;
-        float average_chunk_time_ms;
+        UInt chunk_time_sample_count;
+        Real average_chunk_time_ms;
     };
     Statistics m_statistics{0, 0.0f};
 };
diff --git a/src/main.cpp b/src/main.cpp
index 0995b5b..6a6f9ee 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,6 +2,7 @@
 #include <GL/glew.h>
 #include <GLFW/glfw3.h>
 
+#include "Common/Sizes.hpp"
 #include "GFX/Window.hpp"
 #include "GFX/Camera.hpp"
 #include "GFX/Binder.hpp"
@@ -15,7 +16,7 @@
 
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 600
-#define ASPECT (static_cast<float>(WINDOW_WIDTH) / WINDOW_HEIGHT)
+#define ASPECT (static_cast<Real>(WINDOW_WIDTH) / WINDOW_HEIGHT)
 
 #define FOV 90
 
@@ -45,7 +46,7 @@ void run() {
     setup_gl();
 
     glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
-    window.on_size_change([](GLFWwindow* _, int w, int h) {
+    window.on_size_change([](GLFWwindow* _, I32 w, I32 h) {
         glViewport(0, 0, w, h);
     });
 
@@ -69,13 +70,13 @@ void run() {
     auto sky_color_uniform = program.uniform("sky_color");
 
     program.bind();
-    auto projection = Math::MVP::perspective_projection(ASPECT, FOV, 0.1f, 1000.0f);
+    auto projection = Math::MVP::perspective_projection<F32>(ASPECT, FOV, 0.1f, 1000.0f);
     projection_uniform.set(projection);
 
-    Vector<3> sun_direction{1.0f, -1.0f, 0.0f};
+    Vector<3, F32> sun_direction{1.0f, -1.0f, 0.0f};
     sun_direction_uniform.set(sun_direction);
 
-    Vector<3> sky_color{0.85f, 0.85f, 0.85f}; // #DBDBDB
+    Vector<3, F32> sky_color{0.85f, 0.85f, 0.85f}; // #DBDBDB
     sky_color_uniform.set(sky_color);
 
     glEnable(GL_DEPTH_TEST);
@@ -84,7 +85,7 @@ void run() {
     glEnable(GL_CULL_FACE);
     glCullFace(GL_BACK);
 
-    uint64_t time = 0;
+    U64 time = 0;
 
     while (!window.should_close()) {
         window.start_frame();
@@ -97,13 +98,13 @@ void run() {
 
         program.bind();
 
-        auto view = Math::MVP::view(camera.position(), camera.angles());
+        auto view = Math::MVP::view<F32>(camera.position(), camera.angles());
         view_uniform.set(view);
 
         glClearColor(sky_color.x(), sky_color.y(), sky_color.z(), 1.0f); // #DBDBDB
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         for (auto chunk : world.get_visible_chunks(camera.position())) {
-            auto model = Math::MVP::model(chunk->chunk.value().position(), {});
+            auto model = Math::MVP::model<F32>(chunk->chunk.value().position(), {});
             model_uniform.set(model);
             render(chunk->mesh.value(), texture);
         }
@@ -127,12 +128,12 @@ void process_input(MC::GFX::Window& window, MC::GFX::Camera& camera) {
 
     auto r = window.mouse_delta();
 
-    auto key = [&](int k) -> float { return window.key(k, GLFW_PRESS); };
+    auto key = [&](Int k) -> Real { return window.key(k, GLFW_PRESS); };
 
-    float x = key(GLFW_KEY_D) - key(GLFW_KEY_A);
-    float y = key(GLFW_KEY_SPACE) - key(GLFW_KEY_LEFT_SHIFT);
-    float z = key(GLFW_KEY_S) - key(GLFW_KEY_W);
-    float boost = key(GLFW_KEY_LEFT_CONTROL) * 2.0f;
+    Real x = key(GLFW_KEY_D) - key(GLFW_KEY_A);
+    Real y = key(GLFW_KEY_SPACE) - key(GLFW_KEY_LEFT_SHIFT);
+    Real z = key(GLFW_KEY_S) - key(GLFW_KEY_W);
+    Real boost = key(GLFW_KEY_LEFT_CONTROL) * 2.0f;
 
     auto move_speed = 0.2f + boost;
     auto rotation_speed = 0.1f;
@@ -145,16 +146,16 @@ void process_input(MC::GFX::Window& window, MC::GFX::Camera& camera) {
 void setup_gl() {
     GLenum error;
     if ((error = glewInit()) != GLEW_OK) {
-        std::string error_string(reinterpret_cast<const char*>(glewGetErrorString(error)));
+        std::string error_string(reinterpret_cast<const Char*>(glewGetErrorString(error)));
         throw std::runtime_error("Failed to load GL functions: " + error_string);
     }
 }
 
 void fix_macos_render(const MC::GFX::Window& window) {
-    static bool moved = false;
+    static Bool moved = false;
 
     if(!moved) {
-        int x, y;
+        I32 x, y;
         glfwGetWindowPos(window.get(), &x, &y);
         glfwSetWindowPos(window.get(), ++x, y);