From ad9344f3f8b3601bae5239f1549ef4484647101f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9au?= <theau.baton@etu.univ-amu.fr>
Date: Wed, 13 Nov 2024 19:21:27 +0100
Subject: [PATCH] Add vertexArray

---
 assets/shaders/FrameBuffer-Instanced.frag     |   7 +-
 assets/shaders/Grid-Instanced.frag            |  10 ++
 assets/shaders/Grid-Instanced.vert            |  19 ++++
 assets/textures/Test.png                      | Bin 37257 -> 0 bytes
 assets/textures/Tile_Test.png                 | Bin 0 -> 1202 bytes
 assets/textures/Tile_Test_2.png               | Bin 0 -> 2079 bytes
 assets/textures/Tile_Test_3.png               | Bin 0 -> 604 bytes
 .../graphics/back/geometry/Geometry.hpp       |   3 +-
 .../engine/graphics/back/shaders/Program.cpp  |  11 ++
 .../engine/graphics/back/shaders/Program.hpp  |   2 +
 .../engine/graphics/front/engine/Engine.cpp   |   9 +-
 .../engine/graphics/front/engine/Engine.hpp   |   1 +
 .../engine/graphics/front/geometry/Plane.hpp  |   1 +
 .../engine/graphics/front/geometry/Quads.cpp  |   4 +-
 .../engine/graphics/front/geometry/Quads.hpp  |   1 +
 .../engine/graphics/front/geometry/Vertex.hpp |  10 ++
 .../graphics/front/group/FrameBufferGroup.cpp |   5 +-
 .../graphics/front/group/FrameBufferGroup.hpp |   2 +
 .../graphics/front/group/ImageGroup.cpp       |  14 +--
 .../graphics/front/group/VertexArrayGroup.cpp |  42 ++++++++
 .../graphics/front/group/VertexArrayGroup.hpp |  33 ++++++
 .../graphics/front/object/VerticesArray.cpp   |  20 ++++
 .../graphics/front/object/VerticesArray.hpp   |  37 +++++++
 .../graphics/utility/texture_comparator.hpp   |  11 ++
 source/main.cpp                               |  94 +++++++++++++++++-
 25 files changed, 316 insertions(+), 20 deletions(-)
 create mode 100644 assets/shaders/Grid-Instanced.frag
 create mode 100644 assets/shaders/Grid-Instanced.vert
 delete mode 100644 assets/textures/Test.png
 create mode 100644 assets/textures/Tile_Test.png
 create mode 100644 assets/textures/Tile_Test_2.png
 create mode 100644 assets/textures/Tile_Test_3.png
 create mode 100644 source/engine/graphics/front/geometry/Vertex.hpp
 create mode 100644 source/engine/graphics/front/group/VertexArrayGroup.cpp
 create mode 100644 source/engine/graphics/front/group/VertexArrayGroup.hpp
 create mode 100644 source/engine/graphics/front/object/VerticesArray.cpp
 create mode 100644 source/engine/graphics/front/object/VerticesArray.hpp
 create mode 100644 source/engine/graphics/utility/texture_comparator.hpp

diff --git a/assets/shaders/FrameBuffer-Instanced.frag b/assets/shaders/FrameBuffer-Instanced.frag
index 2db481d..736ee8a 100644
--- a/assets/shaders/FrameBuffer-Instanced.frag
+++ b/assets/shaders/FrameBuffer-Instanced.frag
@@ -6,20 +6,21 @@ in vec2 Texture;
 
 uniform sampler2D uSampler[32];
 uniform uint uTexturesCount;
