diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 40daa211bf..f59c713243 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -586,6 +587,19 @@ void mainDraw2DFunc(const sgct::RenderData& data) { currentFrustumMode = data.frustumMode; currentDrawResolution = glm::ivec2(data.bufferSize.x, data.bufferSize.y); + GLint prevFbo = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFbo); + + glm::ivec4 viewport = glm::ivec4( + data.viewport.position().x, + data.viewport.position().y, + data.viewport.size().x * data.window.framebufferResolution().x, + data.viewport.size().y * data.window.framebufferResolution().y + ); + global::renderEngine->applyTMOEffect(global::renderEngine->combinedBlackoutFactor(), viewport); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + try { global::openSpaceEngine->drawOverlays(); } @@ -597,6 +611,7 @@ void mainDraw2DFunc(const sgct::RenderData& data) { glEnable(GL_BLEND); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); + glBindFramebuffer(GL_FRAMEBUFFER, prevFbo); LTRACE("main::mainDraw2DFunc(end)"); } diff --git a/config/single_fisheye.json b/config/single_fisheye.json index 4587e961f4..9f012c8a9f 100644 --- a/config/single_fisheye.json +++ b/config/single_fisheye.json @@ -10,6 +10,7 @@ "name": "OpenSpace", "fullscreen": false, "stereo": "none", + "bufferbitdepth": "32f", "size": { "x": 1024, "y": 1024 }, "viewports": [ { diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index 4eb2335f67..574bc75f82 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -168,7 +168,8 @@ public: * Apply Tone Mapping Operator on the current framebuffer content for composite frame processing. * This should be called after bloom but before GUI overlays. */ - void applyTMOComposite(float blackoutFactor); + void applyTMOComposite(float blackoutFactor, const glm::ivec4& viewport); + void applyTMO(float blackoutFactor, const glm::ivec4& viewport); void update(); void performRaycasterTasks(const std::vector& tasks, @@ -198,7 +199,6 @@ private: >; void resolveMSAA(float blackoutFactor); - void applyTMO(float blackoutFactor, const glm::ivec4& viewport); void applyFXAA(const glm::ivec4& viewport); void updateDownscaleTextures() const; void updateExitVolumeTextures(); diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index e76d9b6991..a9cbfbd0b5 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -92,7 +92,7 @@ public: void renderOverlays(const ShutdownInformation& shutdownInfo); void renderEndscreen(); void applyBloomEffect(); - void applyTMOEffect(float blackoutFactor); + void applyTMOEffect(float blackoutFactor, const glm::ivec4& viewport); void postDraw(); float hdrExposure() const; diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 82ab71e2ec..3ba04fc4f5 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -1292,12 +1292,6 @@ void OpenSpaceEngine::drawOverlays() { viewportChanged(); - // Apply bloom effect on the stitched / composited image - // global::renderEngine->applyBloomEffect(); - - // Apply TMO on the composite frame after bloom - // global::renderEngine->applyTMOEffect(global::renderEngine->combinedBlackoutFactor()); - // Render the overlays on top of the rendered scene const bool isGuiWindow = global::windowDelegate->hasGuiWindow() ? diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 0b8a70cbc8..64ac6f4c81 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -466,40 +466,29 @@ void FramebufferRenderer::applyTMO(float blackoutFactor, const glm::ivec4& viewp _hdrFilteringProgram->deactivate(); } -void FramebufferRenderer::applyTMOComposite(float blackoutFactor) { +void FramebufferRenderer::applyTMOComposite(float blackoutFactor, const glm::ivec4& viewport) { ZoneScoped; TracyGpuZone("applyTMOComposite"); - GLint currentFbo; + // Get currently bound FBO and its color texture + GLint currentFbo, currentFboTex; glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tFbo); - - // Create temporary texture to capture current framebuffer content - static GLuint captureTexture = 0; - static glm::ivec2 lastRes = glm::ivec2(0); - - if (captureTexture == 0 || lastRes != _resolution) { - if (captureTexture != 0) { - glDeleteTextures(1, &captureTexture); - } - glGenTextures(1, &captureTexture); - glBindTexture(GL_TEXTURE_2D, captureTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, _resolution.x, _resolution.y, 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); - lastRes = _resolution; - } - - // Copy current framebuffer to texture - glBindTexture(GL_TEXTURE_2D, captureTexture); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, _resolution.x, _resolution.y, 0); + glGetFramebufferAttachmentParameteriv( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + ¤tFboTex + ); + glBindFramebuffer(GL_FRAMEBUFFER, 0u); + assert(currentFboTex != 0); + assert(currentFbo != 0); + _hdrFilteringProgram->activate(); ghoul::opengl::TextureUnit hdrFeedingTextureUnit; hdrFeedingTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, captureTexture); + glBindTexture(GL_TEXTURE_2D, currentFboTex); _hdrFilteringProgram->setUniform( _hdrUniformCache.hdrFeedingTexture, @@ -513,7 +502,7 @@ void FramebufferRenderer::applyTMOComposite(float blackoutFactor) { _hdrFilteringProgram->setUniform(_hdrUniformCache.Saturation, _saturation); _hdrFilteringProgram->setUniform(_hdrUniformCache.Value, _value); // Use full viewport for composite frame - _hdrFilteringProgram->setUniform(_hdrUniformCache.Viewport, glm::vec4(0, 0, _resolution.x, _resolution.y)); + _hdrFilteringProgram->setUniform(_hdrUniformCache.Viewport, glm::vec4(viewport)); _hdrFilteringProgram->setUniform(_hdrUniformCache.Resolution, glm::vec2(_resolution)); glDepthMask(false); @@ -527,6 +516,7 @@ void FramebufferRenderer::applyTMOComposite(float blackoutFactor) { glEnable(GL_DEPTH_TEST); _hdrFilteringProgram->deactivate(); + glBindFramebuffer(GL_FRAMEBUFFER, currentFbo); } void FramebufferRenderer::applyFXAA(const glm::ivec4& viewport) { @@ -1222,14 +1212,6 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac glDrawBuffers(1, &ColorAttachmentArray[_pingPongIndex]); glEnablei(GL_BLEND, 0); - // Apply bloom effect before TMO (in HDR color space) - if (_bloomEffect && _bloomEffect->isEnabled()) { - TracyGpuZone("Apply Bloom"); - const ghoul::GLDebugGroup group("Apply Bloom"); - - _bloomEffect->render(_pingPongBuffers.colorTexture[_pingPongIndex]); - } - { TracyGpuZone("Overlay") const ghoul::GLDebugGroup group("Overlay"); @@ -1259,33 +1241,18 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac // Disabling depth test for filtering and hdr glDisable(GL_DEPTH_TEST); + + glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); - if (_enableFXAA) { - glBindFramebuffer(GL_FRAMEBUFFER, _fxaaBuffers.fxaaFramebuffer); - glDrawBuffers(1, ColorAttachmentArray.data()); - glDisable(GL_BLEND); - - } - else { - // When applying the TMO, the result is saved to the default FBO to be displayed - // by the Operating System. Also, the resolve procedure is executed in this step. - glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); - } - - { - // Apply the selected TMO on the results and resolve the result to the default FBO - TracyGpuZone("Apply TMO"); - const ghoul::GLDebugGroup group("Apply TMO"); - - applyTMO(blackoutFactor, viewport); - } - - if (_enableFXAA) { - TracyGpuZone("Apply FXAA") - const ghoul::GLDebugGroup group("Apply FXAA"); - glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); - applyFXAA(viewport); - } + // Copy final color to SGCT output buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, _pingPongBuffers.framebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _defaultFBO); + glBlitFramebuffer( + 0, 0, _resolution.x, _resolution.y, + viewport.x, viewport.y, viewport.x + viewport.z, viewport.y + viewport.w, + GL_COLOR_BUFFER_BIT, + GL_NEAREST + ); } void FramebufferRenderer::performRaycasterTasks(const std::vector& tasks, diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index f9809f8030..58d5939802 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -1045,10 +1045,10 @@ void RenderEngine::applyBloomEffect() { } } -void RenderEngine::applyTMOEffect(float blackoutFactor) { +void RenderEngine::applyTMOEffect(float blackoutFactor, const glm::ivec4& viewport) { ZoneScoped; - _renderer.applyTMOComposite(blackoutFactor); + _renderer.applyTMOComposite(blackoutFactor, viewport); } void RenderEngine::postDraw() {