Encapsulate frame buffers

This commit is contained in:
Dane Johnson 2021-03-09 16:40:21 -06:00
parent ccd69afc2e
commit a899135e6f
8 changed files with 193 additions and 28 deletions

View File

@ -23,6 +23,8 @@ target_sources(couchlib PUBLIC
CollisionShape.h
CollisionShape.cpp
constants.h
Framebuffer.h
Framebuffer.cpp
Index.h
Index.cpp
Input.h

79
core/Framebuffer.cpp Normal file
View File

@ -0,0 +1,79 @@
/*
Dane Johnson <dane@danejohnson.org>
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;
}

81
core/Framebuffer.h Normal file
View File

@ -0,0 +1,81 @@
/**
@file
@author Dane Johnson <dane@danejohnson.org>
@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 <vector>
#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<Framebuffer *> stack;
};
#endif /* FRAMEBUFFER_H */

View File

@ -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() {

View File

@ -7,6 +7,7 @@
#include <GL/glew.h>
#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;
};

View File

@ -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();

View File

@ -27,6 +27,8 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#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
*/

View File

@ -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();