From 5bc1703b2cd70e74f76c3988ec40e72e3f878e37 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Tue, 9 Mar 2021 16:40:21 -0600 Subject: [PATCH] Encapsulate frame buffers --- core/CMakeLists.txt | 2 ++ core/Framebuffer.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++ core/Framebuffer.h | 81 ++++++++++++++++++++++++++++++++++++++++++++ core/Screen.cpp | 19 +++++++---- core/Screen.h | 4 ++- core/Window.cpp | 8 ----- core/Window.h | 6 ++-- core/couch.cpp | 22 +++++++----- 8 files changed, 193 insertions(+), 28 deletions(-) create mode 100644 core/Framebuffer.cpp create mode 100644 core/Framebuffer.h diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 3ab3a62..a1c0d6f 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -23,6 +23,8 @@ target_sources(couchlib PUBLIC CollisionShape.h CollisionShape.cpp constants.h + Framebuffer.h + Framebuffer.cpp Index.h Index.cpp Input.h diff --git a/core/Framebuffer.cpp b/core/Framebuffer.cpp new file mode 100644 index 0000000..12397d8 --- /dev/null +++ b/core/Framebuffer.cpp @@ -0,0 +1,79 @@ +/* + Dane Johnson + + LICENSE + + Couch Copyright (C) 2021 Dane Johnson + + This program comes with ABSOLUTELY NO WARRANTY; without event the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for details at + https://www.gnu.org/licenses/gpl-3.0.html + + This is free software, and you are welcome to redistribute it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + DESCRIPTION + + Framebuffers are essentially just things that can be drawn to. They have + a number of settings that are set via stateful calls to OpenGL, so they + are wrapped here so they can be saved and restored in a stateless fashion. +*/ + +#include "Framebuffer.h" + +Framebuffer::Framebuffer() { + glGenFramebuffers(1, &fbo); +} + +Framebuffer::Framebuffer(Id fbo) { + this->fbo = fbo; +} + +Framebuffer::~Framebuffer() { + // If this isn't the default framebuffer. + if (fbo != 0) { + glDeleteFramebuffers(1, &fbo); + } +} + +void Framebuffer::Enable() { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + if (depthTest) { + glEnable(GL_DEPTH_TEST); + } else { + glDisable(GL_DEPTH_TEST); + } +} + + +void Framebuffer::Clear() { + glClearColor(clearColor.x, clearColor.y, clearColor.z, 1.0f); + glClear(clearFlags); +} + +void Framebuffer::Bind() { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); +} + +// Gotta initialize static members here so DLLs will +// only create one instance. +static FramebufferStack static_stack; + +void FramebufferStack::Save(Framebuffer *buffer) { + stack.push_back(curr); + curr = buffer; +} + +void FramebufferStack::Restore() { + curr = stack.back(); + stack.pop_back(); + + curr->Enable(); +} + +FramebufferStack *FramebufferStack::GetStack() { + return &static_stack; +} diff --git a/core/Framebuffer.h b/core/Framebuffer.h new file mode 100644 index 0000000..1124214 --- /dev/null +++ b/core/Framebuffer.h @@ -0,0 +1,81 @@ +/** + @file + @author Dane Johnson + + @section LICENSE + + Couch Copyright (C) 2021 Dane Johnson + + This program comes with ABSOLUTELY NO WARRANTY; without event the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for details at + https://www.gnu.org/licenses/gpl-3.0.html + + This is free software, and you are welcome to redistribute it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + @section DESCRIPTION + + Framebuffers are essentially just things that can be drawn to. They have + a number of settings that are set via stateful calls to OpenGL, so they + are wrapped here so they can be saved and restored in a stateless fashion. +*/ + +#ifndef FRAMEBUFFER_H +#define FRAMEBUFFER_H + +#include + +#include "types.h" + +class Framebuffer { +public: + Framebuffer(); + /** + If the frame buffer has already been initialized, you can pass it + in with this constructor + @param fbo the frame buffer object handle. + */ + Framebuffer(Id fbo); + /** + Apply the configuration for this framebuffer to the OpenGL state. + */ + ~Framebuffer(); + void Enable(); + /** + Clear out this framebuffer. + */ + void Clear(); + /** + Bind the texture without applying configuration. + */ + void Bind(); + /** + What clear color to draw to this frame buffer + */ + Vector3 clearColor = Vector3(0.0f, 0.0f, 1.0f); + /** + What bit(s) to clear in this buffer. + */ + int clearFlags = GL_COLOR_BUFFER_BIT; + /** + Should we enable depth testing? + */ + bool depthTest = false; +private: + Id fbo; +}; + +class FramebufferStack { +public: + void Save(Framebuffer *buffer); + void Restore(); + Framebuffer *curr = new Framebuffer(0); // Start with the default framebuffer + static FramebufferStack *GetStack(); +private: + std::vector stack; +}; + +#endif /* FRAMEBUFFER_H */ diff --git a/core/Screen.cpp b/core/Screen.cpp index 5be3959..1946319 100644 --- a/core/Screen.cpp +++ b/core/Screen.cpp @@ -33,8 +33,10 @@ Screen::Screen() { glBindVertexArray(0); // Setup frame buffers - glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + framebuffer.clearColor = Vector3(1.0f, 0.0f, 0.0f); + framebuffer.clearFlags = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; + framebuffer.depthTest = true; + framebuffer.Bind(); tex.width = width; tex.height = height; @@ -59,14 +61,17 @@ Screen::Screen() { std::cerr << "Error setting up screen framebuffer." << std::endl; exit(1); } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + FramebufferStack::GetStack()->curr->Bind(); } void Screen::Enable() { - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); + FramebufferStack::GetStack()->Save(&framebuffer); + framebuffer.Enable(); + framebuffer.Clear(); +} + +void Screen::Disable() { + FramebufferStack::GetStack()->Restore(); } void Screen::Draw() { diff --git a/core/Screen.h b/core/Screen.h index cf797e2..9c31a99 100644 --- a/core/Screen.h +++ b/core/Screen.h @@ -7,6 +7,7 @@ #include #include "types.h" +#include "Framebuffer.h" #include "Vertex.h" #include "Material.h" @@ -14,13 +15,14 @@ class Screen { public: Screen(); void Enable(); + void Disable(); void Draw(); const int width = 640; const int height = 480; Texture tex; private: Id quad; - Id framebuffer; + Framebuffer framebuffer; Id renderbuffer; }; diff --git a/core/Window.cpp b/core/Window.cpp index a870572..743dafa 100644 --- a/core/Window.cpp +++ b/core/Window.cpp @@ -32,14 +32,6 @@ bool Window::ShouldClose() { return glfwWindowShouldClose(glfwWindow); } -void Window::Enable() { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); - glViewport(0, 0, width, height); -} - void Window::Update() { glfwSwapBuffers(glfwWindow); glfwPollEvents(); diff --git a/core/Window.h b/core/Window.h index e9cd0ae..2fa08a0 100644 --- a/core/Window.h +++ b/core/Window.h @@ -27,6 +27,8 @@ #include #include +#include "Framebuffer.h" + class Window { public: /** @@ -37,10 +39,6 @@ public: @returns whether or not the user tried to close the window */ bool ShouldClose(); - /** - Begin rendering to the window - */ - void Enable(); /** Swap the buffers and poll for events */ diff --git a/core/couch.cpp b/core/couch.cpp index 9bb45ae..b9909b3 100644 --- a/core/couch.cpp +++ b/core/couch.cpp @@ -16,6 +16,7 @@ #include "Shaders/SkyboxShader.h" #include "Screen.h" +#include "Framebuffer.h" #include "Camera.h" #include "Input.h" @@ -84,17 +85,21 @@ int main() { double delta = 0.0; while(!window.ShouldClose()) { - // Physics update() + // Physics update world->Step(delta); - - // Start rendering to texture; - screen.Enable(); - // Call update function + // Script update lua->Update(delta); + // Delete freed nodes root->DoFree(); + // Clear the default shader + FramebufferStack::GetStack()->curr->Clear(); + + // Start rendering to screen + screen.Enable(); + shader->Use(); shader->UpdateProjection(projection); Matrix view(1.0f); @@ -133,11 +138,12 @@ int main() { glDepthFunc(GL_LESS); } - // Render to the window - window.Enable(); - + // Stop rendering to texture + screen.Disable(); + screenShader->Use(); screenShader->UpdateTex(screen.tex); + screen.Draw(); window.Update();