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