moved bloom into postDraw() stage

This commit is contained in:
benpm
2025-08-13 22:38:10 -06:00
parent f00027fa45
commit 757849ffb2
11 changed files with 660 additions and 23 deletions
+105
View File
@@ -0,0 +1,105 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_RENDERING_POSTPROCESS___
#define __OPENSPACE_RENDERING_POSTPROCESS___
#include <ghoul/opengl/ghoul_gl.h>
#include <memory>
namespace ghoul::opengl {
class ProgramObject;
}
namespace openspace {
class PostprocessingBloom {
public:
PostprocessingBloom();
~PostprocessingBloom();
void initialize();
void deinitialize();
void setResolution(int width, int height);
void update();
void render(GLuint inputTexture);
void setEnabled(bool enabled) { _enabled = enabled; }
bool isEnabled() const { return _enabled; }
void setThreshold(float threshold) { _threshold = threshold; }
void setBlurPasses(int passes) { _blurPasses = passes; }
void setBlurMagnitude(float magnitude) { _blurMagnitude = magnitude; }
void setIntensity(float intensity) { _intensity = intensity; }
private:
void createFramebuffers();
void renderExtract(GLuint inputTexture);
void renderBlur();
void renderBlend(GLuint inputTexture);
bool _enabled = true;
float _threshold = 0.75f;
int _blurPasses = 3;
float _blurMagnitude = 0.001f;
float _intensity = 1.0f;
int _width = 0;
int _height = 0;
int _bloomWidth = 0;
int _bloomHeight = 0;
GLuint _screenQuad = 0;
GLuint _vertexBuffer = 0;
GLuint _bloomFramebuffer = 0;
GLuint _blurFramebuffer = 0;
GLuint _bloomTexture = 0;
GLuint _blurTexture[2] = {0, 0};
std::unique_ptr<ghoul::opengl::ProgramObject> _extractProgram;
std::unique_ptr<ghoul::opengl::ProgramObject> _blurProgram;
std::unique_ptr<ghoul::opengl::ProgramObject> _blendProgram;
struct {
GLint mainColorTexture = -1;
GLint threshold = -1;
} _extractUniforms;
struct {
GLint mainColorTexture = -1;
GLint blurDirection = -1;
GLint blurMagnitude = -1;
} _blurUniforms;
struct {
GLint mainColorTexture = -1;
GLint bloomTexture = -1;
GLint bloomIntensity = -1;
} _blendUniforms;
};
} // namespace openspace
#endif // __OPENSPACE_RENDERING_POSTPROCESS___
@@ -36,6 +36,7 @@
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/vector/vec4property.h>
#include <openspace/rendering/framebufferrenderer.h>
#include <openspace/rendering/postprocess.h>
#include <chrono>
#include <filesystem>
@@ -172,6 +173,7 @@ private:
Scene* _scene = nullptr;
FramebufferRenderer _renderer;
PostprocessingBloom _bloom;
ghoul::Dictionary _rendererData;
ghoul::Dictionary _resolveData;
ScreenLog* _log = nullptr;
+1 -1
View File
@@ -1 +1 @@
set (DEFAULT_MODULE ON)
set (DEFAULT_MODULE OFF)
+41
View File
@@ -0,0 +1,41 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout (location = 0) out vec4 finalColor;
in vec2 UV;
uniform sampler2D mainColorTexture;
uniform sampler2D bloomTexture;
uniform float bloomIntensity;
void main() {
vec3 scene = texture(mainColorTexture, UV).rgb;
vec3 bloom = texture(bloomTexture, UV).rgb;
vec3 color = scene + bloom * bloomIntensity;
finalColor = vec4(color, 1.0);
}
+55
View File
@@ -0,0 +1,55 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout (location = 0) out vec4 finalColor;
in vec2 UV;
uniform sampler2D mainColorTexture;
uniform vec2 blurDirection;
uniform float blurMagnitude;
uniform int n = 3;
uniform float offset[3] = float[]( 0, 1.4983346041173402, 3.4961134994916776 );
uniform float weight[3] = float[]( 0.112759, 0.224271, 0.21934900000000002 );
void main() {
vec4 sum = vec4(0.0);
vec2 tc = UV;
float mag = blurMagnitude;
float hstep = blurDirection.x;
float vstep = blurDirection.y;
float h = mag*hstep;
float v = mag*vstep;
sum = texture( mainColorTexture, tc ) * weight[0];
for (int i=1; i<n; i++) {
sum += texture( mainColorTexture, tc + vec2( offset[i] * h, offset[i] * v ) ) * weight[i];
sum += texture( mainColorTexture, tc - vec2( offset[i] * h, offset[i] * v ) ) * weight[i];
}
finalColor = vec4(sum.rgb, 1.0);
}
+42
View File
@@ -0,0 +1,42 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
layout (location = 0) out vec4 finalColor;
in vec2 UV;
uniform sampler2D mainColorTexture;
uniform float threshold;
void main() {
vec4 color = texture(mainColorTexture, UV);
float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
if (brightness > threshold){
finalColor = vec4(color.rgb, 1.0);
} else {
finalColor = vec4(0.0, 0.0, 0.0, 1.0);
}
}
+34
View File
@@ -0,0 +1,34 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
in vec4 position;
out vec2 UV;
void main() {
gl_Position = position;
UV = 0.5 + position.xy * 0.5;
}
+2
View File
@@ -138,6 +138,7 @@ set(OPENSPACE_SOURCE
rendering/labelscomponent.cpp
rendering/loadingscreen.cpp
rendering/luaconsole.cpp
rendering/postprocess.cpp
rendering/raycastermanager.cpp
rendering/renderable.cpp
rendering/renderengine.cpp
@@ -335,6 +336,7 @@ set(OPENSPACE_HEADER
${PROJECT_SOURCE_DIR}/include/openspace/rendering/luaconsole.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/helper.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/labelscomponent.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/postprocess.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/raycasterlistener.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/raycastermanager.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/renderable.h
-22
View File
@@ -48,11 +48,6 @@
#include <string>
#include <vector>
#define OPENSPACE_MODULE_POSTPROCESSING_ENABLED
#ifdef OPENSPACE_MODULE_POSTPROCESSING_ENABLED
#include <modules/postprocessing/postprocessingmodule.h>
#endif
namespace {
constexpr std::string_view _loggerCat = "FramebufferRenderer";
@@ -609,10 +604,6 @@ void FramebufferRenderer::update() {
ghoul::opengl::updateUniformLocations(*_hdrFilteringProgram, _hdrUniformCache);
}
#ifdef OPENSPACE_MODULE_POSTPROCESSING_ENABLED
PostprocessingModule::renderer().update();
#endif
if (_fxaaProgram->isDirty()) {
_fxaaProgram->rebuildFromFile();
@@ -1146,19 +1137,6 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac
glDrawBuffers(1, &ColorAttachmentArray[_pingPongIndex]);
glEnablei(GL_BLEND, 0);
#ifdef OPENSPACE_MODULE_POSTPROCESSING_ENABLED
{
// Render Postprocessing effects
TracyGpuZone("Postprocessing");
const ghoul::GLDebugGroup group("Postprocessing");
PostprocessingModule::renderer().setSceneTexture(
_pingPongBuffers.colorTexture[_pingPongIndex]
);
PostprocessingModule::renderer().render(camera);
}
#endif
{
TracyGpuZone("Overlay")
+336
View File
@@ -0,0 +1,336 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/rendering/postprocess.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr std::string_view _loggerCat = "PostprocessingBloom";
constexpr std::string_view BloomPassVertexShaderPath = "${SHADERS}/bloom_pass_vs.glsl";
constexpr std::string_view BloomExtractFragmentShaderPath = "${SHADERS}/bloom_extract_fs.glsl";
constexpr std::string_view BloomBlurFragmentShaderPath = "${SHADERS}/bloom_blur_fs.glsl";
constexpr std::string_view BloomBlendFragmentShaderPath = "${SHADERS}/bloom_blend_fs.glsl";
}
namespace openspace {
PostprocessingBloom::PostprocessingBloom() = default;
PostprocessingBloom::~PostprocessingBloom() {
deinitialize();
}
void PostprocessingBloom::initialize() {
const GLfloat vertexData[] = {
-1.f, -1.f,
1.f, 1.f,
-1.f, 1.f,
-1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
};
glGenVertexArrays(1, &_screenQuad);
glBindVertexArray(_screenQuad);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
_extractProgram = ghoul::opengl::ProgramObject::Build(
"BloomExtract",
absPath(BloomPassVertexShaderPath),
absPath(BloomExtractFragmentShaderPath)
);
if (_extractProgram) {
_extractUniforms.mainColorTexture = _extractProgram->uniformLocation("mainColorTexture");
_extractUniforms.threshold = _extractProgram->uniformLocation("threshold");
}
_blurProgram = ghoul::opengl::ProgramObject::Build(
"BloomBlur",
absPath(BloomPassVertexShaderPath),
absPath(BloomBlurFragmentShaderPath)
);
if (_blurProgram) {
_blurUniforms.mainColorTexture = _blurProgram->uniformLocation("mainColorTexture");
_blurUniforms.blurDirection = _blurProgram->uniformLocation("blurDirection");
_blurUniforms.blurMagnitude = _blurProgram->uniformLocation("blurMagnitude");
}
_blendProgram = ghoul::opengl::ProgramObject::Build(
"BloomBlend",
absPath(BloomPassVertexShaderPath),
absPath(BloomBlendFragmentShaderPath)
);
if (_blendProgram) {
_blendUniforms.mainColorTexture = _blendProgram->uniformLocation("mainColorTexture");
_blendUniforms.bloomTexture = _blendProgram->uniformLocation("bloomTexture");
_blendUniforms.bloomIntensity = _blendProgram->uniformLocation("bloomIntensity");
}
}
void PostprocessingBloom::deinitialize() {
if (_screenQuad != 0) {
glDeleteVertexArrays(1, &_screenQuad);
_screenQuad = 0;
}
if (_vertexBuffer != 0) {
glDeleteBuffers(1, &_vertexBuffer);
_vertexBuffer = 0;
}
if (_bloomFramebuffer != 0) {
glDeleteFramebuffers(1, &_bloomFramebuffer);
_bloomFramebuffer = 0;
}
if (_blurFramebuffer != 0) {
glDeleteFramebuffers(1, &_blurFramebuffer);
_blurFramebuffer = 0;
}
if (_bloomTexture != 0) {
glDeleteTextures(1, &_bloomTexture);
_bloomTexture = 0;
}
if (_blurTexture[0] != 0) {
glDeleteTextures(2, _blurTexture);
_blurTexture[0] = 0;
_blurTexture[1] = 0;
}
}
void PostprocessingBloom::setResolution(int width, int height) {
if (_width == width && _height == height) {
return;
}
_width = width;
_height = height;
_bloomWidth = width / 2;
_bloomHeight = height / 2;
createFramebuffers();
}
void PostprocessingBloom::createFramebuffers() {
if (_bloomFramebuffer != 0) {
glDeleteFramebuffers(1, &_bloomFramebuffer);
glDeleteTextures(1, &_bloomTexture);
}
if (_blurFramebuffer != 0) {
glDeleteFramebuffers(1, &_blurFramebuffer);
glDeleteTextures(2, _blurTexture);
}
glGenTextures(1, &_bloomTexture);
glBindTexture(GL_TEXTURE_2D, _bloomTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, _bloomWidth, _bloomHeight, 0, GL_RGBA, GL_FLOAT, nullptr);
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);
glGenTextures(2, _blurTexture);
for (int i = 0; i < 2; i++) {
glBindTexture(GL_TEXTURE_2D, _blurTexture[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, _bloomWidth, _bloomHeight, 0, GL_RGBA, GL_FLOAT, nullptr);
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);
}
glGenFramebuffers(1, &_bloomFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _bloomFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _bloomTexture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
LERROR("Bloom framebuffer is not complete");
}
glGenFramebuffers(1, &_blurFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _blurFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _blurTexture[0], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _blurTexture[1], 0);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
LERROR("Blur framebuffer is not complete");
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void PostprocessingBloom::update() {
if (_extractProgram && _extractProgram->isDirty()) {
_extractProgram->rebuildFromFile();
_extractUniforms.mainColorTexture = _extractProgram->uniformLocation("mainColorTexture");
_extractUniforms.threshold = _extractProgram->uniformLocation("threshold");
}
if (_blurProgram && _blurProgram->isDirty()) {
_blurProgram->rebuildFromFile();
_blurUniforms.mainColorTexture = _blurProgram->uniformLocation("mainColorTexture");
_blurUniforms.blurDirection = _blurProgram->uniformLocation("blurDirection");
_blurUniforms.blurMagnitude = _blurProgram->uniformLocation("blurMagnitude");
}
if (_blendProgram && _blendProgram->isDirty()) {
_blendProgram->rebuildFromFile();
_blendUniforms.mainColorTexture = _blendProgram->uniformLocation("mainColorTexture");
_blendUniforms.bloomTexture = _blendProgram->uniformLocation("bloomTexture");
_blendUniforms.bloomIntensity = _blendProgram->uniformLocation("bloomIntensity");
}
}
void PostprocessingBloom::render(GLuint inputTexture) {
if (!_enabled || !_extractProgram || !_blurProgram || !_blendProgram) {
return;
}
GLint defaultFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo);
renderExtract(inputTexture);
renderBlur();
renderBlend(inputTexture);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo);
}
void PostprocessingBloom::renderExtract(GLuint inputTexture) {
glBindFramebuffer(GL_FRAMEBUFFER, _bloomFramebuffer);
glViewport(0, 0, _bloomWidth, _bloomHeight);
_extractProgram->activate();
ghoul::opengl::TextureUnit textureUnit;
textureUnit.activate();
glBindTexture(GL_TEXTURE_2D, inputTexture);
glUniform1i(_extractUniforms.mainColorTexture, textureUnit);
glUniform1f(_extractUniforms.threshold, _threshold);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
_extractProgram->deactivate();
}
void PostprocessingBloom::renderBlur() {
_blurProgram->activate();
int sourceBuffer = 0;
int targetBuffer = 1;
glBindTexture(GL_TEXTURE_2D, _bloomTexture);
for (int pass = 0; pass < _blurPasses; pass++) {
// Horizontal pass
glBindFramebuffer(GL_FRAMEBUFFER, _blurFramebuffer);
glDrawBuffer(GL_COLOR_ATTACHMENT0 + targetBuffer);
glViewport(0, 0, _bloomWidth, _bloomHeight);
ghoul::opengl::TextureUnit textureUnit;
textureUnit.activate();
if (pass == 0) {
glBindTexture(GL_TEXTURE_2D, _bloomTexture);
} else {
glBindTexture(GL_TEXTURE_2D, _blurTexture[sourceBuffer]);
}
glUniform1i(_blurUniforms.mainColorTexture, textureUnit);
glUniform2f(_blurUniforms.blurDirection, 1.0f, 0.0f);
glUniform1f(_blurUniforms.blurMagnitude, _blurMagnitude);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
std::swap(sourceBuffer, targetBuffer);
// Vertical pass
glDrawBuffer(GL_COLOR_ATTACHMENT0 + targetBuffer);
textureUnit.activate();
glBindTexture(GL_TEXTURE_2D, _blurTexture[sourceBuffer]);
glUniform1i(_blurUniforms.mainColorTexture, textureUnit);
glUniform2f(_blurUniforms.blurDirection, 0.0f, 1.0f);
glUniform1f(_blurUniforms.blurMagnitude, _blurMagnitude);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
std::swap(sourceBuffer, targetBuffer);
}
_blurProgram->deactivate();
}
void PostprocessingBloom::renderBlend(GLuint inputTexture) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, _width, _height);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
_blendProgram->activate();
ghoul::opengl::TextureUnit mainTextureUnit;
mainTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D, inputTexture);
glUniform1i(_blendUniforms.mainColorTexture, mainTextureUnit);
ghoul::opengl::TextureUnit bloomTextureUnit;
bloomTextureUnit.activate();
glBindTexture(GL_TEXTURE_2D, _blurTexture[0]);
glUniform1i(_blendUniforms.bloomTexture, bloomTextureUnit);
glUniform1f(_blendUniforms.bloomIntensity, _intensity);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
_blendProgram->deactivate();
glDisable(GL_BLEND);
}
} // namespace openspace
+42
View File
@@ -514,6 +514,10 @@ void RenderEngine::initializeGL() {
_renderer.setHDRExposure(_hdrExposure);
_renderer.initialize();
_bloom.initialize();
const glm::ivec2 res = renderingResolution();
_bloom.setResolution(res.x, res.y);
// set the close clip plane and the far clip plane to extreme values while in
// development
global::windowDelegate->setNearFarClippingPlane(0.001f, 1000.f);
@@ -553,6 +557,7 @@ void RenderEngine::initializeGL() {
void RenderEngine::deinitializeGL() {
ZoneScoped;
_bloom.deinitialize();
_renderer.deinitialize();
}
@@ -600,6 +605,9 @@ void RenderEngine::updateRenderer() {
if (windowResized) {
_renderer.setResolution(renderingResolution());
const glm::ivec2 res = renderingResolution();
_bloom.setResolution(res.x, res.y);
using FR = ghoul::fontrendering::FontRenderer;
FR::defaultRenderer().setFramebufferSize(fontResolution());
FR::defaultProjectionRenderer().setFramebufferSize(renderingResolution());
@@ -614,6 +622,7 @@ void RenderEngine::updateRenderer() {
}
_renderer.update();
_bloom.update();
}
void RenderEngine::updateScreenSpaceRenderables() {
@@ -914,6 +923,39 @@ float RenderEngine::combinedBlackoutFactor() const {
void RenderEngine::postDraw() {
ZoneScoped;
// Apply bloom postprocessing effect
if (_bloom.isEnabled()) {
// Copy current framebuffer to texture for bloom processing
GLint currentFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFbo);
// Create temporary texture to capture current framebuffer content
static GLuint captureTexture = 0;
static glm::ivec2 lastRes = glm::ivec2(0);
const glm::ivec2 res = renderingResolution();
if (captureTexture == 0 || lastRes != res) {
if (captureTexture != 0) {
glDeleteTextures(1, &captureTexture);
}
glGenTextures(1, &captureTexture);
glBindTexture(GL_TEXTURE_2D, captureTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, res.x, res.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
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);
lastRes = res;
}
// Copy current framebuffer to texture
glBindTexture(GL_TEXTURE_2D, captureTexture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, res.x, res.y, 0);
// Apply bloom effect
_bloom.render(captureTexture);
}
++_frameNumber;
}