Created
May 6, 2022 15:57
-
-
Save OperationDarkside/1a40f859dd97dc67c7fa3f21067258f4 to your computer and use it in GitHub Desktop.
Stronger Blur with Low Res Framebuffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module; | |
#include <memory> | |
#include <array> | |
#include <iostream> | |
#include <glad/glad.h> | |
#include <GLFW/glfw3.h> | |
export module BlurRenderer; | |
import Shader; | |
import ScreenDimensions; | |
export class BlurRenderer { | |
public: | |
constexpr BlurRenderer(ScreenDimensions& screenDim) : m_screenDim(screenDim) { | |
} | |
void init() { | |
// PING PONG | |
glGenFramebuffers(2, pingpongFBO); | |
glGenTextures(2, pingpongBuffer); | |
for (std::uint8_t i = 0; i < 2; i++) { | |
glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]); | |
glBindTexture(GL_TEXTURE_2D, pingpongBuffer[i]); | |
glTexImage2D( | |
GL_TEXTURE_2D, 0, GL_RGB16F, m_screenDim.SCR_WIDTH / scaleFactor, m_screenDim.SCR_HEIGHT / scaleFactor, 0, GL_RGB, | |
GL_FLOAT, NULL); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
glFramebufferTexture2D( | |
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
pingpongBuffer[i], 0); | |
} | |
// HIGH RESOLUTION | |
glGenFramebuffers(1, &highResFBO); | |
glGenTextures(1, &highResBuf); | |
glBindFramebuffer(GL_FRAMEBUFFER, highResFBO); | |
glBindTexture(GL_TEXTURE_2D, highResBuf); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, m_screenDim.SCR_WIDTH, m_screenDim.SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, highResBuf, 0); | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
blurShader.init("shaders/blur.vs", "shaders/blur.fs", ""); | |
blurShader.use(); | |
blurShader.setInt("image", 0); | |
// create copy vao | |
glGenVertexArrays(1, ©VAO); | |
glGenBuffers(1, ©VBO); | |
glBindVertexArray(copyVAO); | |
glBindBuffer(GL_ARRAY_BUFFER, copyVBO); | |
glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(float), &quadVertices, GL_STATIC_DRAW); | |
glEnableVertexAttribArray(0); | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); | |
glEnableVertexAttribArray(1); | |
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); | |
} | |
void draw() { | |
// Copy default FBO to HighResFBO | |
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); | |
glReadBuffer(GL_COLOR_ATTACHMENT0); | |
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, highResFBO); | |
glDrawBuffer(GL_COLOR_ATTACHMENT0); | |
glBlitFramebuffer(0, 0, m_screenDim.SCR_WIDTH, m_screenDim.SCR_HEIGHT, 0, 0, m_screenDim.SCR_WIDTH, | |
m_screenDim.SCR_HEIGHT, | |
GL_COLOR_BUFFER_BIT, | |
GL_NEAREST); | |
// Copy HighResFBO to PingPong0FBO | |
glBindFramebuffer(GL_READ_FRAMEBUFFER, highResFBO); | |
glReadBuffer(GL_COLOR_ATTACHMENT0); | |
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pingpongFBO[0]); | |
glDrawBuffer(GL_COLOR_ATTACHMENT0); | |
glViewport(0, 0, m_screenDim.SCR_WIDTH / scaleFactor, m_screenDim.SCR_HEIGHT / scaleFactor); | |
glBlitFramebuffer(0, 0, m_screenDim.SCR_WIDTH, m_screenDim.SCR_HEIGHT, 0, 0, m_screenDim.SCR_WIDTH / scaleFactor, | |
m_screenDim.SCR_HEIGHT / scaleFactor, | |
GL_COLOR_BUFFER_BIT, | |
GL_LINEAR); | |
// Blur texture | |
bool horizontal = false; | |
blurShader.use(); | |
for (std::uint8_t i = 0; i < blurIterations; i++) { | |
glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[!horizontal]); | |
blurShader.setInt("horizontal", horizontal); | |
glActiveTexture(GL_TEXTURE0); | |
glBindTexture(GL_TEXTURE_2D, pingpongBuffer[horizontal]); | |
glBindVertexArray(copyVAO); | |
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
glBindVertexArray(0); | |
horizontal = !horizontal; | |
} | |
// Copy PingPong1FBO to HighResFBO | |
glBindFramebuffer(GL_READ_FRAMEBUFFER, pingpongFBO[1]); | |
glReadBuffer(GL_COLOR_ATTACHMENT0); | |
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, highResFBO); | |
glDrawBuffer(GL_COLOR_ATTACHMENT0); | |
glViewport(0, 0, m_screenDim.SCR_WIDTH, m_screenDim.SCR_HEIGHT); | |
glBlitFramebuffer(0, 0, m_screenDim.SCR_WIDTH / scaleFactor, m_screenDim.SCR_HEIGHT / scaleFactor, 0, 0, m_screenDim.SCR_WIDTH, | |
m_screenDim.SCR_HEIGHT, | |
GL_COLOR_BUFFER_BIT, | |
GL_LINEAR); | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
} | |
constexpr unsigned int getBlurredTexture() { | |
return highResBuf; | |
} | |
constexpr void setScreenDimensions(const ScreenDimensions& screenDim) { | |
m_screenDim = screenDim; | |
} | |
void deleteStuff() { | |
glDeleteFramebuffers(2, pingpongFBO); | |
glDeleteFramebuffers(1, &highResFBO); | |
glDeleteVertexArrays(1, ©VAO); | |
glDeleteBuffers(1, ©VBO); | |
glDeleteTextures(2, pingpongBuffer); | |
glDeleteTextures(1, &highResBuf); | |
} | |
private: | |
static constexpr std::uint8_t scaleFactor = 16; | |
unsigned int copyVAO = 0, copyVBO = 0; | |
unsigned int highResFBO{}; | |
unsigned int highResBuf{}; | |
unsigned int pingpongFBO[2]{}; | |
unsigned int pingpongBuffer[2]{}; | |
static constexpr std::uint8_t blurIterations = 6; | |
static constexpr std::array<float, 20> quadVertices { | |
// positions // texture Coords | |
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, | |
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, | |
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, | |
1.0f, -1.0f, 0.0f, 1.0f, 0.0f | |
}; | |
Shader blurShader{}; | |
ScreenDimensions& m_screenDim; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment