diff --git a/assets/scene/scene1.json b/assets/scene/scene1.json index 6a57417..e7016b2 100644 --- a/assets/scene/scene1.json +++ b/assets/scene/scene1.json @@ -44,7 +44,7 @@ "id": { "id": 97897897 }, "tag": { "tag": "Quad 2" }, "transform" : { - "translate": [ 1.1, 0.0, 0.0 ], + "translate": [ 2.5, 0.0, 0.0 ], "rotate": [ 0.0, 0.0, 0.0 ], "scale": [ 1.0, 1.0, 1.0 ] }, @@ -57,7 +57,7 @@ "id": { "id": 3424242 }, "tag": { "tag": "Quad 3" }, "transform" : { - "translate": [ 2.2, 1.0, 0.0 ], + "translate": [ 5.0, 1.0, 0.0 ], "rotate": [ 0.0, 0.0, -20.0 ], "scale": [ 1.0, 1.0, 1.0 ] }, @@ -70,7 +70,7 @@ "id": { "id": 4345472 }, "tag": { "tag": "Quad 4" }, "transform" : { - "translate": [ 0.85, 0.0, 0.0 ], + "translate": [ 1.7, 0.0, 0.0 ], "rotate": [ 0.0, 0.0, 0.0 ], "scale": [ 0.5, 0.5, 1.0 ] }, @@ -83,7 +83,7 @@ "id": { "id": 5234723 }, "tag": { "tag": "Quad 5" }, "transform" : { - "translate": [ 1.0, 0.0, 0.0 ], + "translate": [ 2.0, 0.0, 0.0 ], "rotate": [ 0.0, 0.0, -20.0 ], "scale": [ 0.5, 0.5, 1.0 ] }, diff --git a/src/inferno/application.cpp b/src/inferno/application.cpp index cea36fe..70b68af 100644 --- a/src/inferno/application.cpp +++ b/src/inferno/application.cpp @@ -6,11 +6,13 @@ #include // std::pair +#include "glm/ext/vector_float3.hpp" #include "glm/gtc/type_ptr.hpp" // glm::make_mat4 #include "ruc/format/log.h" #include "ruc/meta/assert.h" #include "inferno/application.h" +#include "inferno/component/transformcomponent.h" #include "inferno/core.h" #include "inferno/event/applicationevent.h" #include "inferno/event/event.h" @@ -20,6 +22,7 @@ #include "inferno/keycodes.h" #include "inferno/render/buffer.h" #include "inferno/render/context.h" +#include "inferno/render/framebuffer.h" // #include "inferno/render/gltf.h" #include "inferno/asset/shader.h" #include "inferno/asset/texture.h" @@ -50,6 +53,11 @@ Application::Application() Input::initialize(); RenderCommand::initialize(); + m_framebuffer = std::make_unique( + Framebuffer::Properties { .type = Framebuffer::Type::Color | Framebuffer::Type::Depth | Framebuffer::Type::Stencil, + .width = m_window->getWidth(), + .height = m_window->getHeight() }); + m_scene = std::make_shared(); m_scene->initialize(); @@ -141,6 +149,10 @@ int Application::run() // offset #endif + constexpr glm::vec4 vectorOne { 1.0f, 1.0f, 1.0f, 1.0f }; + constexpr glm::mat4 matIdentity { 1.0f }; + constexpr TransformComponent transformIdentity; + // m_window->setVSync(false); while (!m_window->shouldClose()) { @@ -149,6 +161,7 @@ int Application::run() m_lastFrameTime = time; // ruc::debug("Frametime {}ms", deltaTime * 1000); + // --------------------------------- // Update update(); @@ -157,12 +170,15 @@ int Application::run() m_window->update(); m_scene->update(deltaTime); + // --------------------------------- // Render + m_framebuffer->bind(); + render(); RenderCommand::clearColor({ 0.2f, 0.3f, 0.3f, 1.0f }); - RenderCommand::clear(); + RenderCommand::clearColorDepthBit(); std::pair projectionView = m_scene->cameraProjectionView(); RendererCubemap::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment @@ -178,6 +194,20 @@ int Application::run() Renderer2D::the().endScene(); RendererFont::the().endScene(); + m_framebuffer->unbind(); + + // --------------------------------- + // Framebuffer + + RenderCommand::clearColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + RenderCommand::clearColorBit(); + + Renderer2D::the().setEnableDepthBuffer(false); + Renderer2D::the().beginScene(matIdentity, matIdentity); + Renderer2D::the().drawQuad(transformIdentity, vectorOne, m_framebuffer->texture(0)); + Renderer2D::the().endScene(); + Renderer2D::the().setEnableDepthBuffer(true); + m_window->render(); } @@ -212,6 +242,7 @@ bool Application::onWindowResize(WindowResizeEvent& e) ruc::info("WindowResizeEvent {}x{}", e.getWidth(), e.getHeight()); RenderCommand::setViewport(0, 0, e.getWidth(), e.getHeight()); + m_framebuffer->setSize(e.getWidth(), e.getHeight()); return true; } diff --git a/src/inferno/application.h b/src/inferno/application.h index 489f2e7..7ef5250 100644 --- a/src/inferno/application.h +++ b/src/inferno/application.h @@ -12,12 +12,14 @@ namespace Inferno { class Event; class Font; +class Framebuffer; class KeyPressEvent; class MousePositionEvent; class Scene; class Window; class WindowCloseEvent; class WindowResizeEvent; +struct TransformComponent; class Application { public: @@ -50,6 +52,7 @@ private: std::unique_ptr m_window; std::shared_ptr m_scene; + std::unique_ptr m_framebuffer; // std::shared_ptr m_font; diff --git a/src/inferno/asset/asset-manager.cpp b/src/inferno/asset/asset-manager.cpp index a9a462a..6dc25fc 100644 --- a/src/inferno/asset/asset-manager.cpp +++ b/src/inferno/asset/asset-manager.cpp @@ -38,18 +38,22 @@ bool AssetManager::exists(std::string_view path) return m_assetList.find(path.data()) != m_assetList.end(); } -void AssetManager::remove(std::string_view path) +std::nullptr_t AssetManager::remove(std::string_view path) { if (exists(path)) { m_assetList.erase(path.data()); } + + return nullptr; } -void AssetManager::remove(std::shared_ptr asset) +std::nullptr_t AssetManager::remove(std::shared_ptr asset) { if (exists(asset->path())) { m_assetList.erase(asset->path()); } + + return nullptr; } } // namespace Inferno diff --git a/src/inferno/asset/asset-manager.h b/src/inferno/asset/asset-manager.h index 8dd8276..d3624ab 100644 --- a/src/inferno/asset/asset-manager.h +++ b/src/inferno/asset/asset-manager.h @@ -6,10 +6,12 @@ #pragma once -#include // std::shared_ptr +#include // std::nullptr_t +#include // std::shared_ptr #include #include #include +#include // std::forward #include "ruc/meta/assert.h" #include "ruc/meta/types.h" @@ -62,8 +64,8 @@ public: void add(std::string_view path, std::shared_ptr asset); bool exists(std::string_view path); - void remove(std::string_view path); - void remove(std::shared_ptr asset); + std::nullptr_t remove(std::string_view path); + std::nullptr_t remove(std::shared_ptr asset); template std::shared_ptr get(std::string_view path) @@ -77,14 +79,14 @@ public: return std::static_pointer_cast(asset); } - template - std::shared_ptr load(std::string_view path) + template + std::shared_ptr load(std::string_view path, Args&&... args) { if (exists(path)) { return get(path); } - auto asset = T::create(path); + auto asset = T::create(path, std::forward(args)...); add(path, asset); return asset; } diff --git a/src/inferno/asset/texture.cpp b/src/inferno/asset/texture.cpp index 9243ba6..bc432ea 100644 --- a/src/inferno/asset/texture.cpp +++ b/src/inferno/asset/texture.cpp @@ -234,9 +234,11 @@ void TextureCubemap::createImpl() // ----------------------------------------- -std::shared_ptr TextureFramebuffer::create(uint32_t width, uint32_t height, uint32_t internalFormat, uint32_t dataFormat, uint32_t dataType) +std::shared_ptr TextureFramebuffer::create( + std::string_view path, + uint32_t width, uint32_t height, uint32_t internalFormat, uint32_t dataFormat, uint32_t dataType) { - auto result = std::shared_ptr(new TextureFramebuffer("")); + auto result = std::shared_ptr(new TextureFramebuffer(path)); result->init(width, height, internalFormat, dataFormat, dataType); result->createImpl(); @@ -244,6 +246,22 @@ std::shared_ptr TextureFramebuffer::create(uint32_t width, u return result; } +void TextureFramebuffer::bind(uint32_t unit) const +{ + // Set active unit + glActiveTexture(GL_TEXTURE0 + unit); + + glBindTexture(GL_TEXTURE_2D, m_id); + + // Reset unit + glActiveTexture(GL_TEXTURE0); +} + +void TextureFramebuffer::unbind() const +{ + glBindTexture(GL_TEXTURE_2D, 0); +} + void TextureFramebuffer::createImpl() { m_id = UINT_MAX; diff --git a/src/inferno/asset/texture.h b/src/inferno/asset/texture.h index e05ea6a..143455b 100644 --- a/src/inferno/asset/texture.h +++ b/src/inferno/asset/texture.h @@ -112,11 +112,11 @@ public: // Factory function static std::shared_ptr create( - uint32_t width, uint32_t height, - uint32_t internalFormat, uint32_t dataFormat, uint32_t dataType = GL_UNSIGNED_BYTE); + std::string_view path, + uint32_t width, uint32_t height, uint32_t internalFormat, uint32_t dataFormat, uint32_t dataType = GL_UNSIGNED_BYTE); - virtual void bind(uint32_t) const override {} - virtual void unbind() const override {} + virtual void bind(uint32_t unit) const override; + virtual void unbind() const override; private: TextureFramebuffer(std::string_view path) diff --git a/src/inferno/render/framebuffer.cpp b/src/inferno/render/framebuffer.cpp index 6d4a73a..8f67821 100644 --- a/src/inferno/render/framebuffer.cpp +++ b/src/inferno/render/framebuffer.cpp @@ -7,7 +7,6 @@ #include // int8_t #include "glad/glad.h" -#include "ruc/format/log.h" #include "ruc/meta/assert.h" #include "inferno/asset/texture.h" @@ -16,40 +15,17 @@ namespace Inferno { Framebuffer::Framebuffer(const Properties& init) + : m_type(init.type) + , m_width(init.width) + , m_height(init.height) { VERIFY(static_cast(init.type) != 0, "malformed framebuffer type: {}", init.type); m_id = UINT_MAX; glGenFramebuffers(1, &m_id); - bind(); - - if (init.type & Type::Color) { - ruc::error("color!"); - // Set color attachment 0 out of 32 - m_textures[0] = TextureFramebuffer::create(init.width, init.height, GL_RGB, GL_RGB); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[0]->id(), 0); - } - - // This combined texture is required for older GPUs - if (init.type & Type::Depth && init.type & Stencil) { - ruc::error("both!"); - m_textures[3] = TextureFramebuffer::create(init.width, init.height, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[3]->id(), 0); - } - else if (init.type & Type::Depth) { - ruc::error("depth!"); - m_textures[1] = TextureFramebuffer::create(init.width, init.height, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[1]->id(), 0); - } - else if (init.type & Type::Stencil) { - ruc::error("stencil!"); - m_textures[2] = TextureFramebuffer::create(init.width, init.height, GL_STENCIL_INDEX, GL_STENCIL_INDEX); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[2]->id(), 0); - } - check(); - unbind(); + createTextures(); } Framebuffer::~Framebuffer() @@ -76,4 +52,57 @@ void Framebuffer::unbind() const glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void Framebuffer::setSize(uint32_t width, uint32_t height) +{ + if (m_width == width && m_height == height) { + return; + } + + m_width = width; + m_height = height; + + createTextures(); +} + +// ----------------------------------------- + +void Framebuffer::createTextures() +{ + bind(); + + m_textures[0] = AssetManager::the().remove(FRAMEBUFFER_TEXTURE_COLOR); + m_textures[1] = AssetManager::the().remove(FRAMEBUFFER_TEXTURE_DEPTH); + m_textures[2] = AssetManager::the().remove(FRAMEBUFFER_TEXTURE_STENCIL); + m_textures[3] = AssetManager::the().remove(FRAMEBUFFER_TEXTURE_DEPTH_STENCIL); + + if (m_type & Type::Color) { + // Set color attachment 0 out of 32 + m_textures[0] = AssetManager::the().load( + FRAMEBUFFER_TEXTURE_COLOR, m_width, m_height, GL_RGB, GL_RGB); + m_textures[0]->bind(0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[0]->id(), 0); + m_textures[0]->unbind(); + } + + // This combined texture is required for older GPUs + if (m_type & Type::Depth && m_type & Stencil) { + m_textures[3] = AssetManager::the().load( + FRAMEBUFFER_TEXTURE_DEPTH_STENCIL, m_width, m_height, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[3]->id(), 0); + } + else if (m_type & Type::Depth) { + m_textures[1] = AssetManager::the().load( + FRAMEBUFFER_TEXTURE_DEPTH, m_width, m_height, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[1]->id(), 0); + } + else if (m_type & Type::Stencil) { + m_textures[2] = AssetManager::the().load( + FRAMEBUFFER_TEXTURE_STENCIL, m_width, m_height, GL_STENCIL_INDEX, GL_STENCIL_INDEX); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[2]->id(), 0); + } + + check(); + unbind(); +} + } // namespace Inferno diff --git a/src/inferno/render/framebuffer.h b/src/inferno/render/framebuffer.h index 7f08f19..c067840 100644 --- a/src/inferno/render/framebuffer.h +++ b/src/inferno/render/framebuffer.h @@ -12,6 +12,12 @@ #include "inferno/asset/texture.h" #include "ruc/meta/core.h" +// AssetManager paths to the global framebuffer textures +#define FRAMEBUFFER_TEXTURE_COLOR "@framebuffer-color" +#define FRAMEBUFFER_TEXTURE_DEPTH "@framebuffer-depth" +#define FRAMEBUFFER_TEXTURE_STENCIL "@framebuffer-stencil" +#define FRAMEBUFFER_TEXTURE_DEPTH_STENCIL "@framebuffer-depth-stencil" + namespace Inferno { class Framebuffer final { // Frame Buffer Object, FBO @@ -37,7 +43,21 @@ public: void bind() const; void unbind() const; + void setSize(uint32_t width, uint32_t height); + + Type type() const { return m_type; } + uint32_t width() const { return m_width; } + uint32_t height() const { return m_height; } + uint32_t id() const { return m_id; } + std::shared_ptr texture(uint8_t index) const { return m_textures[index]; } + +private: + void createTextures(); + private: + Type m_type { None }; + uint32_t m_width { 0 }; + uint32_t m_height { 0 }; uint32_t m_id { 0 }; std::shared_ptr m_textures[4] { nullptr, nullptr, nullptr, nullptr }; }; diff --git a/src/inferno/render/render-command.cpp b/src/inferno/render/render-command.cpp index 8368e8f..88fe692 100644 --- a/src/inferno/render/render-command.cpp +++ b/src/inferno/render/render-command.cpp @@ -29,11 +29,16 @@ void RenderCommand::destroy() { } -void RenderCommand::clear() +void RenderCommand::clearColorDepthBit() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } +void RenderCommand::clearColorBit() +{ + glClear(GL_COLOR_BUFFER_BIT); +} + void RenderCommand::clearColor(const glm::vec4& color) { glClearColor(color.r, color.g, color.b, color.a); diff --git a/src/inferno/render/render-command.h b/src/inferno/render/render-command.h index 2233103..7c2b934 100644 --- a/src/inferno/render/render-command.h +++ b/src/inferno/render/render-command.h @@ -19,7 +19,8 @@ public: static void initialize(); static void destroy(); - static void clear(); + static void clearColorDepthBit(); + static void clearColorBit(); static void clearColor(const glm::vec4& color); static void drawIndexed(std::shared_ptr vertexArray, uint32_t indexCount = 0); diff --git a/src/inferno/render/renderer.cpp b/src/inferno/render/renderer.cpp index 4421f09..a33690e 100644 --- a/src/inferno/render/renderer.cpp +++ b/src/inferno/render/renderer.cpp @@ -124,8 +124,8 @@ void Renderer::unbind() template void Renderer::createElementBuffer() { - // CPU // --------------------------------- + // CPU // Generate indices @@ -143,8 +143,8 @@ void Renderer::createElementBuffer() offset += vertexPerQuad; } - // GPU // --------------------------------- + // GPU // Create index buffer auto indexBuffer = std::make_shared(elements, sizeof(uint32_t) * maxElements); @@ -199,21 +199,21 @@ Renderer2D::Renderer2D(s) { Renderer::initialize(); - // CPU // --------------------------------- + // CPU // Create array for storing quads vertices m_vertexBufferBase = new QuadVertex[maxVertices]; m_vertexBufferPtr = m_vertexBufferBase; // Set default quad vertex positions - m_vertexPositions[0] = { -0.5f, -0.5f, 0.0f, 1.0f }; - m_vertexPositions[1] = { 0.5f, -0.5f, 0.0f, 1.0f }; - m_vertexPositions[2] = { 0.5f, 0.5f, 0.0f, 1.0f }; - m_vertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f }; + m_vertexPositions[0] = { -1.0f, -1.0f, 0.0f, 1.0f }; + m_vertexPositions[1] = { 1.0f, -1.0f, 0.0f, 1.0f }; + m_vertexPositions[2] = { 1.0f, 1.0f, 0.0f, 1.0f }; + m_vertexPositions[3] = { -1.0f, 1.0f, 0.0f, 1.0f }; - // GPU // --------------------------------- + // GPU // Create vertex buffer auto vertexBuffer = std::make_shared(sizeof(QuadVertex) * maxVertices); @@ -290,8 +290,8 @@ RendererCubemap::RendererCubemap(s) { Renderer::initialize(); - // CPU // --------------------------------- + // CPU // Create array for storing quads vertices m_vertexBufferBase = new CubemapVertex[maxVertices]; @@ -335,8 +335,8 @@ RendererCubemap::RendererCubemap(s) m_vertexPositions[22] = { 0.5f, -0.5f, 0.5f, 1.0f }; m_vertexPositions[23] = { 0.5f, -0.5f, -0.5f, 1.0f }; - // GPU // --------------------------------- + // GPU m_enableDepthBuffer = false; @@ -405,15 +405,15 @@ RendererFont::RendererFont(s) { Renderer::initialize(); - // CPU // --------------------------------- + // CPU // Create array for storing quads vertices m_vertexBufferBase = new SymbolVertex[maxVertices]; m_vertexBufferPtr = m_vertexBufferBase; - // GPU // --------------------------------- + // GPU m_enableDepthBuffer = false; @@ -477,15 +477,15 @@ Renderer3D::Renderer3D(s) { Renderer::initialize(); - // CPU // --------------------------------- + // CPU // Create array for storing quads vertices m_vertexBufferBase = new Vertex[maxVertices]; m_vertexBufferPtr = m_vertexBufferBase; - // GPU // --------------------------------- + // GPU m_enableDepthBuffer = true; @@ -545,15 +545,15 @@ void Renderer3D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView) void Renderer3D::createElementBuffer() { - // CPU // --------------------------------- + // CPU // Create array for storing quads vertices m_elementBufferBase = new uint32_t[maxElements]; m_elementBufferPtr = m_elementBufferBase; - // GPU // --------------------------------- + // GPU // Create index buffer auto indexBuffer = std::make_shared(m_elementBufferBase, sizeof(uint32_t) * maxElements); diff --git a/src/inferno/render/renderer.h b/src/inferno/render/renderer.h index eecef79..1d4502a 100644 --- a/src/inferno/render/renderer.h +++ b/src/inferno/render/renderer.h @@ -76,6 +76,8 @@ public: virtual void beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView); virtual void endScene(); + void setEnableDepthBuffer(bool state) { m_enableDepthBuffer = state; } + protected: Renderer() {} virtual ~Renderer() { destroy(); };