+uniform vec3 uClearColor;
 
 void main() {
     vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
     for(uint i = 0; i < uTexturesCount; ++i) {
         vec4 tcolor = texture(uSampler[i], Texture);
-        if(tcolor.r != 0.0) {
+        if(tcolor.r != uClearColor.r) {
             color.r = tcolor.r;
         }
 
-        if(tcolor.g != 0.0) {
+        if(tcolor.g != uClearColor.g) {
             color.g = tcolor.g;
         }
 
-        if(tcolor.b != 0.0) {
+        if(tcolor.b != uClearColor.b) {
             color.b = tcolor.b;
         }
     }
diff --git a/assets/shaders/Grid-Instanced.frag b/assets/shaders/Grid-Instanced.frag
new file mode 100644
index 0000000..6860880
--- /dev/null
+++ b/assets/shaders/Grid-Instanced.frag
@@ -0,0 +1,10 @@
+#version 450 core
+out vec4 FragColor;
+
+in vec2 Texture;
+
+uniform sampler2D uSampler;
+
+void main() {
+    FragColor = texture(uSampler, Texture);
+}
\ No newline at end of file
diff --git a/assets/shaders/Grid-Instanced.vert b/assets/shaders/Grid-Instanced.vert
new file mode 100644
index 0000000..f9d3622
--- /dev/null
+++ b/assets/shaders/Grid-Instanced.vert
@@ -0,0 +1,19 @@
+#version 450 core
+layout (location = 0) in vec2 aPos;
+layout (location = 1) in vec2 aTex;
+
+uniform mat4 uProj;
+uniform mat4 uView;
+uniform mat4 uModel;
+
+uniform vec4 uData[254];
+
+out vec2 Texture;
+out vec2 Color;
+
+void main() {
+    vec4 usedData = uData[gl_VertexID];
+    Texture = usedData.zw;
+
+    gl_Position = uProj * uView * uModel * vec4(aPos.x + usedData.x, aPos.y + usedData.y, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/assets/textures/Test.png b/assets/textures/Test.png
deleted file mode 100644
index 5900cdb901de8ec21b580869c01c70d32e764dae..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 37257
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

diff --git a/assets/textures/Tile_Test.png b/assets/textures/Tile_Test.png
new file mode 100644
index 0000000000000000000000000000000000000000..d25e9e0324403cbccc67e1a0eed3fdbb9b63e694
GIT binary patch
literal 1202
zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}jKx9jP7LeL$-HD>U|>mi
z^mSxl*x1kgCy|wbfq}EYBeIx*f$snaGiF`u<YZuAarbm_42f{xJH0w5#8srdK76Al
zE3bm?ja4=}N`b<QU4FOsuMiYw;n9kk@3JE5f<&^CoAS1Oi`0&-QkW6o5g;h-%Bz&w
zV#3AsQLtG}&2?hXkyWBmky}MpthxW@%%<IYH@|*+?N_S*vwJ%?7uOpXKby1Du~%e$
zXdO$ZyiVV7;neuZ_|*;dX@5V<-%y@Wd769KA?FP@K7YS|drAJi$=`Aoe^<Wr!t;{r
z=cP>t*Ex2rVTwC0cjSfF@}#vh`X@A;^<LVxd*_0E2^}Rb^rP)-dP4s03n|;Sw_N7&
zsl_r!)*a6~>SrkWVY{~S#f{Nc^Xv701Xca>U-_=V<gMq*$%=a_r)N)5GGX?a)$`AN
zqqd>(U-iT^wVI0Q2aYozUMklXe*LMI&O%8G_TM7L`u>-eOP+8OWMUKDHCsfH(e9V7
z!nf`%>sw82uZJ%AQO}YSm2}#8`7NW~M)3`=jaPo;%sjO8($nv|Pl-%q*)aL@V&?Pl
zfttK&f7ACq(K43YA^GCflxg=HI$|%)VO#k{=exq>M!|v!fB&E2StNcreyiK8lGbX0
zXZytqX6((2+xJ;G^VsD#ue0wk+usY=!(q&LWzUT#OwA`*k0%~aR`XKhWL@+t(q;4Z
zr4yfCy1{+p|KTNvgzq?O%+v@yQ)Vv5$Py&Db#oE-w^@6A1cU<0H-0&sR{r?mp~|48
zx2H|;SiaZw$){gmOkbB<?NjGi)9~zrk&B|mVa|^J)BX+@gjn`X-~LZ!@9w}~->Nsg
zOq{mKXI8m#=H45o9?CN;&c#+{sC+ajz5P0CPx_vZi+r4zraiU~J@?s9Uc2_VnVE>#
zgjeC7lZ`J|<}p4uoV1?r=Ih?Yoh=WUJu{^1?)qrW*M56fD>vUqr(bSY@T+C>TlIIj
z1+KWAA0Jn?X7Brt>nD|SR$cz4{Ws<i&%B=I%_c7^(jS<c75wbK6mTrOsUepm(%fs;
zsuQLjf|>%Q$8su_qOF8XTOLY0z7=)qR;2w|Hx<V7dYhlVnYr!ENwGP3n#XV6ZZDc4
zGi83m^uleo#XO8HXZy}@dJw5?Tc_{7b#`oX%oU@m!(7`_KM7vw{GaojVRQ3_j58lT
zJ`eirS3P%Xxa3c^w1k@;;f(*46ebB@+pl_e<Ak0lrP_m~n*XLeSs^U9aP}u#vt`><
z&R;GF-o0hknM?BOYn1lSP|aAp-c)|qse3wyf}^XJ2$onrP0zG?ejxj%UGy18`FY7v
ztG|ERI$83CGN(b$!G*l+G4+a8FLum$S0-R(zLDqk54nnVj~iVYhuyF2J!rYm)_7+-
zOO8Q$5r41VLEmrkIZKXPlx>~t{$1E^cjUAkn=Rk4ISWrTIJWt+(cwZ52i51txa@k@
zJquo!XnW2lV_)CP_`i(Cr}}oRIb_=7b%}HHk0g%+!QTxTmR06X7B!x}Cn4==;=Wa3
zc8{gLwkqxnw_Gvv{Buj?H)r$q9Zk}S{K%0Ra%-KJdXd$;L-t)ZPFdey%7-S~xkjuj
S7iM5!VDNPHb6Mw<&;$T@R5i;0

