From 608b53730e26410372ccf9d8f5ccf89ec5364f57 Mon Sep 17 00:00:00 2001 From: Quentin Bazin Date: Mon, 29 Jun 2020 23:18:24 +0200 Subject: [PATCH] [Framebuffer] Added. [GameState] Now using a framebuffer to render the scene and apply effects. --- external/gamekit | 2 +- resources/shaders/screen.f.glsl | 12 +++++ resources/shaders/screen.v.glsl | 15 ++++++ source/client/graphics/Framebuffer.cpp | 75 ++++++++++++++++++++++++++ source/client/graphics/Framebuffer.hpp | 49 +++++++++++++++++ source/client/states/GameState.cpp | 46 +++++++++++++++- source/client/states/GameState.hpp | 5 ++ 7 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 resources/shaders/screen.f.glsl create mode 100644 resources/shaders/screen.v.glsl create mode 100644 source/client/graphics/Framebuffer.cpp create mode 100644 source/client/graphics/Framebuffer.hpp diff --git a/external/gamekit b/external/gamekit index 4e431788..29f76f71 160000 --- a/external/gamekit +++ b/external/gamekit @@ -1 +1 @@ -Subproject commit 4e4317882c53b0b67ed4918f4cf5f11335b4fb69 +Subproject commit 29f76f71e938234c110794008854eea23582bef2 diff --git a/resources/shaders/screen.f.glsl b/resources/shaders/screen.f.glsl new file mode 100644 index 00000000..b5bc3460 --- /dev/null +++ b/resources/shaders/screen.f.glsl @@ -0,0 +1,12 @@ +#version 120 + +varying vec2 v_texCoord; +varying vec2 v_coord2d; + +uniform sampler2D screenTexture; + +void main() { + gl_FragColor = texture2D(screenTexture, v_texCoord); + /* gl_FragColor = vec4(vec3(1.0 - texture2D(screenTexture, v_texCoord)), 1.0); */ +} + diff --git a/resources/shaders/screen.v.glsl b/resources/shaders/screen.v.glsl new file mode 100644 index 00000000..b72b3f87 --- /dev/null +++ b/resources/shaders/screen.v.glsl @@ -0,0 +1,15 @@ +#version 120 + +attribute vec2 coord2d; +attribute vec2 texCoord; + +varying vec2 v_texCoord; +varying vec2 v_coord2d; + +void main() { + v_texCoord = texCoord; + v_coord2d = coord2d; + + gl_Position = vec4(coord2d.x, coord2d.y, 0.0, 1.0); +} + diff --git a/source/client/graphics/Framebuffer.cpp b/source/client/graphics/Framebuffer.cpp new file mode 100644 index 00000000..80a38073 --- /dev/null +++ b/source/client/graphics/Framebuffer.cpp @@ -0,0 +1,75 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#include +#include + +#include "Framebuffer.hpp" + +Framebuffer::Framebuffer(u16 width, u16 height) { + glCheck(glGenFramebuffers(1, &m_id)); + bind(this); + + glCheck(glGenTextures(1, &m_texid)); + glCheck(glBindTexture(GL_TEXTURE_2D, m_texid)); + glCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr)); + glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + glCheck(glBindTexture(GL_TEXTURE_2D, 0)); + + glCheck(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texid, 0)); + + glCheck(glGenRenderbuffers(1, &m_rbo)); + glCheck(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo)); + glCheck(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height)); + glCheck(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + + glCheck(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo)); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + throw EXCEPTION("Framebuffer is not complete"); + + bind(nullptr); +} + +Framebuffer::~Framebuffer() { + if (m_id) + glCheck(glDeleteFramebuffers(1, &m_id)); + + if (m_texid) + glCheck(glDeleteTextures(1, &m_texid)); + + if (m_rbo) + glCheck(glDeleteRenderbuffers(1, &m_rbo)); +} + +void Framebuffer::bind(const Framebuffer *framebuffer) { + if (framebuffer) + glCheck(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->m_id)); + else + glCheck(glBindFramebuffer(GL_FRAMEBUFFER, 0)); +} + diff --git a/source/client/graphics/Framebuffer.hpp b/source/client/graphics/Framebuffer.hpp new file mode 100644 index 00000000..2fe0fe13 --- /dev/null +++ b/source/client/graphics/Framebuffer.hpp @@ -0,0 +1,49 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#ifndef FRAMEBUFFER_HPP_ +#define FRAMEBUFFER_HPP_ + +#include +#include + +class Framebuffer { + public: + Framebuffer(u16 width, u16 height); + ~Framebuffer(); + + GLuint texid() const { return m_texid; } + + static void bind(const Framebuffer *framebuffer); + + private: + GLuint m_id = 0; + + GLuint m_texid = 0; + GLuint m_rbo = 0; +}; + +#endif // FRAMEBUFFER_HPP_ diff --git a/source/client/states/GameState.cpp b/source/client/states/GameState.cpp index 3ffea910..896e33fc 100644 --- a/source/client/states/GameState.cpp +++ b/source/client/states/GameState.cpp @@ -182,6 +182,24 @@ void GameState::initShaders() { m_shader.addShader(GL_FRAGMENT_SHADER, "resources/shaders/game.f.glsl"); m_shader.linkProgram(); + + m_screenShader.createProgram(); + m_screenShader.addShader(GL_VERTEX_SHADER, "resources/shaders/screen.v.glsl"); + m_screenShader.addShader(GL_FRAGMENT_SHADER, "resources/shaders/screen.f.glsl"); + m_screenShader.linkProgram(); + + float quad[24] = { + -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 + }; + gk::VertexBuffer::bind(&m_screenQuadVBO); + m_screenQuadVBO.setData(sizeof(quad), &quad, GL_STATIC_DRAW); + gk::VertexBuffer::bind(nullptr); } void GameState::onGuiScaleChanged(const GuiScaleChangedEvent &event) { @@ -194,8 +212,12 @@ void GameState::draw(gk::RenderTarget &target, gk::RenderStates states) const { // m_shader.setUniform("u_time", gk::GameClock::getInstance().getTicks()); // gk::Shader::bind(nullptr); - states.shader = &m_shader; + Framebuffer::bind(&m_fbo); + // glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + states.shader = &m_shader; target.setView(m_camera); target.draw(m_world, states); @@ -203,6 +225,28 @@ void GameState::draw(gk::RenderTarget &target, gk::RenderStates states) const { if (it.second.dimension() == m_player.dimension()) target.draw(it.second, states); + Framebuffer::bind(nullptr); + // glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glDisable(GL_DEPTH_TEST); + glBindTexture(GL_TEXTURE_2D, m_fbo.texid()); + + gk::Shader::bind(&m_screenShader); + gk::VertexBuffer::bind(&m_screenQuadVBO); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + m_screenQuadVBO.setAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(0 * sizeof(float))); + m_screenQuadVBO.setAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); + glDrawArrays(GL_TRIANGLES, 0, 6); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); + gk::VertexBuffer::bind(nullptr); + gk::Shader::bind(nullptr); + + states.shader = &m_shader; + glEnable(GL_DEPTH_TEST); + target.draw(m_hud, states); } diff --git a/source/client/states/GameState.hpp b/source/client/states/GameState.hpp index be9c874c..cf6e7ba9 100644 --- a/source/client/states/GameState.hpp +++ b/source/client/states/GameState.hpp @@ -38,6 +38,7 @@ #include "ClientPlayer.hpp" #include "ClientWorld.hpp" #include "Config.hpp" +#include "Framebuffer.hpp" #include "HUD.hpp" #include "KeyboardHandler.hpp" #include "PlayerBox.hpp" @@ -78,6 +79,10 @@ class GameState : public gk::ApplicationState { gk::Shader m_shader; + gk::Shader m_screenShader; + Framebuffer m_fbo{Config::screenWidth, Config::screenHeight}; + gk::VertexBuffer m_screenQuadVBO; + gk::Camera m_camera{70.0f, DIST_NEAR, DIST_FAR}; ClientPlayer m_player{m_camera};