now using intermediate 32-bit float framebuffer target, delaying TMO til after composite image is created by SGCT

This commit is contained in:
benpm
2025-10-14 12:40:24 -06:00
parent 4382fd9ddf
commit 2c60881fcd
7 changed files with 48 additions and 71 deletions

View File

@@ -26,6 +26,7 @@
#include <openspace/engine/configuration.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/engine/settings.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/joystickinputstate.h>
@@ -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)");
}

View File

@@ -10,6 +10,7 @@
"name": "OpenSpace",
"fullscreen": false,
"stereo": "none",
"bufferbitdepth": "32f",
"size": { "x": 1024, "y": 1024 },
"viewports": [
{

View File

@@ -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<RaycasterTask>& 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();

View File

@@ -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;

View File

@@ -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() ?

View File

@@ -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, &currentFbo);
// 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,
&currentFboTex
);
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<RaycasterTask>& tasks,

View File

@@ -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() {