literal 0
HcmV?d00001

diff --git a/assets/textures/Tile_Test_2.png b/assets/textures/Tile_Test_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..6193471ba9f044adff524fb9b3afa01ee664c806
GIT binary patch
literal 2079
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
FngB(@+Qa|=

literal 0
HcmV?d00001

diff --git a/assets/textures/Tile_Test_3.png b/assets/textures/Tile_Test_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b6bb5cbd73647990fa99bac0513a38665b877c3
GIT binary patch
literal 604
zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}jKx9jP7LeL$-HD>U|>mi
z^mSxl*x1kgCy|wbfq}EYBeIx*f$tCqGm2_>H83zRe)M#442f`mJJm3c$xy&m+;769
zqSLlcr>0DiQB+k`bziV#$r(Y7;Aaw=+n1c-?bv_)ehvRN))PT0Q`94Of1CBU{+RLU
zoXUuKyX{lt)}6Jeo&RUUlxwr4BY3#$Lk;hJo_XmA!{XDf85^r-OI$ed;Ze+zh~VZs
zm)~%#S#d7={Jizt@19ojWTal-@OzfT1Mb|7PanwrTlQ1Xz^T`0yW1>DhZL;^H!oDb
zxmYR8{L3lf`GPIa|65N;Nsy`E_3i~*<X)ff&DXvs?q$5laP+tDdwG>Kmy$dEuEMXc
zs@*BQ`)~(;xv)+^H1|J_Ju?!XFWBbZD!Oj^k%Kum_RX6t!aV!eoxp|(oLsdsc7H|p
zte^g`%V!1S?N!Cg?k<;ek`OqgaprN|8q007YuHL`)%lXdRW#csFkd{nnJ-(R+(p3o
zicDC{#h*D6Z7aE54m@7e%__;Iujq2#HsMdvZ>GPuQ}?><W8-kuKEG93&N$$t!y#VD
z3YK{0aQ%fAF5HnCoQp4Pxgk=*&EDxM5xnxzkr@}ZL`NiKIkAeaiSIiQ<gt@==7zUN
zEze$XcxP?6zsux|>8T~6Z|mB(i5@BC%evpWlDnZ>;NlOt^i_u~f19!R38Zb&y}F`z
z&IaqU->3gG`~I|77Tr5D;h9`f?yP^(Q5jyB<#vS2#7Mu`6(6c$?Dx9;TLl9H1B0il
KpUXO@geCwG!3CKB

literal 0
HcmV?d00001

diff --git a/source/engine/graphics/back/geometry/Geometry.hpp b/source/engine/graphics/back/geometry/Geometry.hpp
index c34f8fd..2ba0d91 100644
--- a/source/engine/graphics/back/geometry/Geometry.hpp
+++ b/source/engine/graphics/back/geometry/Geometry.hpp
@@ -59,7 +59,8 @@ namespace megu {
             const Vertices_t & vertices() const {return Static_Geometry<T, P>::Vertices();}
 
             static Layout_t Layout() {return Counter<megu::layout::Value>::Count<L...>();}
-            static const Vertices_t & Vertices() {return T::Vertices();}
+            static const Vertices_t & Vertices()  {return T::Vertices();}
+            static const size_t & Count() {return T::Count();}
     };
 
     template <class T, Primitive_t P, layout::Value ... L>
diff --git a/source/engine/graphics/back/shaders/Program.cpp b/source/engine/graphics/back/shaders/Program.cpp
index 71a3e77..a06d4f3 100644
--- a/source/engine/graphics/back/shaders/Program.cpp
+++ b/source/engine/graphics/back/shaders/Program.cpp
@@ -181,4 +181,15 @@ namespace megu {
     void Program::setUniform(const std::string & name, const std::set<std::reference_wrapper<const glm::mat4>> & value) const {
         glUniformMatrix4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), GL_FALSE, glm::value_ptr(value.begin()->get()));
     }
+
+    void Program::setUniform(const std::string & name, const void * data, size_t size, GLenum type) const {
+        switch (type) {
+            case GL_FLOAT:
+                glUniform4fv(this->_locations.at(name), static_cast<GLsizei>(size), static_cast<const float*>(data));
+                break;
+            
+            default:
+                break;
+        }
+    }
 }
\ No newline at end of file
diff --git a/source/engine/graphics/back/shaders/Program.hpp b/source/engine/graphics/back/shaders/Program.hpp
index cd005dd..42e0011 100644
--- a/source/engine/graphics/back/shaders/Program.hpp
+++ b/source/engine/graphics/back/shaders/Program.hpp
@@ -71,5 +71,7 @@ namespace megu {
 
             void setUniform(const std::string &, const std::vector<std::reference_wrapper<const glm::mat4>> &) const;
             void setUniform(const std::string &, const std::set<std::reference_wrapper<const glm::mat4>> &) const;
+
+            void setUniform(const std::string &, const void *, size_t, GLenum = GL_FLOAT) const;
     };
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/Engine.cpp b/source/engine/graphics/front/engine/Engine.cpp
index 46822d9..7551656 100644
--- a/source/engine/graphics/front/engine/Engine.cpp
+++ b/source/engine/graphics/front/engine/Engine.cpp
@@ -57,7 +57,6 @@ namespace megu {
         if(this->_window.isOpen()) {
             // Draw Layers
             TextureArray textures;
-            
             for(auto & [priority, layer] : this->_layers) {
                 if(!layer.get()->empty()) {
                     const glm::vec2 & dimension = layer->renderer().dimension();
@@ -73,4 +72,12 @@ namespace megu {
             this->_window.swapBuffers();
         }
     }
+
+    void GraphicEngine::setClearColor(float x, float y, float z) {
+        this->_renderer.setClearColor(x, y, z);
+        this->_group.setClearColor(x, y, z);
+        for(auto & [priority, layer] : this->_layers) {
+            layer.get()->renderer().setClearColor(x, y, z);
+        }
+    } 
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/Engine.hpp b/source/engine/graphics/front/engine/Engine.hpp
index b9a88bc..aa721f0 100644
--- a/source/engine/graphics/front/engine/Engine.hpp
+++ b/source/engine/graphics/front/engine/Engine.hpp
@@ -30,6 +30,7 @@ namespace megu {
             inline const std::map<Priority, std::unique_ptr<Layer>> & layers() const {return this->_layers;}
     
             void step();
+            void setClearColor(float, float, float);
 
         private:
             std::map<Priority, std::unique_ptr<Layer>> _layers;
diff --git a/source/engine/graphics/front/geometry/Plane.hpp b/source/engine/graphics/front/geometry/Plane.hpp
index 373e367..023e399 100644
--- a/source/engine/graphics/front/geometry/Plane.hpp
+++ b/source/engine/graphics/front/geometry/Plane.hpp
@@ -6,6 +6,7 @@ namespace megu {
     class Plane : public Static_Geometry<Plane, QUADS, layout::FLAT, layout::TEXTURE> {
         public:
             inline static const Vertices_t & Vertices() {return Plane::_Vertices;}
+            inline static const size_t & Count() {return 4;}
             
         private:
             static Vertices_t _Vertices;
diff --git a/source/engine/graphics/front/geometry/Quads.cpp b/source/engine/graphics/front/geometry/Quads.cpp
index fccb887..e4550c4 100644
--- a/source/engine/graphics/front/geometry/Quads.cpp
+++ b/source/engine/graphics/front/geometry/Quads.cpp
@@ -5,6 +5,6 @@ namespace megu {
         0.f,  0.f,    0.f, 0.f,
         1.f,  0.f,    1.f, 0.f,
         1.f,  1.f,    1.f, 1.f,
-        0.f,  1.f,    0.f, 1.f
-    };    
+        0.f,  1.f,    0.f, 1.f     
+    };
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/geometry/Quads.hpp b/source/engine/graphics/front/geometry/Quads.hpp
index 2e70bc6..f36888a 100644
--- a/source/engine/graphics/front/geometry/Quads.hpp
+++ b/source/engine/graphics/front/geometry/Quads.hpp
@@ -6,6 +6,7 @@ namespace megu {
     class Quads : public Static_Geometry<Quads, QUADS, layout::FLAT, layout::TEXTURE> {
         public:
             inline static const Vertices_t & Vertices() {return Quads::_Vertices;}
+            inline static const size_t & Count() {return 4;}
             
         private:
             static Vertices_t _Vertices;
diff --git a/source/engine/graphics/front/geometry/Vertex.hpp b/source/engine/graphics/front/geometry/Vertex.hpp
new file mode 100644
index 0000000..4c3eed9
--- /dev/null
+++ b/source/engine/graphics/front/geometry/Vertex.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <glm/glm.hpp>
+
+namespace megu {
+    struct Vertex {
+        glm::vec2 _position;
+        glm::vec2 _texture;
+    };
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/group/FrameBufferGroup.cpp b/source/engine/graphics/front/group/FrameBufferGroup.cpp
index 6653a7c..c9052ed 100644
--- a/source/engine/graphics/front/group/FrameBufferGroup.cpp
+++ b/source/engine/graphics/front/group/FrameBufferGroup.cpp
@@ -6,7 +6,7 @@
 
 namespace megu {
     FrameBufferGroup::FrameBufferGroup() 
-    : _vbo(this->_vao, Plane::Layout(), Plane::Vertices().size(), megu::EditMode::STATIC) {
+    : _vbo(this->_vao, Plane::Layout(), Plane::Vertices(), megu::EditMode::STATIC), _clear(0.f) {
         megu::Source vert("assets/shaders/FrameBuffer-Instanced.vert", Source::Categorie::VERTEX);
         this->_program.attach(vert);
 
@@ -15,8 +15,6 @@ namespace megu {
 
         this->_program.link();
 
-        this->_vbo << Plane::Vertices();
-
         vert.release();
         frag.release();
     }
@@ -33,6 +31,7 @@ namespace megu {
 
         this->_program.setUniform("uSampler", uSampler);
         this->_program.setUniform("uTexturesCount", static_cast<GLuint>(textures.size()));
+        this->_program.setUniform("uClearColor", this->_clear);
         glDrawArrays(Plane::Primitive(), 0, static_cast<GLsizei>(Plane::Vertices().size()));
     }
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/group/FrameBufferGroup.hpp b/source/engine/graphics/front/group/FrameBufferGroup.hpp
index c4ee336..40858d4 100644
--- a/source/engine/graphics/front/group/FrameBufferGroup.hpp
+++ b/source/engine/graphics/front/group/FrameBufferGroup.hpp
@@ -13,10 +13,12 @@ namespace megu {
            ~FrameBufferGroup() = default;
 
             virtual void draw(const Window &, const Camera &, const TextureArray &) const;
+            inline void setClearColor(float x, float y, float z) {this->_clear = {x, y, z};}
 
         private:
             VertexArray _vao;
             VerticeBuffer _vbo;
             Program _program;
+            glm::vec3 _clear;
     };
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/group/ImageGroup.cpp b/source/engine/graphics/front/group/ImageGroup.cpp
index 8730cb9..32db991 100644
--- a/source/engine/graphics/front/group/ImageGroup.cpp
+++ b/source/engine/graphics/front/group/ImageGroup.cpp
@@ -37,12 +37,16 @@ namespace megu {
         this->_vao.bind();
         this->_program.use();
 
+        this->_program.setUniform("uProj", camera.projection());
+        this->_program.setUniform("uView", camera.view());
+
         std::vector<std::reference_wrapper<const Texture>> textures;
 
         std::vector<glm::mat4> uModels;
         std::vector<GLint> uTextures;
 
-        static auto uSampler = array_generator<GLint, 32>().array;         
+        static auto uSampler = array_generator<GLint, 32>().array;
+        this->_program.setUniform("uSampler", uSampler);         
     
         for(auto & image : this->_images) {
             
@@ -53,9 +57,6 @@ namespace megu {
             }
             else {
                 if(textures.size() >= 8 || uModels.size() >= 124) {
-                    this->_program.setUniform("uProj", camera.projection());
-                    this->_program.setUniform("uView", camera.view());
-                    this->_program.setUniform("uSampler", uSampler);
                     this->_program.setUniform("uModel", uModels);
                     this->_program.setUniform("uTextures", uTextures);
 
@@ -74,11 +75,6 @@ namespace megu {
         }
 
         if(!textures.empty()) {
-            this->_program.setUniform("uProj", camera.projection());
-            this->_program.setUniform("uView", camera.view());
-            
-            
-            this->_program.setUniform("uSampler", uSampler);
             this->_program.setUniform("uModel", uModels);
             this->_program.setUniform("uTextures", uTextures);
 
diff --git a/source/engine/graphics/front/group/VertexArrayGroup.cpp b/source/engine/graphics/front/group/VertexArrayGroup.cpp
new file mode 100644
index 0000000..26c5bda
--- /dev/null
+++ b/source/engine/graphics/front/group/VertexArrayGroup.cpp
@@ -0,0 +1,42 @@
+#include "VertexArrayGroup.hpp"
+
+#include <engine/graphics/utility/array_generator.hpp>
+
+namespace megu {
+    VertexArrayGroup::VertexArrayGroup()
+    : _vbo(this->_vao, Quads::Layout(), Quads::Vertices(), megu::EditMode::STATIC) {
+        Source vert("assets/shaders/Grid-Instanced.vert", Source::Categorie::VERTEX);
+        this->_program.attach(vert);
+
+        Source frag("assets/shaders/Grid-Instanced.frag", Source::Categorie::FRAGMENT);
+        this->_program.attach(frag);
+
+        this->_program.link();
+
+        vert.release();
+        frag.release();
+    }
+
+    void VertexArrayGroup::add(const Texture & texture, const VerticesArray & grid) {
+        this->_objects[texture].push_back(grid);
+    }
+
+    void VertexArrayGroup::draw(const Window &, const Camera & camera, const TextureArray &) const {
+        this->_vao.bind();
+        this->_program.use();
+
+        this->_program.setUniform("uProj", camera.projection());
+        this->_program.setUniform("uView", camera.view());
+
+        for(const auto & [texture, grids] : this->_objects) {
+            texture.get().bind(0);
+            for(const auto & grid : grids) {
+                this->_program.setUniform("uModel", grid.get().transformation().model());
+                this->_program.setUniform("uSampler", 0);
+                this->_program.setUniform("uData", static_cast<const void *>(grid.get().vertices().data()), grid.get().size());
+
+                glDrawArraysInstanced(Quads::Primitive(), 0, static_cast<GLsizei>(this->_vbo.size()), static_cast<GLsizei>(grid.get().size()));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/group/VertexArrayGroup.hpp b/source/engine/graphics/front/group/VertexArrayGroup.hpp
new file mode 100644
index 0000000..65efa65
--- /dev/null
+++ b/source/engine/graphics/front/group/VertexArrayGroup.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "DrawGroup.hpp"
+
+#include <map>
+#include <optional>
+
+#include <engine/graphics/back/textures/Texture.hpp>
+#include <engine/graphics/back/buffers/VertexArray.hpp>
+#include <engine/graphics/back/buffers/VerticeBuffer.hpp>
+#include <engine/graphics/back/shaders/Program.hpp>
+
+#include <engine/graphics/front/object/VerticesArray.hpp>
+
+#include <engine/graphics/utility/texture_comparator.hpp>
+
+namespace megu {
+    class VertexArrayGroup : public DrawGroup {
+        public:
+            VertexArrayGroup();
+           ~VertexArrayGroup() = default;
+            
+            void add(const Texture &, const VerticesArray &);
+            void draw(const Window &, const Camera &, const TextureArray &) const override;
+
+        private:
+            std::map<std::reference_wrapper<const Texture>, std::vector<std::reference_wrapper<const VerticesArray>>, texture_comparator> _objects;
+
+            VertexArray _vao;
+            VerticeBuffer _vbo;
+            Program _program;
+    };
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/object/VerticesArray.cpp b/source/engine/graphics/front/object/VerticesArray.cpp
new file mode 100644
index 0000000..3a576ed
--- /dev/null
+++ b/source/engine/graphics/front/object/VerticesArray.cpp
@@ -0,0 +1,20 @@
+#include "VerticesArray.hpp"
+
+namespace megu {
+    VerticesArray::VerticesArray(Primitive_t primitive, size_t size)
+    : _primitive(primitive), _vertices(size) {}
+
+    VerticesArray::VerticesArray(const VerticesArray & src)
+    : _transformation(src._transformation), _primitive(src._primitive), _vertices(src._vertices) {}
+
+    VerticesArray VerticesArray::operator=(const VerticesArray & src) {
+        this->_transformation = src._transformation;
+        this->_primitive = src._primitive;
+        this->_vertices = src._vertices;
+        return *this;
+    }
+
+    void VerticesArray::append(const Vertex & vertex) {
+        this->_vertices.push_back(vertex);
+    }
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/object/VerticesArray.hpp b/source/engine/graphics/front/object/VerticesArray.hpp
new file mode 100644
index 0000000..bbceaa9
--- /dev/null
+++ b/source/engine/graphics/front/object/VerticesArray.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <array>
+
+#include <engine/graphics/back/geometry/Transformable.hpp>
+#include <engine/graphics/back/textures/Texture.hpp> 
+
+#include <engine/graphics/front/geometry/Quads.hpp>
+#include <engine/graphics/front/geometry/Vertex.hpp>
+
+namespace megu {
+    class VerticesArray {
+        public:
+            VerticesArray(Primitive_t, size_t);
+            VerticesArray(const VerticesArray &);
+            VerticesArray operator=(const VerticesArray &);
+            ~VerticesArray() = default;
+
+            inline size_t size() const {return this->_vertices.size();}
+
+            void scale(float x, float y) {this->_transformation.scale(x, y);}
+
+            void append(const Vertex &);
+
+            const Transformable & transformation() const {return this->_transformation;}
+            const Primitive_t & primitive() const {return this->_primitive;}
+            const std::vector<Vertex> & vertices() const {return this->_vertices;}
+            
+            Vertex & operator[](size_t index) {return this->_vertices[index];}
+            const Vertex & operator[](size_t index) const {return this->_vertices[index];}
+
+        private:
+            Transformable _transformation;
+            Primitive_t _primitive;
+            std::vector<Vertex> _vertices;
+    };
+}
\ No newline at end of file
diff --git a/source/engine/graphics/utility/texture_comparator.hpp b/source/engine/graphics/utility/texture_comparator.hpp
new file mode 100644
index 0000000..cdb9f9a
--- /dev/null
+++ b/source/engine/graphics/utility/texture_comparator.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <engine/graphics/back/textures/Texture.hpp>
+
+namespace megu {
+    struct texture_comparator {
+        bool operator()(const Texture & t1, const Texture & t2) const {
+            return t1.identifier() > t2.identifier();
+        }
+    };
+}
\ No newline at end of file
diff --git a/source/main.cpp b/source/main.cpp
index c4abc5e..67c44ff 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -16,6 +16,7 @@
 #include <engine/graphics/front/group/ImageGroup.hpp>
 #include <engine/graphics/front/engine/Renderer.hpp>
 #include <engine/graphics/front/engine/Engine.hpp>
+#include <engine/graphics/front/group/VertexArrayGroup.hpp>
 #include <engine/graphics/errors.hpp>
 
 const float i_x =  1.f;
@@ -30,6 +31,12 @@ glm::vec2 to_screen_coordinate(const glm::vec2 & tile, float w, float h, float l
     };
 }
 
+megu::Vertex to_screen_coordinate(int x, int y, unsigned int u, unsigned int v, const megu::Texture & texture) {
+    return {{x, y}, {static_cast<float>(u) / static_cast<float>(texture.width()), static_cast<float>(v) / static_cast<float>(texture.height())}};
+}
+
+//* Isometric : 
+/*
 int main(int argc, const char * argv[]) {
     try {
         //? Window
@@ -201,4 +208,89 @@ int main(int argc, const char * argv[]) {
     }
 
     return EXIT_SUCCESS;
-}
\ No newline at end of file
+}
+*/
+
+int main(int argc, const char * argv[]) {
+    try {
+        //? Window
+        megu::Window window;
+        window.open("Isometric Window", 360, 360);
+        megu::error::opengl_error::check();
+
+        std::cout << "Window Inited" << std::endl;
+
+        //? Group
+        megu::VertexArrayGroup group;
+       
+        std::cout << "Group Inited" << std::endl;
+
+        //? Grids
+
+        megu::Texture texture_1;
+        texture_1.store(megu::TextureBuffer("assets/textures/Tile_Test_3.png"));
+
+        megu::VerticesArray grid_1(megu::Quads::Primitive(), 4);
+
+        /*grid_1[0] = {{0.f,  0.f},  {0.0f,  0.0f}};
+        grid_1[1] = {{16.f, 0.f},  {0.5f,  0.0f}};
+        grid_1[2] = {{16.f, 16.f}, {0.5f,  0.5f}};
+        grid_1[3] = {{0.f,  16.f}, {0.0f,  0.5f}};*/
+
+     
+
+        grid_1[0] = to_screen_coordinate(0,  0,  0,  0,  texture_1);
+        grid_1[1] = to_screen_coordinate(16, 0,  16, 0,  texture_1);
+        grid_1[2] = to_screen_coordinate(16, 16, 16, 16, texture_1);
+        grid_1[3] = to_screen_coordinate(0,  16, 0,  16, texture_1);
+
+
+        grid_1.scale(1.f, 1.f);
+
+        
+
+        group.add(texture_1, grid_1);
+
+        std::cout << "Grid created" << std::endl;
+
+        //? ImGui
+        //ImGui::CreateContext();
+        //ImGui_ImplOpenGL3_Init();
+        //ImGui_ImplGlfw_InitForOpenGL(window.ptr(), true);
+
+        //? Engines
+        megu::GraphicEngine engine(window);
+        megu::Renderer basic_renderer(100, 100);
+
+        engine.push(0, basic_renderer);
+        engine.push(0, 0, group);
+
+        //? Render Loop
+        std::cout << "Render Loop Begin !" << std::endl;
+
+        double previousTime = megu::Window::Time();
+        int frameCount = 0;
+
+        while(window.isOpen()) {
+            double currentTime = megu::Window::Time();
+            frameCount++;
+
+            if(currentTime - previousTime >= 1.0) {
+                window.setTitle(std::to_string(frameCount));
+
+                frameCount = 0;
+                previousTime = currentTime;
+            }
+
+            window.pollEvents();
+            engine.step();
+        }
+        std::cout << "Render Loop End !" << std::endl;
+    }
+    catch(std::exception & error) {
+        std::cerr << error.what() << std::endl;
+    }
+
+    return EXIT_SUCCESS;
+}
+
-- 
GitLab