From b3f711b12e85b6fb297888819b5aff6a756fff12 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9au?= <theau.baton@etu.univ-amu.fr>
Date: Mon, 28 Oct 2024 03:03:37 +0100
Subject: [PATCH] Add per layer rendering

---
 assets/shaders/Framebuffer-Instanced.frag     | 28 +++++++++
 assets/shaders/Framebuffer-Instanced.vert     | 10 ++++
 .../graphics/back/buffers/FrameBuffer.cpp     |  1 +
 .../engine/graphics/front/engine/Engine.cpp   | 30 +++++++---
 .../engine/graphics/front/engine/Engine.hpp   | 15 ++---
 .../front/engine/FrameBufferGroup.cpp         | 57 -------------------
 source/engine/graphics/front/engine/Layer.cpp | 28 +++++++++
 source/engine/graphics/front/engine/Layer.hpp | 26 +++++++++
 .../engine/graphics/front/engine/Priority.hpp | 13 +++++
 .../engine/graphics/front/engine/Renderer.cpp |  4 +-
 .../engine/graphics/front/engine/Renderer.hpp |  6 +-
 .../graphics/front/engine/TextureArray.hpp    |  2 +-
 .../engine/graphics/front/geometry/Plane.cpp  | 10 ++++
 .../engine/graphics/front/geometry/Plane.hpp  | 13 +++++
 .../engine/graphics/front/group/DrawGroup.hpp |  8 ---
 .../graphics/front/group/FrameBufferGroup.cpp | 37 ++++++++++++
 .../{engine => group}/FrameBufferGroup.hpp    |  1 -
 source/main.cpp                               | 19 ++++---
 18 files changed, 212 insertions(+), 96 deletions(-)
 create mode 100644 assets/shaders/Framebuffer-Instanced.frag
 create mode 100644 assets/shaders/Framebuffer-Instanced.vert
 delete mode 100644 source/engine/graphics/front/engine/FrameBufferGroup.cpp
 create mode 100644 source/engine/graphics/front/engine/Layer.cpp
 create mode 100644 source/engine/graphics/front/engine/Layer.hpp
 create mode 100644 source/engine/graphics/front/engine/Priority.hpp
 create mode 100644 source/engine/graphics/front/geometry/Plane.cpp
 create mode 100644 source/engine/graphics/front/geometry/Plane.hpp
 create mode 100644 source/engine/graphics/front/group/FrameBufferGroup.cpp
 rename source/engine/graphics/front/{engine => group}/FrameBufferGroup.hpp (92%)

