summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Framebuffer.cpp125
-rw-r--r--src/Framebuffer.hpp29
-rw-r--r--src/Render.cpp46
-rw-r--r--src/Render.hpp5
4 files changed, 192 insertions, 13 deletions
diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp
new file mode 100644
index 0000000..7127a57
--- /dev/null
+++ b/src/Framebuffer.cpp
@@ -0,0 +1,125 @@
+#include "Framebuffer.hpp"
+#include "Shader.hpp"
+#include <string>
+#include "Utility.hpp"
+
+GLuint quadVao, quadVbo;
+Shader *quadShader = nullptr;
+
+Framebuffer::Framebuffer(unsigned int width, unsigned int height, bool createDepthStencilBuffer) : width(width), height(height) {
+ if (quadShader == nullptr) {
+ float quadVertices[] = {
+ // positions // texCoords
+ -1.0f, 1.0f, 0.0f, 1.0f,
+ -1.0f, -1.0f, 0.0f, 0.0f,
+ 1.0f, -1.0f, 1.0f, 0.0f,
+
+ -1.0f, 1.0f, 0.0f, 1.0f,
+ 1.0f, -1.0f, 1.0f, 0.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f
+ };
+
+ glGenVertexArrays(1, &quadVao);
+ glGenBuffers(1, &quadVbo);
+ glBindVertexArray(quadVao);
+ glBindBuffer(GL_ARRAY_BUFFER, quadVbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
+ quadShader = new Shader("./shaders/fbo.vs", "./shaders/fbo.fs");
+ quadShader->Use();
+ glUniform1i(glGetUniformLocation(quadShader->Program, "inputTexture"), 1);
+ glActiveTexture(GL_TEXTURE1);
+ glCheckError();
+ }
+
+ glGenTextures(1, &texColor);
+ glBindTexture(GL_TEXTURE_2D, texColor);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glCheckError();
+
+ if (createDepthStencilBuffer) {
+ glGenRenderbuffers(1, &rboDepthStencil);
+ glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+ }
+
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0);
+ if(createDepthStencilBuffer)
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);
+ glCheckError();
+
+ GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE)
+ throw std::runtime_error("Failed to initialize framebuffer: " + std::to_string(framebufferStatus));
+}
+
+Framebuffer::~Framebuffer() {
+ if (rboDepthStencil)
+ glDeleteRenderbuffers(1, &rboDepthStencil);
+ if (texColor)
+ glDeleteTextures(1, &texColor);
+
+ glDeleteFramebuffers(1, &fbo);
+}
+
+void Framebuffer::Activate() {
+ glViewport(0, 0, width, height);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+}
+
+void Framebuffer::RenderTo(Framebuffer &target) {
+ glBindFramebuffer(GL_FRAMEBUFFER, target.fbo);
+ glViewport(0, 0, target.width, target.height);
+ glBindVertexArray(quadVao);
+ glUseProgram(quadShader->Program);
+ glBindTexture(GL_TEXTURE_2D, texColor);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+void Framebuffer::Resize(unsigned int newWidth, unsigned int newHeight) {
+ width = newWidth;
+ height = newHeight;
+ if (texColor) {
+ glBindTexture(GL_TEXTURE_2D, texColor);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ }
+ if (rboDepthStencil) {
+ glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+ }
+}
+
+Framebuffer &Framebuffer::GetDefault()
+{
+ static char fboDefaultData[sizeof(Framebuffer)];
+ static Framebuffer *fboDefault = nullptr;
+ if (fboDefault == nullptr) {
+ fboDefault = reinterpret_cast<Framebuffer*>(fboDefaultData);
+ fboDefault->fbo = 0;
+ fboDefault->width = 1;
+ fboDefault->height = 1;
+ fboDefault->texColor = 0;
+ fboDefault->rboDepthStencil = 0;
+ }
+ return *fboDefault;
+}
+
+void Framebuffer::Clear(bool color, bool depth, bool stencil)
+{
+ Activate();
+ GLbitfield clearBits = 0;
+ if (color)
+ clearBits |= GL_COLOR_BUFFER_BIT;
+ if (depth)
+ clearBits |= GL_DEPTH_BUFFER_BIT;
+ if (stencil)
+ clearBits |= GL_STENCIL_BUFFER_BIT;
+ glClear(clearBits);
+}
diff --git a/src/Framebuffer.hpp b/src/Framebuffer.hpp
new file mode 100644
index 0000000..6e0d33e
--- /dev/null
+++ b/src/Framebuffer.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <gl/glew.h>
+
+class Framebuffer {
+ unsigned int width, height;
+ GLuint fbo, texColor = 0, rboDepthStencil = 0;
+public:
+ Framebuffer(unsigned int width, unsigned int height, bool createDepthStencilBuffer);
+ ~Framebuffer();
+ Framebuffer(const Framebuffer&) = delete;
+ Framebuffer(Framebuffer &&) = delete;
+ Framebuffer &operator=(const Framebuffer &) = delete;
+ Framebuffer &operator=(Framebuffer &&) = delete;
+
+ void Activate();
+
+ void RenderTo(Framebuffer &target);
+
+ void Resize(unsigned int newWidth, unsigned int newHeight);
+
+ inline GLuint GetColor() {
+ return texColor;
+ }
+
+ static Framebuffer &GetDefault();
+
+ void Clear(bool color = true, bool depth = true, bool stencil = true);
+}; \ No newline at end of file
diff --git a/src/Render.cpp b/src/Render.cpp
index 21e815c..41f2c7e 100644
--- a/src/Render.cpp
+++ b/src/Render.cpp
@@ -13,6 +13,7 @@
#include "GameState.hpp"
#include "RendererWorld.hpp"
#include "Settings.hpp"
+#include "Framebuffer.hpp"
Render::Render(unsigned int windowWidth, unsigned int windowHeight,
std::string windowTitle)
@@ -40,6 +41,7 @@ Render::Render(unsigned int windowWidth, unsigned int windowHeight,
fieldWireframe = Settings::ReadBool("wireframe", false);
fieldFlight = Settings::ReadBool("flight", false);
fieldBrightness = Settings::ReadDouble("brightness", 0.2f);
+ fieldResolutionScale = Settings::ReadDouble("resolutionScale", 1.0f);
//Apply settings
if (fieldSensetivity != sensetivity)
@@ -52,6 +54,7 @@ Render::Render(unsigned int windowWidth, unsigned int windowHeight,
}
else
SDL_GL_SetSwapInterval(0);
+ framebuffer->Resize(renderState.WindowWidth * fieldResolutionScale, renderState.WindowHeight * fieldResolutionScale);
LOG(INFO) << "Supported threads: " << std::thread::hardware_concurrency();
}
@@ -66,8 +69,10 @@ Render::~Render() {
Settings::WriteBool("wireframe", fieldWireframe);
Settings::WriteBool("flight", fieldFlight);
Settings::WriteDouble("brightness", fieldBrightness);
+ Settings::WriteDouble("resolutionScale", fieldResolutionScale);
Settings::Save();
-
+
+ framebuffer.reset();
ImGui_ImplSdlGL3_Shutdown();
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
@@ -115,7 +120,7 @@ void Render::InitGlew() {
int width, height;
SDL_GL_GetDrawableSize(window, &width, &height);
glViewport(0, 0, width, height);
- glClearColor(0.8,0.8,0.8, 1.0f);
+ glClearColor(0.8,0.8,0.8, 1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
@@ -136,6 +141,12 @@ void Render::PrepareToRendering() {
glBindTexture(GL_TEXTURE_2D_ARRAY, AssetManager::GetTextureAtlasId());
ImGui_ImplSdlGL3_Init(window);
+
+ int width, height;
+ SDL_GL_GetDrawableSize(window, &width, &height);
+ framebuffer = std::make_unique<Framebuffer>(width, height, true);
+ Framebuffer::GetDefault().Activate();
+ Framebuffer::GetDefault().Resize(width, height);
}
void Render::UpdateKeyboard() {
@@ -160,20 +171,25 @@ void Render::UpdateKeyboard() {
}
void Render::RenderFrame() {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ framebuffer->Clear();
+ Framebuffer::GetDefault().Clear();
+ if (renderWorld)
+ framebuffer->Activate();
if (isWireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (renderWorld)
world->Render(renderState);
if (isWireframe)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ if (renderWorld)
+ framebuffer->RenderTo(Framebuffer::GetDefault());
- if (world) {
- world->Update(timer.RemainTimeMs());
- }
+ RenderGui();
- RenderGui();
+ if (world) {
+ world->Update(timer.RemainTimeMs());
+ }
SDL_GL_SwapWindow(window);
}
@@ -196,9 +212,10 @@ void Render::HandleEvents() {
case SDL_WINDOWEVENT_RESIZED: {
int width, height;
SDL_GL_GetDrawableSize(window, &width, &height);
- glViewport(0, 0, width, height);
renderState.WindowWidth = width;
renderState.WindowHeight = height;
+ framebuffer->Resize(width * fieldResolutionScale, height * fieldResolutionScale);
+ Framebuffer::GetDefault().Resize(width, height);
break;
}
@@ -581,6 +598,8 @@ void Render::RenderGui() {
ImGui::SliderFloat("Target FPS", &fieldTargetFps, 1.0f, 300.0f);
+ ImGui::SliderFloat("Resolution scale", &fieldResolutionScale, 0.1f, 2.0f);
+
ImGui::Checkbox("Wireframe", &fieldWireframe);
ImGui::Checkbox("VSync", &fieldVsync);
@@ -608,6 +627,9 @@ void Render::RenderGui() {
PUSH_EVENT("SetMinLightLevel", fieldBrightness);
+ int width, height;
+ SDL_GL_GetDrawableSize(window, &width, &height);
+ framebuffer->Resize(width * fieldResolutionScale, height * fieldResolutionScale);
}
ImGui::Separator();
@@ -648,7 +670,7 @@ void Render::InitEvents() {
stateString = "Playing";
renderWorld = true;
GlobalState::SetState(State::Playing);
- glClearColor(0, 0, 0, 1.0f);
+ glClearColor(0, 0, 0, 1.0f);
world->GameStatePtr()->player->isFlying = this->fieldFlight;
PUSH_EVENT("SetMinLightLevel", fieldBrightness);
});
@@ -658,7 +680,7 @@ void Render::InitEvents() {
renderWorld = false;
world.reset();
GlobalState::SetState(State::MainMenu);
- glClearColor(0.8, 0.8, 0.8, 1.0f);
+ glClearColor(0.8, 0.8, 0.8, 1.0f);
});
listener.RegisterHandler("Disconnected", [this](const Event& eventData) {
@@ -666,7 +688,7 @@ void Render::InitEvents() {
renderWorld = false;
world.reset();
GlobalState::SetState(State::MainMenu);
- glClearColor(0.8, 0.8, 0.8, 1.0f);
+ glClearColor(0.8, 0.8, 0.8, 1.0f);
});
listener.RegisterHandler("Connecting", [this](const Event&) {
diff --git a/src/Render.hpp b/src/Render.hpp
index adb0547..eea5450 100644
--- a/src/Render.hpp
+++ b/src/Render.hpp
@@ -12,6 +12,7 @@
#include "Event.hpp"
class RendererWorld;
+class Framebuffer;
class Render {
SDL_Window *window;
@@ -28,7 +29,8 @@ class Render {
std::map<SDL_Scancode, bool> isKeyPressed;
bool HasFocus=true;
float sensetivity = 0.1f;
- bool isWireframe = false;
+ bool isWireframe = false;
+ std::unique_ptr<Framebuffer> framebuffer;
std::vector<std::string> chatMessages;
EventListener listener;
std::string stateString;
@@ -41,6 +43,7 @@ class Render {
bool fieldVsync;
bool fieldFlight;
float fieldBrightness;
+ float fieldResolutionScale;
void SetMouseCapture(bool IsCaptured);