Skip to content

Instantly share code, notes, and snippets.

@OperationDarkside
Created May 6, 2022 15:57
Show Gist options
  • Save OperationDarkside/1a40f859dd97dc67c7fa3f21067258f4 to your computer and use it in GitHub Desktop.
Save OperationDarkside/1a40f859dd97dc67c7fa3f21067258f4 to your computer and use it in GitHub Desktop.
Stronger Blur with Low Res Framebuffer
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, &copyVAO);
glGenBuffers(1, &copyVBO);
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, &copyVAO);
glDeleteBuffers(1, &copyVBO);
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