diff --git a/assets/shaders/Framebuffer-Instanced.frag b/assets/shaders/Framebuffer-Instanced.frag
new file mode 100644
index 0000000..2db481d
--- /dev/null
+++ b/assets/shaders/Framebuffer-Instanced.frag
@@ -0,0 +1,28 @@
+#version 450 core
+out vec4 FragColor;
+
+in flat int Id;
+in vec2 Texture;
+
+uniform sampler2D uSampler[32];
+uniform uint uTexturesCount;
+
+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) {
+            color.r = tcolor.r;
+        }
+
+        if(tcolor.g != 0.0) {
+            color.g = tcolor.g;
+        }
+
+        if(tcolor.b != 0.0) {
+            color.b = tcolor.b;
+        }
+    }
+
+    FragColor = color;
+}
\ No newline at end of file
diff --git a/assets/shaders/Framebuffer-Instanced.vert b/assets/shaders/Framebuffer-Instanced.vert
new file mode 100644
index 0000000..2cf6623
--- /dev/null
+++ b/assets/shaders/Framebuffer-Instanced.vert
@@ -0,0 +1,10 @@
+#version 450 core
+layout (location = 0) in vec2 aPos;
+layout (location = 1) in vec2 aTex;
+
+out vec2 Texture;
+
+void main() {
+    Texture = aTex;
+    gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/source/engine/graphics/back/buffers/FrameBuffer.cpp b/source/engine/graphics/back/buffers/FrameBuffer.cpp
index e2f8234..c846b69 100644
--- a/source/engine/graphics/back/buffers/FrameBuffer.cpp
+++ b/source/engine/graphics/back/buffers/FrameBuffer.cpp
@@ -13,6 +13,7 @@ namespace megu {
         this->_texture.setWraping(Texture::Wraping::CLAMP_TO_EDGE, Texture::Axis::S | Texture::Axis::T);
 
         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->_texture.identifier(), 0);
+
         glGenRenderbuffers(1, &this->_rbo_id);
         glBindRenderbuffer(GL_RENDERBUFFER, this->_rbo_id);
         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
diff --git a/source/engine/graphics/front/engine/Engine.cpp b/source/engine/graphics/front/engine/Engine.cpp
index ff97032..6c78b0c 100644
--- a/source/engine/graphics/front/engine/Engine.cpp
+++ b/source/engine/graphics/front/engine/Engine.cpp
@@ -1,22 +1,34 @@
 #include "Engine.hpp"
 
+#define NORMALIZE(X) X/255.f
+
 namespace megu {
-    GraphicEngine::GraphicEngine(Window & window,float w, float h) 
-    : _renderer(w, h), _window(window) {
+    GraphicEngine::GraphicEngine(Window & window) 
+    : _window(window), _renderer(window.width(), window.height()) {
         glViewport(0, 0, window.width(), window.height());
-        this->_renderer.setClearColor(0.f, 0.f, 0.f);
+        this->_renderer.setClearColor(NORMALIZE(135.f), NORMALIZE(170.f), NORMALIZE(255.f));
     } 
 
-    void GraphicEngine::push(DrawGroup & group, Priority priority) {
-        this->_objects[priority] = &group;
+    void GraphicEngine::push(Priority priority, const Renderer & renderer) {
+        this->_layers[priority] = std::make_unique<Layer>(renderer);
+    }
+
+    void GraphicEngine::push(Priority layer_priority, Priority draw_priority, const DrawGroup & group) {
+        this->_layers[layer_priority]->push(draw_priority, group);
     }
 
     void GraphicEngine::step() {
-        if(this->_window.isOpen() && !this->_objects.empty()) {
-            this->_renderer.clear();
-            for(auto & [priority, groups] : this->_objects) {
-                this->_renderer.render(this->_window, *groups, {});
+        if(this->_window.isOpen()) {
+            // Draw Layers
+            TextureArray textures;
+            for(auto & [priority, layer] : this->_layers) {
+                textures.push_back(layer->draw(this->_window, textures));
             }
+
+            // Merge Textures
+            FrameBuffer::BindDefaultFrameBuffer();
+            this->_renderer.clear();
+            this->_renderer.render(this->_window, this->_group, textures);
             this->_window.swapBuffers();
         }
     }
diff --git a/source/engine/graphics/front/engine/Engine.hpp b/source/engine/graphics/front/engine/Engine.hpp
index 144bbdb..116b7de 100644
--- a/source/engine/graphics/front/engine/Engine.hpp
+++ b/source/engine/graphics/front/engine/Engine.hpp
@@ -2,26 +2,27 @@
 
 #include <map>
 #include <engine/graphics/front/group/DrawGroup.hpp>
+#include <engine/graphics/front/group/FrameBufferGroup.hpp>
 
 #include "Renderer.hpp"
-#include "FrameBufferGroup.hpp"
+#include "Layer.hpp"
 
 namespace megu {
     class GraphicEngine {
         public:
             GraphicEngine() = delete;
-            GraphicEngine(Window &, float, float);
+            GraphicEngine(Window &);
            ~GraphicEngine() = default;
 
-            void push(DrawGroup &, Priority);
-
+            void push(Priority, const Renderer &);
+            void push(Priority, Priority, const DrawGroup &);
+    
             void step();
 
-            Renderer & tmp_renderer() {return this->_renderer;}
-
         private:
+            std::map<Priority, std::unique_ptr<Layer>> _layers;
             Renderer _renderer;
-            std::map<Priority, DrawGroup *> _objects;
+            FrameBufferGroup _group;
             Window & _window;
 
     };
diff --git a/source/engine/graphics/front/engine/FrameBufferGroup.cpp b/source/engine/graphics/front/engine/FrameBufferGroup.cpp
deleted file mode 100644
index 34835f6..0000000
--- a/source/engine/graphics/front/engine/FrameBufferGroup.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "FrameBufferGroup.hpp"
-
-#include <glm/gtc/matrix_transform.hpp>
-
-namespace megu {
-    FrameBufferGroup::FrameBufferGroup() 
-    : _vbo(this->_vao, Quads::Layout(), Quads::Vertices(), EditMode::STATIC) {
-        megu::Source vert("assets/shaders/FrameBuffer-Instanced.vert", Source::Categorie::VERTEX);
-        this->_program.attach(vert);
-
-        megu::Source frag("assets/shaders/FrameBuffer-Instanced.frag", Source::Categorie::FRAGMENT);
-        this->_program.attach(frag);
-
-        this->_program.link();
-
-        vert.release();
-        frag.release();
-    }
-
-    void FrameBufferGroup::draw(const Window & window, const Camera & camera, const TextureArray & textures) const {
-        if(window.isOpen()) {
-            std::vector<glm::mat4> uModels;
-            std::vector<GLint> uTextures;
-
-            this->_vao.bind();
-
-            size_t i = 1;
-            GLint slotsCount = Texture::CountSlots();
-            for(auto & texture : textures) {
-                if(i % slotsCount == 0) {
-                    this->_program.use();
-
-                    this->_program.setUniform("uModels", uModels);
-                    this->_program.setUniform("uTextures", uTextures);
-
-                    glDrawArraysInstanced(Quads::Primitive(), 0, static_cast<GLsizei>(Quads::Vertices().size()),  static_cast<GLsizei>(i));
-                    uModels.clear();
-                    uModels.clear();
-                }
-
-                texture.get().bind(i-1 % slotsCount);
-
-                uTextures.push_back(i-1);
-                uModels.push_back(glm::translate(glm::mat4(1), glm::vec3(0.f, 0.f, static_cast<float>(i))));
-            }
-
-            if(uModels.empty()) {
-                this->_program.use();
-
-                this->_program.setUniform("uModels", uModels);
-                this->_program.setUniform("uTextures", uTextures);
-
-                glDrawArraysInstanced(Quads::Primitive(), 0, static_cast<GLsizei>(Quads::Vertices().size()),  static_cast<GLsizei>(i));
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/Layer.cpp b/source/engine/graphics/front/engine/Layer.cpp
new file mode 100644
index 0000000..762f10a
--- /dev/null
+++ b/source/engine/graphics/front/engine/Layer.cpp
@@ -0,0 +1,28 @@
+#include "Layer.hpp"
+
+#include <iostream>
+
+namespace megu {
+    Layer::Layer(const Renderer & renderer) 
+    : _renderer(renderer), 
+      _frameBuffer(static_cast<GLuint>(renderer.dimension().x), static_cast<GLuint>(renderer.dimension().y)) {}
+
+    void Layer::push(Priority priority, const DrawGroup & group) {
+        this->_objects[priority] = &group;
+    }
+
+    const Texture & Layer::draw(const Window & window, const TextureArray & textures) const {
+        if(this->_frameBuffer.usable()) {
+            this->_renderer.setClearColor(0.f, 0.f, 0.f, 0.f);
+            this->_renderer.clear();
+            this->_frameBuffer.bind();
+
+            for(auto &[priority, group] : this->_objects) {
+                this->_renderer.render(window, *group, textures);
+            }
+        }
+        
+        return this->_frameBuffer.texture();
+    }
+
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/Layer.hpp b/source/engine/graphics/front/engine/Layer.hpp
new file mode 100644
index 0000000..8c9eb22
--- /dev/null
+++ b/source/engine/graphics/front/engine/Layer.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <map>
+#include <engine/graphics/back/buffers/FrameBuffer.hpp>
+#include <engine/graphics/front/group/DrawGroup.hpp>
+
+#include "Priority.hpp" 
+#include "Renderer.hpp"
+
+namespace megu {
+    class Layer {
+        public:
+            Layer() = delete;
+            Layer(const Renderer &);
+           ~Layer() = default;
+
+            void push(Priority, const DrawGroup &); 
+
+            virtual const Texture & draw(const Window &, const TextureArray &) const;
+
+        private:
+            const Renderer & _renderer;
+            FrameBuffer _frameBuffer;
+            std::map<Priority, DrawGroup const*> _objects;
+    };
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/Priority.hpp b/source/engine/graphics/front/engine/Priority.hpp
new file mode 100644
index 0000000..e331840
--- /dev/null
+++ b/source/engine/graphics/front/engine/Priority.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <stddef.h>
+
+namespace megu {
+    using Priority = size_t;
+    
+    struct priority_sorter {
+        bool operator()(const Priority & p1, const Priority & p2) {
+            return p1 != p2 ? p1 > p2 : &p1 > &p2;
+        }
+    };
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/Renderer.cpp b/source/engine/graphics/front/engine/Renderer.cpp
index 0566339..3b97d5a 100644
--- a/source/engine/graphics/front/engine/Renderer.cpp
+++ b/source/engine/graphics/front/engine/Renderer.cpp
@@ -11,11 +11,11 @@ namespace megu {
         group.draw(window, this->_view, textures);
     }
 
-    void Renderer::clear() {
+    void Renderer::clear() const {
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     }
 
-    void Renderer::setClearColor(float r, float g, float b, float a) {
+    void Renderer::setClearColor(float r, float g, float b, float a) const {
         glClearColor(r, g, b, a);
     }
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/Renderer.hpp b/source/engine/graphics/front/engine/Renderer.hpp
index a99b6ec..9157f4c 100644
--- a/source/engine/graphics/front/engine/Renderer.hpp
+++ b/source/engine/graphics/front/engine/Renderer.hpp
@@ -17,8 +17,10 @@ namespace megu {
             
             virtual void render(const Window &, const DrawGroup &, const TextureArray &) const;
 
-            void clear();
-            void setClearColor(float, float, float, float = 1.f);
+            const glm::vec2 dimension() const {return this->_view.dimension();}
+
+            void clear() const;
+            void setClearColor(float, float, float, float = 1.f) const;
 
         private:
             View _view;
diff --git a/source/engine/graphics/front/engine/TextureArray.hpp b/source/engine/graphics/front/engine/TextureArray.hpp
index 174955e..d5106a4 100644
--- a/source/engine/graphics/front/engine/TextureArray.hpp
+++ b/source/engine/graphics/front/engine/TextureArray.hpp
@@ -4,5 +4,5 @@
 #include <engine/graphics/back/textures/Texture.hpp>
 
 namespace megu {
-    using TextureArray = std::set<std::reference_wrapper<const Texture>>;
+    using TextureArray = std::vector<std::reference_wrapper<const Texture>>;
 }
\ No newline at end of file
diff --git a/source/engine/graphics/front/geometry/Plane.cpp b/source/engine/graphics/front/geometry/Plane.cpp
new file mode 100644
index 0000000..e7ef70a
--- /dev/null
+++ b/source/engine/graphics/front/geometry/Plane.cpp
@@ -0,0 +1,10 @@
+#include "Plane.hpp"
+
+namespace megu {
+    Vertices_t Plane::_Vertices = {
+        -1.f,  -1.f,    0.f, 0.f,
+         1.f,  -1.f,    1.f, 0.f,
+         1.f,   1.f,    1.f, 1.f,
+        -1.f,   1.f,    0.f, 1.f
+    };    
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/geometry/Plane.hpp b/source/engine/graphics/front/geometry/Plane.hpp
new file mode 100644
index 0000000..373e367
--- /dev/null
+++ b/source/engine/graphics/front/geometry/Plane.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <engine/graphics/back/geometry/Geometry.hpp>
+
+namespace megu {
+    class Plane : public Static_Geometry<Plane, QUADS, layout::FLAT, layout::TEXTURE> {
+        public:
+            inline static const Vertices_t & Vertices() {return Plane::_Vertices;}
+            
+        private:
+            static Vertices_t _Vertices;
+    };
+}
diff --git a/source/engine/graphics/front/group/DrawGroup.hpp b/source/engine/graphics/front/group/DrawGroup.hpp
index f32eaf9..f2d8ca3 100644
--- a/source/engine/graphics/front/group/DrawGroup.hpp
+++ b/source/engine/graphics/front/group/DrawGroup.hpp
@@ -5,14 +5,6 @@
 #include <engine/io/Window.hpp>
 
 namespace megu {
-    using Priority = size_t;
-    
-    struct priority_sorter {
-        bool operator()(const Priority & p1, const Priority & p2) {
-            return p1 != p2 ? p1 > p2 : &p1 > &p2;
-        }
-    };
-
     class DrawGroup {
         public:
             virtual void draw(const Window &, const Camera &, const TextureArray &) const = 0;
diff --git a/source/engine/graphics/front/group/FrameBufferGroup.cpp b/source/engine/graphics/front/group/FrameBufferGroup.cpp
new file mode 100644
index 0000000..730ab99
--- /dev/null
+++ b/source/engine/graphics/front/group/FrameBufferGroup.cpp
@@ -0,0 +1,37 @@
+#include "FrameBufferGroup.hpp"
+
+#include <glm/gtc/matrix_transform.hpp>
+#include <engine/graphics/front/geometry/Plane.hpp>
+
+namespace megu {
+    FrameBufferGroup::FrameBufferGroup() 
+    : _vbo(this->_vao, Plane::Layout(), Plane::Vertices().size()) {
+        megu::Source vert("assets/shaders/FrameBuffer-Instanced.vert", Source::Categorie::VERTEX);
+        this->_program.attach(vert);
+
+        megu::Source frag("assets/shaders/FrameBuffer-Instanced.frag", Source::Categorie::FRAGMENT);
+        this->_program.attach(frag);
+
+        this->_program.link();
+
+        this->_vbo << Plane::Vertices();
+
+        vert.release();
+        frag.release();
+    }
+
+    void FrameBufferGroup::draw(const Window & window, const Camera & camera, const TextureArray & textures) const {
+        if(window.isOpen()) {
+            this->_program.use();
+            this->_vao.bind();
+
+            for(GLuint i = 0; i < static_cast<GLuint>(textures.size()); ++i) {
+                textures[i].get().bind(static_cast<GLuint>(i));
+            }   
+
+            this->_program.setUniform("uSampler", std::vector<GLint>{0, 1, 2, 3, 4, 5, 6 , 7, 8, 9, 10});
+            this->_program.setUniform("uTexturesCount", static_cast<GLuint>(textures.size()));
+            glDrawArrays(Plane::Primitive(), 0, static_cast<GLsizei>(Plane::Vertices().size()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/source/engine/graphics/front/engine/FrameBufferGroup.hpp b/source/engine/graphics/front/group/FrameBufferGroup.hpp
similarity index 92%
rename from source/engine/graphics/front/engine/FrameBufferGroup.hpp
rename to source/engine/graphics/front/group/FrameBufferGroup.hpp
index 94659e3..c4ee336 100644
--- a/source/engine/graphics/front/engine/FrameBufferGroup.hpp
+++ b/source/engine/graphics/front/group/FrameBufferGroup.hpp
@@ -4,7 +4,6 @@
 #include <engine/graphics/back/buffers/VerticeBuffer.hpp>
 #include <engine/graphics/back/shaders/Program.hpp>
 
-#include <engine/graphics/front/geometry/Quads.hpp>
 #include <engine/graphics/front/group/DrawGroup.hpp>
 
 namespace megu {
diff --git a/source/main.cpp b/source/main.cpp
index ea1e694..584217f 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -18,8 +18,6 @@
 #include <engine/graphics/front/engine/Engine.hpp>
 #include <engine/graphics/errors.hpp>
 
-#define NORMALIZE(X) X/255.f
-
 const float i_x =  1.f;
 const float i_y =  0.5f;
 const float j_x = -1.f;
@@ -83,7 +81,7 @@ int main(int argc, const char * argv[]) {
                 images.push_back(std::make_unique<megu::Image>(id == 1 ? texture_1 : texture_2));
                 glm::vec2 pos = to_screen_coordinate({x, y}, 32.f, 32.f, 1.f);
 
-                images.back()->setPosition({pos.x + 160, pos.y});
+                images.back()->setPosition({pos.x + 25, pos.y});
             }
             
             ++x;
@@ -129,7 +127,7 @@ int main(int argc, const char * argv[]) {
                 images_2.push_back(std::make_unique<megu::Image>(texture_3));
                 glm::vec2 pos = to_screen_coordinate({x_2, y_2}, 32.f, 32.f);
 
-                images_2.back()->setPosition({pos.x + 160, pos.y});
+                images_2.back()->setPosition({pos.x + 25, pos.y});
             }
             
             ++x_2;
@@ -148,16 +146,19 @@ int main(int argc, const char * argv[]) {
         ImGui_ImplGlfw_InitForOpenGL(window.ptr(), true);
 
         //? Engines
-        megu::GraphicEngine engine(window, 320, 320);
-        engine.tmp_renderer().setClearColor(NORMALIZE(135), NORMALIZE(150), NORMALIZE(255));
+        megu::GraphicEngine engine(window);
+        megu::Renderer basic_renderer(320, 320);
+
+        engine.push(0, basic_renderer);
+        engine.push(1, basic_renderer);
+
+        engine.push(1, 0, group);
+        engine.push(0, 0, group_2);
 
         //? Render Loop
         std::cout << "Render Loop Begin !" << std::endl;
         glm::vec2 xy = {0, 0};
 
-        engine.push(group, 1);
-        engine.push(group_2, 0);
-
         double previousTime = megu::Window::Time();
         int frameCount = 0;
 
-- 
GitLab