From 844ea5f3d259188d79f6e08e8195cc68976e578c Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Fri, 16 Aug 2019 13:44:56 -0400 Subject: [PATCH 1/8] Added FXAA. --- .../openspace/rendering/framebufferrenderer.h | 16 +- include/openspace/rendering/renderengine.h | 2 + include/openspace/rendering/renderer.h | 1 + shaders/framebuffer/fxaa.frag | 265 ++++++++++++++++++ shaders/framebuffer/fxaa.vert | 33 +++ src/rendering/framebufferrenderer.cpp | 128 ++++++++- src/rendering/renderengine.cpp | 14 + 7 files changed, 453 insertions(+), 6 deletions(-) create mode 100644 shaders/framebuffer/fxaa.frag create mode 100644 shaders/framebuffer/fxaa.vert diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index a86fbe2d0e..5b5e173566 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -109,6 +109,11 @@ private: GLuint _hdrFilteringTexture; } HDRBuffers; + typedef struct { + GLuint _fxaaFramebuffer; + GLuint _fxaaTexture; + } FXAABuffers; + public: typedef std::map< VolumeRaycaster*, @@ -128,6 +133,7 @@ public: void updateRaycastData(); void updateDeferredcastData(); void updateHDRAndFiltering(); + void updateFXAA(); void setResolution(glm::ivec2 res) override; void setNAaSamples(int nAaSamples) override; @@ -138,6 +144,7 @@ public: void setSaturation(float sat) override; int nAaSamples() const override; + void enableFXAA(bool enable) override; void disableHDR(bool disable) override; void update() override; @@ -159,6 +166,7 @@ public: private: void resolveMSAA(float blackoutFactor); void applyTMO(float blackoutFactor); + void applyFXAA(); private: std::map _raycastData; @@ -171,12 +179,13 @@ private: std::unique_ptr _hdrFilteringProgram; std::unique_ptr _tmoProgram; - std::unique_ptr _resolveProgram; + std::unique_ptr _fxaaProgram; + UniformCache(mainColorTexture, blackoutFactor, nAaSamples) _uniformCache; - UniformCache(hdrFeedingTexture, blackoutFactor, hdrExposure, gamma, Hue, Saturation, Value, nAaSamples) _hdrUniformCache; + UniformCache(renderedTexture, inverseScreenSize) _fxaaUniformCache; GLint _defaultFBO; GLuint _screenQuad; @@ -188,6 +197,7 @@ private: GBuffers _gBuffers; PingPongBuffers _pingPongBuffers; HDRBuffers _hdrBuffers; + FXAABuffers _fxaaBuffers; unsigned int _pingPongIndex = 0u; @@ -198,11 +208,11 @@ private: glm::ivec2 _resolution = glm::ivec2(0); int _nAaSamples; + bool _enableFXAA = false; bool _disableHDR = false; float _hdrExposure = 3.7f; float _gamma = 0.95f; - float _maxWhite = 5.0f; float _hue = 1.f; float _saturation = 1.f; float _value = 1.f; diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 56caf5a961..5ea7abcbde 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -209,6 +209,8 @@ private: properties::FloatProperty _globalBlackOutFactor; properties::IntProperty _nAaSamples; + properties::BoolProperty _enableFXAA; + properties::BoolProperty _disableHDRPipeline; properties::FloatProperty _hdrExposure; properties::FloatProperty _gamma; diff --git a/include/openspace/rendering/renderer.h b/include/openspace/rendering/renderer.h index 3520a02195..df2f1b3b67 100644 --- a/include/openspace/rendering/renderer.h +++ b/include/openspace/rendering/renderer.h @@ -56,6 +56,7 @@ public: virtual void setValue(float value) = 0; virtual void setSaturation(float sat) = 0; virtual int nAaSamples() const = 0; + virtual void enableFXAA(bool enable) = 0; virtual void disableHDR(bool disable) = 0; /** diff --git a/shaders/framebuffer/fxaa.frag b/shaders/framebuffer/fxaa.frag new file mode 100644 index 0000000000..5cb4963b61 --- /dev/null +++ b/shaders/framebuffer/fxaa.frag @@ -0,0 +1,265 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2019 * + * * + * 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__ + +#define EDGE_THRESHOLD_MIN 0.0312f +#define EDGE_THRESHOLD_MAX 0.125f +#define ITERATIONS 12 +#define SUBPIXEL_QUALITY 0.75f + +const float[12] QUALITY = {1.f, 1.f, 1.f, 1.f, 1.f, 1.5f, 2.f, 2.f, 2.f, 2.f, 4.f, 8.f}; + +layout (location = 0) out vec4 aaFinalColor; + +uniform vec2 inverseScreenSize; +uniform sampler2D renderedTexture; + +in vec2 texCoord; + +float rgb2luma(vec3 rgb){ + return sqrt(dot(rgb, vec3(0.299, 0.587, 0.114))); +} + +void main() { + vec4 colorCenter = texture(renderedTexture,texCoord); + + // ============================ + // Detecting where to apply AA: + // ============================ + + // Luma at the current fragment + float lumaCenter = rgb2luma(colorCenter.rgb); + + // Luma at the four direct neighbours of the current fragment. + float lumaDown = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(0,-1)).rgb); + float lumaUp = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(0,1)).rgb); + float lumaLeft = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(-1,0)).rgb); + float lumaRight = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(1,0)).rgb); + + // Find the maximum and minimum luma around the current fragment. + float lumaMin = min(lumaCenter, min(min(lumaDown, lumaUp), min(lumaLeft, lumaRight))); + float lumaMax = max(lumaCenter, max(max(lumaDown, lumaUp), max(lumaLeft, lumaRight))); + + // Compute the delta. + float lumaRange = lumaMax - lumaMin; + + // If the luma variation is lower that a threshold (or if we are in a really dark area), + // we are not on an edge, don't perform any AA. + if (lumaRange < max(EDGE_THRESHOLD_MIN,lumaMax * EDGE_THRESHOLD_MAX)) { + aaFinalColor = colorCenter; + return; + } + + // ============================ + // Estimating the gradient: + // ============================ + // Query the 4 remaining corners lumas. + float lumaDownLeft = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(-1,-1)).rgb); + float lumaUpRight = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(1,1)).rgb); + float lumaUpLeft = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(-1,1)).rgb); + float lumaDownRight = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(1,-1)).rgb); + + // Combine the four edges lumas (using intermediary variables for future computations + // with the same values). + float lumaDownUp = lumaDown + lumaUp; + float lumaLeftRight = lumaLeft + lumaRight; + + // Same for corners + float lumaLeftCorners = lumaDownLeft + lumaUpLeft; + float lumaDownCorners = lumaDownLeft + lumaDownRight; + float lumaRightCorners = lumaDownRight + lumaUpRight; + float lumaUpCorners = lumaUpRight + lumaUpLeft; + + // Compute an estimation of the gradient along the horizontal and vertical axis. + float edgeHorizontal = abs(-2.0 * lumaLeft + lumaLeftCorners) + + abs(-2.0 * lumaCenter + lumaDownUp ) * 2.0 + abs(-2.0 * lumaRight + lumaRightCorners); + float edgeVertical = abs(-2.0 * lumaUp + lumaUpCorners) + + abs(-2.0 * lumaCenter + lumaLeftRight) * 2.0 + abs(-2.0 * lumaDown + lumaDownCorners); + + // Is the local edge horizontal or vertical ? + bool isHorizontal = (edgeHorizontal >= edgeVertical); + + // ============================ + // Choosing Edge Orientation: + // ============================ + // Select the two neighboring texels lumas in the opposite direction to the local edge. + float luma1 = isHorizontal ? lumaDown : lumaLeft; + float luma2 = isHorizontal ? lumaUp : lumaRight; + // Compute gradients in this direction. + float gradient1 = luma1 - lumaCenter; + float gradient2 = luma2 - lumaCenter; + + // Which direction is the steepest ? + bool is1Steepest = abs(gradient1) >= abs(gradient2); + + // Gradient in the corresponding direction, normalized. + float gradientScaled = 0.25 * max(abs(gradient1), abs(gradient2)); + + // Choose the step size (one pixel) according to the edge direction. + float stepLength = isHorizontal ? inverseScreenSize.y : inverseScreenSize.x; + + // Average luma in the correct direction. + float lumaLocalAverage = 0.0; + + if (is1Steepest) { + // Switch the direction + stepLength = - stepLength; + lumaLocalAverage = 0.5 * (luma1 + lumaCenter); + } else { + lumaLocalAverage = 0.5 * (luma2 + lumaCenter); + } + + // Shift UV in the correct direction by half a pixel. + vec2 currentUv = texCoord; + if (isHorizontal) { + currentUv.y += stepLength * 0.5; + } else { + currentUv.x += stepLength * 0.5; + } + + // ============================ + // Iterations: + // ============================ + // Compute offset (for each iteration step) in the right direction. + vec2 offset = isHorizontal ? vec2(inverseScreenSize.x, 0.0) : vec2(0.0, inverseScreenSize.y); + + // Compute UVs to explore on each side of the edge, orthogonally. + // The QUALITY allows us to step faster. + vec2 uv1 = currentUv - offset; + vec2 uv2 = currentUv + offset; + + // Read the lumas at both current extremities of the exploration segment, + // and compute the delta wrt to the local average luma. + float lumaEnd1 = rgb2luma(texture(renderedTexture, uv1).rgb); + float lumaEnd2 = rgb2luma(texture(renderedTexture, uv2).rgb); + lumaEnd1 -= lumaLocalAverage; + lumaEnd2 -= lumaLocalAverage; + + // If the luma deltas at the current extremities are larger than the local gradient, + // we have reached the side of the edge. + bool reached1 = abs(lumaEnd1) >= gradientScaled; + bool reached2 = abs(lumaEnd2) >= gradientScaled; + bool reachedBoth = reached1 && reached2; + + // If the side is not reached, we continue to explore in this direction. + if (!reached1) { + uv1 -= offset; + } + + if (!reached2) { + uv2 += offset; + } + + // If both sides have not been reached, continue to explore. + if (!reachedBoth) { + for (int i = 2; i < ITERATIONS; i++) { + // If needed, read luma in 1st direction, compute delta. + if (!reached1) { + lumaEnd1 = rgb2luma(texture(renderedTexture, uv1).rgb); + lumaEnd1 = lumaEnd1 - lumaLocalAverage; + } + // If needed, read luma in opposite direction, compute delta. + if (!reached2) { + lumaEnd2 = rgb2luma(texture(renderedTexture, uv2).rgb); + lumaEnd2 = lumaEnd2 - lumaLocalAverage; + } + // If the luma deltas at the current extremities is larger than + // the local gradient, we have reached the side of the edge. + reached1 = abs(lumaEnd1) >= gradientScaled; + reached2 = abs(lumaEnd2) >= gradientScaled; + reachedBoth = reached1 && reached2; + + // If the side is not reached, we continue to explore in this direction, + // with a variable quality. + if (!reached1) { + uv1 -= offset * QUALITY[i]; + } + + if (!reached2) { + uv2 += offset * QUALITY[i]; + } + + // If both sides have been reached, stop the exploration. + if (reachedBoth) { + break; + } + } + } + + // ============================ + // Estimating the offset: + // ============================ + // Compute the distances to each extremity of the edge. + float distance1 = isHorizontal ? (texCoord.x - uv1.x) : (texCoord.y - uv1.y); + float distance2 = isHorizontal ? (uv2.x - texCoord.x) : (uv2.y - texCoord.y); + + // In which direction is the extremity of the edge closer ? + bool isDirection1 = distance1 < distance2; + float distanceFinal = min(distance1, distance2); + + // Length of the edge. + float edgeThickness = (distance1 + distance2); + + // UV offset: read in the direction of the closest side of the edge. + float pixelOffset = - distanceFinal / edgeThickness + 0.5; + + // Is the luma at center smaller than the local average ? + bool isLumaCenterSmaller = lumaCenter < lumaLocalAverage; + + // If the luma at center is smaller than at its neighbour, the delta luma at + // each end should be positive (same variation). + // (in the direction of the closer side of the edge.) + bool correctVariation = ((isDirection1 ? lumaEnd1 : lumaEnd2) < 0.0) != isLumaCenterSmaller; + + // If the luma variation is incorrect, do not offset. + float finalOffset = correctVariation ? pixelOffset : 0.0; + + // ============================ + // Subpixel antialiasing: + // ============================ + // Sub-pixel shifting + // Full weighted average of the luma over the 3x3 neighborhood. + float lumaAverage = (1.0/12.0) * (2.0 * (lumaDownUp + lumaLeftRight) + + lumaLeftCorners + lumaRightCorners); + // Ratio of the delta between the global average and the center luma, over the luma range in the 3x3 neighborhood. + float subPixelOffset1 = clamp(abs(lumaAverage - lumaCenter) / lumaRange, 0.0, 1.0); + float subPixelOffset2 = (-2.0 * subPixelOffset1 + 3.0) * subPixelOffset1 * subPixelOffset1; + // Compute a sub-pixel offset based on this delta. + float subPixelOffsetFinal = subPixelOffset2 * subPixelOffset2 * SUBPIXEL_QUALITY; + + // Pick the biggest of the two offsets. + finalOffset = max(finalOffset, subPixelOffsetFinal); + + // Compute the final UV coordinates. + vec2 finalUv = texCoord; + if (isHorizontal) { + finalUv.y += finalOffset * stepLength; + } else { + finalUv.x += finalOffset * stepLength; + } + + // Read the color at the new UV coordinates, and use it. + aaFinalColor = texture(renderedTexture, finalUv); +} \ No newline at end of file diff --git a/shaders/framebuffer/fxaa.vert b/shaders/framebuffer/fxaa.vert new file mode 100644 index 0000000000..f737e51882 --- /dev/null +++ b/shaders/framebuffer/fxaa.vert @@ -0,0 +1,33 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2019 * + * * + * 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) in vec4 position; +out vec2 texCoord; + +void main() { + texCoord = 0.5 + position.xy * 0.5; + gl_Position = position; +} diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 61f23be178..00f9f4f9e7 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -59,6 +59,10 @@ namespace { "Hue", "Saturation", "Value", "nAaSamples" }; + constexpr const std::array FXAAUniformNames = { + "renderedTexture", "inverseScreenSize" + }; + constexpr const char* ExitFragmentShaderPath = "${SHADERS}/framebuffer/exitframebuffer.frag"; constexpr const char* RaycastFragmentShaderPath = @@ -149,6 +153,10 @@ void FramebufferRenderer::initialize() { glGenFramebuffers(1, &_hdrBuffers._hdrFilteringFramebuffer); glGenTextures(1, &_hdrBuffers._hdrFilteringTexture); + // FXAA Buffers + glGenFramebuffers(1, &_fxaaBuffers._fxaaFramebuffer); + glGenTextures(1, &_fxaaBuffers._fxaaTexture); + // Allocate Textures/Buffers Memory updateResolution(); @@ -266,9 +274,27 @@ void FramebufferRenderer::initialize() { LERROR("HDR/Filtering framebuffer is not complete"); } + //===================================// + //========== FXAA Buffers =========// + //===================================// + glBindFramebuffer(GL_FRAMEBUFFER, _fxaaBuffers._fxaaFramebuffer); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + _fxaaBuffers._fxaaTexture, + 0 + ); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LERROR("FXAA framebuffer is not complete"); + } + // JCC: Moved to here to avoid NVidia: "Program/shader state performance warning" // Building programs updateHDRAndFiltering(); + updateFXAA(); updateDeferredcastData(); _dirtyMsaaSamplingPattern = true; @@ -292,6 +318,11 @@ void FramebufferRenderer::initialize() { _hdrUniformCache, HDRUniformNames ); + ghoul::opengl::updateUniformLocations( + *_fxaaProgram, + _fxaaUniformCache, + FXAAUniformNames + ); global::raycasterManager.addListener(*this); global::deferredcasterManager.addListener(*this); @@ -307,12 +338,14 @@ void FramebufferRenderer::deinitialize() { glDeleteFramebuffers(1, &_gBuffers._framebuffer); glDeleteFramebuffers(1, &_exitFramebuffer); glDeleteFramebuffers(1, &_hdrBuffers._hdrFilteringFramebuffer); + glDeleteFramebuffers(1, &_fxaaBuffers._fxaaFramebuffer); glDeleteFramebuffers(1, &_pingPongBuffers.framebuffer); glDeleteTextures(1, &_gBuffers._colorTexture); glDeleteTextures(1, &_gBuffers._depthTexture); glDeleteTextures(1, &_hdrBuffers._hdrFilteringTexture); + glDeleteTextures(1, &_fxaaBuffers._fxaaTexture); glDeleteTextures(1, &_gBuffers._positionTexture); glDeleteTextures(1, &_gBuffers._normalTexture); @@ -397,6 +430,40 @@ void FramebufferRenderer::applyTMO(float blackoutFactor) { _hdrFilteringProgram->deactivate(); } +void FramebufferRenderer::applyFXAA() { + const bool doPerformanceMeasurements = global::performanceManager.isEnabled(); + std::unique_ptr perfInternal; + + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::FXAA" + ); + } + + _fxaaProgram->activate(); + + ghoul::opengl::TextureUnit renderedTextureUnit; + renderedTextureUnit.activate(); + glBindTexture( + GL_TEXTURE_2D, + _fxaaBuffers._fxaaTexture + ); + + _fxaaProgram->setUniform( + _fxaaUniformCache.renderedTexture, + renderedTextureUnit + ); + + glm::vec2 inverseScreenSize(1.f/_resolution.x, 1.f/_resolution.y); + _fxaaProgram->setUniform(_fxaaUniformCache.inverseScreenSize, inverseScreenSize); + + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + _fxaaProgram->deactivate(); +} + void FramebufferRenderer::update() { if (_dirtyResolution) { updateResolution(); @@ -429,6 +496,16 @@ void FramebufferRenderer::update() { ); } + if (_fxaaProgram->isDirty()) { + _fxaaProgram->rebuildFromFile(); + + ghoul::opengl::updateUniformLocations( + *_fxaaProgram, + _fxaaUniformCache, + FXAAUniformNames + ); + } + using K = VolumeRaycaster*; using V = std::unique_ptr; for (const std::pair& program : _exitPrograms) { @@ -551,6 +628,24 @@ void FramebufferRenderer::updateResolution() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // FXAA + glBindTexture(GL_TEXTURE_2D, _fxaaBuffers._fxaaTexture); + + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA, + _resolution.x, + _resolution.y, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // Volume Rendering Textures glBindTexture(GL_TEXTURE_2D, _exitColorTexture); glTexImage2D( @@ -723,6 +818,17 @@ void FramebufferRenderer::updateHDRAndFiltering() { //_hdrFilteringProgram->setIgnoreUniformLocationError(IgnoreError::Yes); } +void FramebufferRenderer::updateFXAA() { + _fxaaProgram = ghoul::opengl::ProgramObject::Build( + "FXAA Program", + absPath("${SHADERS}/framebuffer/fxaa.vert"), + absPath("${SHADERS}/framebuffer/fxaa.frag") + ); + using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; + //_fxaaProgram->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); + //_fxaaProgram->setIgnoreUniformLocationError(IgnoreError::Yes); +} + void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFactor) { // Set OpenGL default rendering state glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO); @@ -811,9 +917,15 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac // Disabling depth test for filtering and hdr glDisable(GL_DEPTH_TEST); - // 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); + if (_enableFXAA) { + glBindFramebuffer(GL_FRAMEBUFFER, _fxaaBuffers._fxaaFramebuffer); + } + 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); + } + glViewport(0, 0, _resolution.x, _resolution.y); if (_disableHDR) { @@ -823,6 +935,12 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac // Apply the selected TMO on the results and resolve the result for the default FBO applyTMO(blackoutFactor); } + + if (_enableFXAA) { + glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); + applyFXAA(); + } + } void FramebufferRenderer::performRaycasterTasks(const std::vector& tasks) { @@ -1052,6 +1170,10 @@ int FramebufferRenderer::nAaSamples() const { return _nAaSamples; } +void FramebufferRenderer::enableFXAA(bool enable) { + _enableFXAA = std::move(enable); +} + void FramebufferRenderer::updateRendererData() { ghoul::Dictionary dict; dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath)); diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index a0e7d11e3d..d5da7e8abc 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -253,6 +253,12 @@ namespace { "The blackout factor of the rendering. This can be used for fading in or out the " "rendering window" }; + + constexpr openspace::properties::Property::PropertyInfo FXAAInfo = { + "FXAA", + "Enable FXAA", + "Enable FXAA" + }; } // namespace @@ -274,6 +280,7 @@ RenderEngine::RenderEngine() , _disableMasterRendering(DisableMasterInfo, false) , _globalBlackOutFactor(GlobalBlackoutFactorInfo, 1.f, 0.f, 1.f) , _nAaSamples(AaSamplesInfo, 4, 1, 8) + , _enableFXAA(FXAAInfo, false) , _disableHDRPipeline(DisableHDRPipelineInfo, false) , _hdrExposure(HDRExposureInfo, 3.7f, 0.01f, 10.0f) , _gamma(GammaInfo, 0.86f, 0.01f, 5.0f) @@ -317,6 +324,13 @@ RenderEngine::RenderEngine() }); addProperty(_nAaSamples); + _enableFXAA.onChange([this]() { + if (_renderer) { + _renderer->enableFXAA(_enableFXAA); + } + }); + addProperty(_enableFXAA); + _disableHDRPipeline.onChange([this]() { if (_renderer) { _renderer->disableHDR(_disableHDRPipeline); From bb44ed59d1caef8c70dd4b55558a17dc185d6305 Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Sun, 18 Aug 2019 15:59:17 -0400 Subject: [PATCH 2/8] Ultra fast OpenSpace (still need some cleanning here and there). :-p --- .../openspace/rendering/framebufferrenderer.h | 3 +- .../shaders/atmosphere_deferred_fs.glsl | 271 +++++++++--------- .../shaders/atmosphere_deferred_vs.glsl | 2 + openspace.cfg | 2 +- shaders/framebuffer/hdrAndFiltering.frag | 11 +- shaders/framebuffer/renderframebuffer.frag | 1 - src/rendering/framebufferrenderer.cpp | 193 ++++++------- 7 files changed, 229 insertions(+), 254 deletions(-) diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index 5b5e173566..c7d2204276 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -204,8 +204,7 @@ private: bool _dirtyDeferredcastData; bool _dirtyRaycastData; bool _dirtyResolution; - bool _dirtyMsaaSamplingPattern; - + glm::ivec2 _resolution = glm::ivec2(0); int _nAaSamples; bool _enableFXAA = false; diff --git a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl index d8d1d4e28b..920e278a4d 100644 --- a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl +++ b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl @@ -65,15 +65,16 @@ out vec4 renderTarget; in vec3 interpolatedNDCPos; +in vec2 texCoord; uniform int nAaSamples; uniform int cullAtmosphere; uniform sampler2D irradianceTexture; uniform sampler3D inscatterTexture; -uniform sampler2DMS mainPositionTexture; -uniform sampler2DMS mainNormalTexture; -uniform sampler2DMS mainColorTexture; +uniform sampler2D mainPositionTexture; +uniform sampler2D mainNormalTexture; +uniform sampler2D mainColorTexture; uniform dmat4 dInverseModelTransformMatrix; uniform dmat4 dModelTransformMatrix; @@ -230,7 +231,7 @@ bool dAtmosphereIntersection(const dvec3 planetPosition, const dRay ray, const d * This method avoids matrices multiplications * wherever is possible. */ -void dCalculateRayRenderableGlobe(in int mssaSample, out dRay ray, +void dCalculateRayRenderableGlobe(out dRay ray, out dvec4 planetPositionObjectCoords, out dvec4 cameraPositionInObject) { dvec4 clipCoords = dvec4(interpolatedNDCPos.xy, 1.0, 1.0); @@ -529,8 +530,6 @@ vec3 sunColor(const vec3 x, const float t, const vec3 v, const vec3 s, const flo } void main() { - ivec2 fragCoords = ivec2(gl_FragCoord); - if (cullAtmosphere == 0) { vec4 atmosphereFinalColor = vec4(0.0f); int nSamples = 1; @@ -538,153 +537,141 @@ void main() { // First we determine if the pixel is complex (different fragments on it) bool complex = false; vec4 oldColor, currentColor; - vec4 colorArray[16]; + vec4 colorTexture; - colorArray[0] = texelFetch(mainColorTexture, fragCoords, 0); - for (int i = 1; i < nAaSamples; i++) { - colorArray[i] = texelFetch(mainColorTexture, fragCoords, i); - if (colorArray[i] != colorArray[i-1]) { - complex = true; - } - } - nSamples = complex ? nAaSamples / 2 : 1; + colorTexture = texture(mainColorTexture, texCoord); - for (int i = 0; i < nSamples; i++) { - // Color from G-Buffer - vec4 color = colorArray[i]; - // Ray in object space - dRay ray; - dvec4 planetPositionObjectCoords = dvec4(0.0); - dvec4 cameraPositionInObject = dvec4(0.0); + // Color from G-Buffer + vec4 color = colorTexture; + // Ray in object space + dRay ray; + dvec4 planetPositionObjectCoords = dvec4(0.0); + dvec4 cameraPositionInObject = dvec4(0.0); + + // Get the ray from camera to atm in object space + dCalculateRayRenderableGlobe(ray, planetPositionObjectCoords, + cameraPositionInObject); + + bool insideATM = false; + double offset = 0.0; // in Km + double maxLength = 0.0; // in Km + + bool intersectATM = false; + + intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, ray, + Rt - (ATM_EPSILON * 0.001), insideATM, offset, maxLength); - // Get the ray from camera to atm in object space - dCalculateRayRenderableGlobe(i * 3, ray, planetPositionObjectCoords, - cameraPositionInObject); - - bool insideATM = false; - double offset = 0.0; // in Km - double maxLength = 0.0; // in Km + if ( intersectATM ) { + // Now we check is if the atmosphere is occluded, i.e., if the distance to the pixel + // in the G-Buffer positions is less than the distance to the atmosphere then the atmosphere + // is occluded + // Fragments positions into G-Buffer are written in SGCT Eye Space (View plus Camera Rig Coords) + // when using their positions later, one must convert them to the planet's coords + + // Get data from G-Buffer + vec4 normal = texture(mainNormalTexture, texCoord); + // Data in the mainPositionTexture are written in view space (view plus camera rig) + vec4 position = texture(mainPositionTexture, texCoord); - bool intersectATM = false; + // OS Eye to World coords + dvec4 positionWorldCoords = dSGCTViewToWorldMatrix * position; - intersectATM = dAtmosphereIntersection(planetPositionObjectCoords.xyz, ray, - Rt - (ATM_EPSILON * 0.001), insideATM, offset, maxLength); - - if ( intersectATM ) { - // Now we check is if the atmosphere is occluded, i.e., if the distance to the pixel - // in the G-Buffer positions is less than the distance to the atmosphere then the atmosphere - // is occluded - // Fragments positions into G-Buffer are written in SGCT Eye Space (View plus Camera Rig Coords) - // when using their positions later, one must convert them to the planet's coords - - // Get data from G-Buffer - vec4 normal = texelFetch(mainNormalTexture, fragCoords, i); - // Data in the mainPositionTexture are written in view space (view plus camera rig) - vec4 position = texelFetch(mainPositionTexture, fragCoords, i); + // World to Object (Normal and Position in meters) + dvec4 positionObjectsCoords = dInverseModelTransformMatrix * positionWorldCoords; - // OS Eye to World coords - dvec4 positionWorldCoords = dSGCTViewToWorldMatrix * position; + + // Distance of the pixel in the gBuffer to the observer + // JCC (12/12/2017): AMD distance function is buggy. + //double pixelDepth = distance(cameraPositionInObject.xyz, positionObjectsCoords.xyz); + double pixelDepth = length(cameraPositionInObject.xyz - positionObjectsCoords.xyz); + + // JCC (12/13/2017): Trick to remove floating error in texture. + // We see a squared noise on planet's surface when seeing the planet + // from far away. + float dC = float(length(cameraPositionInObject.xyz)); + float x1 = 1e8; + if (dC > x1) { + pixelDepth += 1000.0; + float alpha = 1000.0; + float beta = 1000000.0; + float x2 = 1e9; + float diffGreek = beta - alpha; + float diffDist = x2 - x1; + float varA = diffGreek/diffDist; + float varB = (alpha - varA * x1); + pixelDepth += double(varA * dC + varB); + } - // World to Object (Normal and Position in meters) - dvec4 positionObjectsCoords = dInverseModelTransformMatrix * positionWorldCoords; - - - // Distance of the pixel in the gBuffer to the observer - // JCC (12/12/2017): AMD distance function is buggy. - //double pixelDepth = distance(cameraPositionInObject.xyz, positionObjectsCoords.xyz); - double pixelDepth = length(cameraPositionInObject.xyz - positionObjectsCoords.xyz); - - // JCC (12/13/2017): Trick to remove floating error in texture. - // We see a squared noise on planet's surface when seeing the planet - // from far away. - float dC = float(length(cameraPositionInObject.xyz)); - float x1 = 1e8; - if (dC > x1) { - pixelDepth += 1000.0; - float alpha = 1000.0; - float beta = 1000000.0; - float x2 = 1e9; - float diffGreek = beta - alpha; - float diffDist = x2 - x1; - float varA = diffGreek/diffDist; - float varB = (alpha - varA * x1); - pixelDepth += double(varA * dC + varB); - } - - // All calculations are done in Km: - pixelDepth *= 0.001; - positionObjectsCoords.xyz *= 0.001; - - if (pixelDepth < offset) { - // ATM Occluded - Something in fron of ATM. - atmosphereFinalColor += color; - } else { - // Following paper nomenclature - double t = offset; - vec3 attenuation; - - // Moving observer from camera location to top atmosphere - // If the observer is already inside the atm, offset = 0.0 - // and no changes at all. - vec3 x = vec3(ray.origin.xyz + t*ray.direction.xyz); - float r = 0.0f;//length(x); - vec3 v = vec3(ray.direction.xyz); - float mu = 0.0f;//dot(x, v) / r; - vec3 s = vec3(sunDirectionObj); - float tF = float(maxLength - t); - - // Because we may move the camera origin to the top of atmosphere - // we also need to adjust the pixelDepth for tdCalculateRayRenderableGlobe' offset so the - // next comparison with the planet's ground make sense: - pixelDepth -= offset; - - dvec4 onATMPos = dModelTransformMatrix * dvec4(x * 1000.0, 1.0); - vec4 eclipseShadowATM = calcShadow(shadowDataArray, onATMPos.xyz, false); - float sunIntensityInscatter = sunRadiance * eclipseShadowATM.x; - - float irradianceFactor = 0.0; - - bool groundHit = false; - vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v, - s, r, mu, attenuation, - vec3(positionObjectsCoords.xyz), - groundHit, maxLength, pixelDepth, - color, sunIntensityInscatter); - vec3 groundColorV = vec3(0.0); - vec3 sunColorV = vec3(0.0); - if (groundHit) { - vec4 eclipseShadowPlanet = calcShadow(shadowDataArray, positionWorldCoords.xyz, true); - float sunIntensityGround = sunRadiance * eclipseShadowPlanet.x; - groundColorV = groundColor(x, tF, v, s, r, mu, attenuation, - color, normal.xyz, irradianceFactor, - normal.a, sunIntensityGround); - } else { - // In order to get better performance, we are not tracing - // multiple rays per pixel when the ray doesn't intersect - // the ground. - sunColorV = sunColor(x, tF, v, s, r, mu, irradianceFactor); - } - - // Final Color of ATM plus terrain: - vec4 finalRadiance = vec4(inscatterColor + groundColorV + sunColorV, 1.0); - - atmosphereFinalColor += finalRadiance; - } - } - else { // no intersection - // Buffer color + // All calculations are done in Km: + pixelDepth *= 0.001; + positionObjectsCoords.xyz *= 0.001; + + if (pixelDepth < offset) { + // ATM Occluded - Something in fron of ATM. atmosphereFinalColor += color; - } - } + } else { + // Following paper nomenclature + double t = offset; + vec3 attenuation; - renderTarget = atmosphereFinalColor / float(nSamples); + // Moving observer from camera location to top atmosphere + // If the observer is already inside the atm, offset = 0.0 + // and no changes at all. + vec3 x = vec3(ray.origin.xyz + t*ray.direction.xyz); + float r = 0.0f;//length(x); + vec3 v = vec3(ray.direction.xyz); + float mu = 0.0f;//dot(x, v) / r; + vec3 s = vec3(sunDirectionObj); + float tF = float(maxLength - t); + + // Because we may move the camera origin to the top of atmosphere + // we also need to adjust the pixelDepth for tdCalculateRayRenderableGlobe' offset so the + // next comparison with the planet's ground make sense: + pixelDepth -= offset; + + dvec4 onATMPos = dModelTransformMatrix * dvec4(x * 1000.0, 1.0); + vec4 eclipseShadowATM = calcShadow(shadowDataArray, onATMPos.xyz, false); + float sunIntensityInscatter = sunRadiance * eclipseShadowATM.x; + + float irradianceFactor = 0.0; + + bool groundHit = false; + vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v, + s, r, mu, attenuation, + vec3(positionObjectsCoords.xyz), + groundHit, maxLength, pixelDepth, + color, sunIntensityInscatter); + vec3 groundColorV = vec3(0.0); + vec3 sunColorV = vec3(0.0); + if (groundHit) { + vec4 eclipseShadowPlanet = calcShadow(shadowDataArray, positionWorldCoords.xyz, true); + float sunIntensityGround = sunRadiance * eclipseShadowPlanet.x; + groundColorV = groundColor(x, tF, v, s, r, mu, attenuation, + color, normal.xyz, irradianceFactor, + normal.a, sunIntensityGround); + } else { + // In order to get better performance, we are not tracing + // multiple rays per pixel when the ray doesn't intersect + // the ground. + sunColorV = sunColor(x, tF, v, s, r, mu, irradianceFactor); + } + + // Final Color of ATM plus terrain: + vec4 finalRadiance = vec4(inscatterColor + groundColorV + sunColorV, 1.0); + + atmosphereFinalColor += finalRadiance; + } + } + else { // no intersection + // Buffer color + atmosphereFinalColor += color; + } + + + renderTarget = atmosphereFinalColor; } else { // culling - vec4 bColor = vec4(0.0f); - for (int f = 0; f < nAaSamples; f++) { - bColor += texelFetch(mainColorTexture, fragCoords, f); - } - bColor /= float(nAaSamples); + vec4 bColor = texture(mainColorTexture, texCoord); renderTarget = bColor; } } diff --git a/modules/atmosphere/shaders/atmosphere_deferred_vs.glsl b/modules/atmosphere/shaders/atmosphere_deferred_vs.glsl index 52cd01cb6e..33f0eb1651 100644 --- a/modules/atmosphere/shaders/atmosphere_deferred_vs.glsl +++ b/modules/atmosphere/shaders/atmosphere_deferred_vs.glsl @@ -27,9 +27,11 @@ layout(location = 0) in vec4 in_position; out vec3 interpolatedNDCPos; +out vec2 texCoord; void main() { + texCoord = 0.5 + in_position.xy * 0.5; interpolatedNDCPos = in_position.xyz; gl_Position = in_position; } diff --git a/openspace.cfg b/openspace.cfg index 85daf27146..c7e7bb63a0 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -166,7 +166,7 @@ LoadingScreen = { ShowNodeNames = true, ShowProgressbar = false } -CheckOpenGLState = false +CheckOpenGLState = true LogEachOpenGLCall = false ShutdownCountdown = 3 diff --git a/shaders/framebuffer/hdrAndFiltering.frag b/shaders/framebuffer/hdrAndFiltering.frag index cd943e2e14..997c68780a 100644 --- a/shaders/framebuffer/hdrAndFiltering.frag +++ b/shaders/framebuffer/hdrAndFiltering.frag @@ -40,19 +40,12 @@ uniform float Value; uniform float Lightness; uniform int nAaSamples; -uniform sampler2DMS hdrFeedingTexture; +uniform sampler2D hdrFeedingTexture; in vec2 texCoord; void main() { - vec4 color = vec4(0.0); - - // Resolving... - for (int i = 0; i < nAaSamples; i++) { - color += texelFetch(hdrFeedingTexture, ivec2(gl_FragCoord), i); - } - - color /= nAaSamples; + vec4 color = texture(hdrFeedingTexture, texCoord); color.rgb *= blackoutFactor; // Applies TMO diff --git a/shaders/framebuffer/renderframebuffer.frag b/shaders/framebuffer/renderframebuffer.frag index e7e18698b5..a20d685f4e 100644 --- a/shaders/framebuffer/renderframebuffer.frag +++ b/shaders/framebuffer/renderframebuffer.frag @@ -33,7 +33,6 @@ layout(location = 0) out vec4 _out_color_; layout(location = 1) out vec4 gPosition; layout(location = 2) out vec4 gNormal; -layout(location = 3) out vec4 filterBuffer; void main() { Fragment f = getFragment(); diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 00f9f4f9e7..aebdab6991 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -167,31 +167,27 @@ void FramebufferRenderer::initialize() { //===== GBuffers Buffers =====// //==============================// glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers._framebuffer); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._colorTexture, 0 ); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, - GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._positionTexture, 0 ); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, - GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._normalTexture, 0 ); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._depthTexture, 0 ); @@ -205,24 +201,21 @@ void FramebufferRenderer::initialize() { //===== PingPong Buffers =====// //==============================// glBindFramebuffer(GL_FRAMEBUFFER, _pingPongBuffers.framebuffer); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D_MULTISAMPLE, _pingPongBuffers.colorTexture[0], 0 ); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, - GL_TEXTURE_2D_MULTISAMPLE, _pingPongBuffers.colorTexture[1], 0 ); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._depthTexture, 0 ); @@ -237,17 +230,15 @@ void FramebufferRenderer::initialize() { //======================================// // Builds Exit Framebuffer glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, _exitColorTexture, 0 ); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, _exitDepthTexture, 0 ); @@ -261,10 +252,9 @@ void FramebufferRenderer::initialize() { //===== HDR/Filtering Buffers =====// //===================================// glBindFramebuffer(GL_FRAMEBUFFER, _hdrBuffers._hdrFilteringFramebuffer); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, _hdrBuffers._hdrFilteringTexture, 0 ); @@ -278,10 +268,9 @@ void FramebufferRenderer::initialize() { //========== FXAA Buffers =========// //===================================// glBindFramebuffer(GL_FRAMEBUFFER, _fxaaBuffers._fxaaFramebuffer); - glFramebufferTexture2D( + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, _fxaaBuffers._fxaaTexture, 0 ); @@ -297,8 +286,6 @@ void FramebufferRenderer::initialize() { updateFXAA(); updateDeferredcastData(); - _dirtyMsaaSamplingPattern = true; - // Sets back to default FBO glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); @@ -404,7 +391,7 @@ void FramebufferRenderer::applyTMO(float blackoutFactor) { ghoul::opengl::TextureUnit hdrFeedingTextureUnit; hdrFeedingTextureUnit.activate(); glBindTexture( - GL_TEXTURE_2D_MULTISAMPLE, + GL_TEXTURE_2D, _pingPongBuffers.colorTexture[_pingPongIndex] ); @@ -420,8 +407,6 @@ void FramebufferRenderer::applyTMO(float blackoutFactor) { _hdrFilteringProgram->setUniform(_hdrUniformCache.Hue, _hue); _hdrFilteringProgram->setUniform(_hdrUniformCache.Saturation, _saturation); _hdrFilteringProgram->setUniform(_hdrUniformCache.Value, _value); - _hdrFilteringProgram->setUniform(_hdrUniformCache.nAaSamples, _nAaSamples); - glBindVertexArray(_screenQuad); glDrawArrays(GL_TRIANGLES, 0, 6); @@ -558,61 +543,7 @@ void FramebufferRenderer::update() { } void FramebufferRenderer::updateResolution() { - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._colorTexture); - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - _resolution.x, - _resolution.y, - GL_TRUE - ); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._positionTexture); - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - _resolution.x, - _resolution.y, - GL_TRUE - ); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._normalTexture); - - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - _resolution.x, - _resolution.y, - GL_TRUE - ); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._depthTexture); - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_DEPTH_COMPONENT32F, - _resolution.x, - _resolution.y, - GL_TRUE - ); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _pingPongBuffers.colorTexture[1]); - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - _resolution.x, - _resolution.y, - GL_TRUE - ); - - - // HDR / Filtering - glBindTexture(GL_TEXTURE_2D, _hdrBuffers._hdrFilteringTexture); - + glBindTexture(GL_TEXTURE_2D, _gBuffers._colorTexture); glTexImage2D( GL_TEXTURE_2D, 0, @@ -624,13 +555,87 @@ void FramebufferRenderer::updateResolution() { GL_FLOAT, nullptr ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, _gBuffers._positionTexture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + _resolution.x, + _resolution.y, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, _gBuffers._normalTexture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + _resolution.x, + _resolution.y, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, _gBuffers._depthTexture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT32F, + _resolution.x, + _resolution.y, + 0, + GL_DEPTH_COMPONENT, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, _pingPongBuffers.colorTexture[1]); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + _resolution.x, + _resolution.y, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + // HDR / Filtering + glBindTexture(GL_TEXTURE_2D, _hdrBuffers._hdrFilteringTexture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + _resolution.x, + _resolution.y, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // FXAA glBindTexture(GL_TEXTURE_2D, _fxaaBuffers._fxaaTexture); - glTexImage2D( GL_TEXTURE_2D, 0, @@ -642,7 +647,6 @@ void FramebufferRenderer::updateResolution() { GL_FLOAT, nullptr ); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -928,13 +932,8 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac glViewport(0, 0, _resolution.x, _resolution.y); - if (_disableHDR) { - resolveMSAA(blackoutFactor); - } - else { - // Apply the selected TMO on the results and resolve the result for the default FBO - applyTMO(blackoutFactor); - } + // Apply the selected TMO on the results and resolve the result for the default FBO + applyTMO(blackoutFactor); if (_enableFXAA) { glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); @@ -1003,7 +1002,7 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector ghoul::opengl::TextureUnit mainDepthTextureUnit; mainDepthTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._depthTexture); + glBindTexture(GL_TEXTURE_2D, _gBuffers._depthTexture); raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit); raycastProgram->setUniform("nAaSamples", _nAaSamples); @@ -1058,9 +1057,8 @@ void FramebufferRenderer::performDeferredTasks( // adding G-Buffer ghoul::opengl::TextureUnit mainDColorTextureUnit; mainDColorTextureUnit.activate(); - //glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._colorTexture); glBindTexture( - GL_TEXTURE_2D_MULTISAMPLE, + GL_TEXTURE_2D, _pingPongBuffers.colorTexture[fromIndex] ); deferredcastProgram->setUniform( @@ -1070,7 +1068,7 @@ void FramebufferRenderer::performDeferredTasks( ghoul::opengl::TextureUnit mainPositionTextureUnit; mainPositionTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._positionTexture); + glBindTexture(GL_TEXTURE_2D, _gBuffers._positionTexture); deferredcastProgram->setUniform( "mainPositionTexture", mainPositionTextureUnit @@ -1078,14 +1076,12 @@ void FramebufferRenderer::performDeferredTasks( ghoul::opengl::TextureUnit mainNormalTextureUnit; mainNormalTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._normalTexture); + glBindTexture(GL_TEXTURE_2D, _gBuffers._normalTexture); deferredcastProgram->setUniform( "mainNormalTexture", mainNormalTextureUnit ); - deferredcastProgram->setUniform("nAaSamples", _nAaSamples); - deferredcaster->preRaycast( deferredcasterTask.renderData, _deferredcastData[deferredcaster], @@ -1136,7 +1132,6 @@ void FramebufferRenderer::setNAaSamples(int nAaSamples) { LERROR("Framebuffer renderer does not support more than 8 MSAA samples."); _nAaSamples = 8; } - _dirtyMsaaSamplingPattern = true; } void FramebufferRenderer::disableHDR(bool disable) { From 1fb65887d22e9096a8f256e4aab44953ddaa951e Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Mon, 19 Aug 2019 10:39:48 -0400 Subject: [PATCH 3/8] Even faster... --- include/openspace/rendering/framebufferrenderer.h | 2 +- shaders/framebuffer/fxaa.frag | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index c7d2204276..2baa219a61 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -207,7 +207,7 @@ private: glm::ivec2 _resolution = glm::ivec2(0); int _nAaSamples; - bool _enableFXAA = false; + bool _enableFXAA = true; bool _disableHDR = false; float _hdrExposure = 3.7f; diff --git a/shaders/framebuffer/fxaa.frag b/shaders/framebuffer/fxaa.frag index 5cb4963b61..84a78bf0b6 100644 --- a/shaders/framebuffer/fxaa.frag +++ b/shaders/framebuffer/fxaa.frag @@ -30,6 +30,9 @@ #define SUBPIXEL_QUALITY 0.75f const float[12] QUALITY = {1.f, 1.f, 1.f, 1.f, 1.f, 1.5f, 2.f, 2.f, 2.f, 2.f, 4.f, 8.f}; +// const float[24] QUALITY = {2.f, 4.f, 6.f, 8.f, 10.f, 12.f, 12.f, 12.f, 12.f, 12.f, 14.f, 18.f, +// 18.f, 18.f, 18.f, 18.f, 18.f, 18.f, 18.f, 18.f, 18.f, 18.f, +// 18.f, 18.f}; layout (location = 0) out vec4 aaFinalColor; @@ -38,8 +41,9 @@ uniform sampler2D renderedTexture; in vec2 texCoord; +// Relative luminance float rgb2luma(vec3 rgb){ - return sqrt(dot(rgb, vec3(0.299, 0.587, 0.114))); + return dot(vec3(0.2126, 0.7152, 0.0722), rgb); } void main() { From 15d6586e0692e103016c8e47bc2f2083e3a7fec1 Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Mon, 19 Aug 2019 14:31:28 -0400 Subject: [PATCH 4/8] Get rid of MSAA GUI and updated framebuffer volume rendering (need more tests here). --- data/assets/default.scene | 1 + .../openspace/rendering/framebufferrenderer.h | 7 +-- include/openspace/rendering/renderengine.h | 1 - include/openspace/rendering/renderer.h | 2 - shaders/framebuffer/raycastframebuffer.frag | 36 ++++----------- src/rendering/framebufferrenderer.cpp | 46 ++----------------- src/rendering/renderengine.cpp | 21 +-------- 7 files changed, 19 insertions(+), 95 deletions(-) diff --git a/data/assets/default.scene b/data/assets/default.scene index 46e59bf846..e2e477f19b 100644 --- a/data/assets/default.scene +++ b/data/assets/default.scene @@ -1,4 +1,5 @@ asset.require('./base') +asset.require('examples/volume/toyvolume') local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index 2baa219a61..d5fab211fa 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -136,14 +136,12 @@ public: void updateFXAA(); void setResolution(glm::ivec2 res) override; - void setNAaSamples(int nAaSamples) override; void setHDRExposure(float hdrExposure) override; void setGamma(float gamma) override; void setHue(float hue) override; void setValue(float value) override; void setSaturation(float sat) override; - int nAaSamples() const override; void enableFXAA(bool enable) override; void disableHDR(bool disable) override; @@ -164,7 +162,6 @@ public: DeferredcasterListener::IsAttached isAttached) override; private: - void resolveMSAA(float blackoutFactor); void applyTMO(float blackoutFactor); void applyFXAA(); @@ -182,9 +179,9 @@ private: std::unique_ptr _resolveProgram; std::unique_ptr _fxaaProgram; - UniformCache(mainColorTexture, blackoutFactor, nAaSamples) _uniformCache; + UniformCache(mainColorTexture, blackoutFactor) _uniformCache; UniformCache(hdrFeedingTexture, blackoutFactor, hdrExposure, gamma, - Hue, Saturation, Value, nAaSamples) _hdrUniformCache; + Hue, Saturation, Value) _hdrUniformCache; UniformCache(renderedTexture, inverseScreenSize) _fxaaUniformCache; GLint _defaultFBO; diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 5ea7abcbde..992a28d011 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -207,7 +207,6 @@ private: properties::BoolProperty _disableMasterRendering; properties::FloatProperty _globalBlackOutFactor; - properties::IntProperty _nAaSamples; properties::BoolProperty _enableFXAA; diff --git a/include/openspace/rendering/renderer.h b/include/openspace/rendering/renderer.h index df2f1b3b67..9e018609fd 100644 --- a/include/openspace/rendering/renderer.h +++ b/include/openspace/rendering/renderer.h @@ -49,13 +49,11 @@ public: virtual void deinitialize() = 0; virtual void setResolution(glm::ivec2 res) = 0; - virtual void setNAaSamples(int nAaSamples) = 0; virtual void setHDRExposure(float hdrExposure) = 0; virtual void setGamma(float gamma) = 0; virtual void setHue(float hue) = 0; virtual void setValue(float value) = 0; virtual void setSaturation(float sat) = 0; - virtual int nAaSamples() const = 0; virtual void enableFXAA(bool enable) = 0; virtual void disableHDR(bool disable) = 0; diff --git a/shaders/framebuffer/raycastframebuffer.frag b/shaders/framebuffer/raycastframebuffer.frag index a4ee03faf4..f7271aadeb 100644 --- a/shaders/framebuffer/raycastframebuffer.frag +++ b/shaders/framebuffer/raycastframebuffer.frag @@ -26,7 +26,7 @@ uniform sampler2D exitColorTexture; uniform sampler2D exitDepthTexture; -uniform sampler2DMS mainDepthTexture; +uniform sampler2D mainDepthTexture; uniform bool insideRaycaster; uniform vec3 cameraPosInRaycaster; @@ -46,9 +46,6 @@ out vec4 finalColor; #define ALPHA_LIMIT 0.99 #define RAYCAST_MAX_STEPS 1000 -#define MAX_AA_SAMPLES 8 - -uniform int nAaSamples; #include <#{getEntryPath}> @@ -76,25 +73,12 @@ void main() { vec3 direction = normalize(diff); float raycastDepth = length(diff); - float raycastDepths[MAX_AA_SAMPLES]; - int i, j; float tmp; - for (i = 0; i < nAaSamples; i++) { - float geoDepth = denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), i).x); - float geoRatio = clamp((geoDepth - entryDepth) / (exitDepth - entryDepth), 0.0, 1.0); - raycastDepths[i] = geoRatio * raycastDepth; - } - - for(i = 1; i < nAaSamples; ++i) { - tmp = raycastDepths[i]; - for(j = i; j > 0 && tmp < raycastDepths[j - 1]; --j) { - raycastDepths[j] = raycastDepths[j-1]; - } - raycastDepths[j] = tmp; - } - + float geoDepth = denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), 0).x); + float geoRatio = clamp((geoDepth - entryDepth) / (exitDepth - entryDepth), 0.0, 1.0); + raycastDepth = geoRatio * raycastDepth; float currentDepth = 0.0; // todo: shorten depth if geometry is intersecting! @@ -106,20 +90,20 @@ void main() { float aaOpacity = 1.0; int sampleIndex = 0; - float opacityDecay = 1.0 / nAaSamples; + float opacityDecay = 1.0; vec3 accumulatedColor = vec3(0.0); vec3 accumulatedAlpha = vec3(0.0); - for (steps = 0; (accumulatedAlpha.r < ALPHA_LIMIT || accumulatedAlpha.g < ALPHA_LIMIT || accumulatedAlpha.b < ALPHA_LIMIT) && steps < RAYCAST_MAX_STEPS; ++steps) { - while (sampleIndex < nAaSamples && currentDepth + nextStepSize * jitterFactor > raycastDepths[sampleIndex]) { - sampleIndex++; + for (steps = 0; (accumulatedAlpha.r < ALPHA_LIMIT || accumulatedAlpha.g < ALPHA_LIMIT || + accumulatedAlpha.b < ALPHA_LIMIT) && steps < RAYCAST_MAX_STEPS; ++steps) { + if (currentDepth + nextStepSize * jitterFactor > raycastDepth) { aaOpacity -= opacityDecay; } bool shortStepSize = nextStepSize < raycastDepth / 10000000000.0; - if (sampleIndex >= nAaSamples || shortStepSize) { + if (shortStepSize) { break; } @@ -139,7 +123,7 @@ void main() { previousJitterDistance = currentStepSize - jitteredStepSize; - float maxStepSize = raycastDepths[nAaSamples - 1] - currentDepth; + float maxStepSize = raycastDepth - currentDepth; nextStepSize = min(nextStepSize, maxStepSize); diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index aebdab6991..c67f7d3945 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -50,13 +50,13 @@ namespace { constexpr const char* _loggerCat = "FramebufferRenderer"; - constexpr const std::array UniformNames = { - "mainColorTexture", "blackoutFactor", "nAaSamples" + constexpr const std::array UniformNames = { + "mainColorTexture", "blackoutFactor" }; - constexpr const std::array HDRUniformNames = { + constexpr const std::array HDRUniformNames = { "hdrFeedingTexture", "blackoutFactor", "hdrExposure", "gamma", - "Hue", "Saturation", "Value", "nAaSamples" + "Hue", "Saturation", "Value" }; constexpr const std::array FXAAUniformNames = { @@ -316,7 +316,6 @@ void FramebufferRenderer::initialize() { // Default GL State for Blending glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } void FramebufferRenderer::deinitialize() { @@ -360,23 +359,6 @@ void FramebufferRenderer::deferredcastersChanged(Deferredcaster&, _dirtyDeferredcastData = true; } -void FramebufferRenderer::resolveMSAA(float blackoutFactor) { - _resolveProgram->activate(); - - ghoul::opengl::TextureUnit mainColorTextureUnit; - mainColorTextureUnit.activate(); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._colorTexture); - _resolveProgram->setUniform(_uniformCache.mainColorTexture, mainColorTextureUnit); - _resolveProgram->setUniform(_uniformCache.blackoutFactor, blackoutFactor); - _resolveProgram->setUniform(_uniformCache.nAaSamples, _nAaSamples); - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - _resolveProgram->deactivate(); -} - void FramebufferRenderer::applyTMO(float blackoutFactor) { const bool doPerformanceMeasurements = global::performanceManager.isEnabled(); std::unique_ptr perfInternal; @@ -1005,7 +987,6 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector glBindTexture(GL_TEXTURE_2D, _gBuffers._depthTexture); raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit); - raycastProgram->setUniform("nAaSamples", _nAaSamples); raycastProgram->setUniform("windowSize", static_cast(_resolution)); glDisable(GL_DEPTH_TEST); @@ -1119,21 +1100,6 @@ void FramebufferRenderer::setResolution(glm::ivec2 res) { _dirtyResolution = true; } -void FramebufferRenderer::setNAaSamples(int nAaSamples) { - ghoul_assert( - nAaSamples >= 1 && nAaSamples <= 8, - "Number of AA samples has to be between 1 and 8" - ); - _nAaSamples = nAaSamples; - if (_nAaSamples == 0) { - _nAaSamples = 1; - } - if (_nAaSamples > 8) { - LERROR("Framebuffer renderer does not support more than 8 MSAA samples."); - _nAaSamples = 8; - } -} - void FramebufferRenderer::disableHDR(bool disable) { _disableHDR = std::move(disable); } @@ -1161,10 +1127,6 @@ void FramebufferRenderer::setSaturation(float sat) { _saturation = std::move(sat); } -int FramebufferRenderer::nAaSamples() const { - return _nAaSamples; -} - void FramebufferRenderer::enableFXAA(bool enable) { _enableFXAA = std::move(enable); } diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index d5da7e8abc..2d76e36340 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -192,13 +192,6 @@ namespace { "direction for tilted display systems in clustered immersive environments." }; - constexpr openspace::properties::Property::PropertyInfo AaSamplesInfo = { - "AaSamples", - "Number of Anti-aliasing samples", - "This value determines the number of anti-aliasing samples to be used in the " - "rendering for the MSAA method." - }; - constexpr openspace::properties::Property::PropertyInfo DisableHDRPipelineInfo = { "DisableHDRPipeline", "Disable HDR Rendering", @@ -279,8 +272,7 @@ RenderEngine::RenderEngine() #endif // OPENSPACE_WITH_INSTRUMENTATION , _disableMasterRendering(DisableMasterInfo, false) , _globalBlackOutFactor(GlobalBlackoutFactorInfo, 1.f, 0.f, 1.f) - , _nAaSamples(AaSamplesInfo, 4, 1, 8) - , _enableFXAA(FXAAInfo, false) + , _enableFXAA(FXAAInfo, true) , _disableHDRPipeline(DisableHDRPipelineInfo, false) , _hdrExposure(HDRExposureInfo, 3.7f, 0.01f, 10.0f) , _gamma(GammaInfo, 0.86f, 0.01f, 5.0f) @@ -317,13 +309,6 @@ RenderEngine::RenderEngine() addProperty(_showVersionInfo); addProperty(_showCameraInfo); - _nAaSamples.onChange([this](){ - if (_renderer) { - _renderer->setNAaSamples(_nAaSamples); - } - }); - addProperty(_nAaSamples); - _enableFXAA.onChange([this]() { if (_renderer) { _renderer->enableFXAA(_enableFXAA); @@ -471,8 +456,6 @@ void RenderEngine::initialize() { void RenderEngine::initializeGL() { LTRACE("RenderEngine::initializeGL(begin)"); - _nAaSamples = global::windowDelegate.currentNumberOfAaSamples(); - std::string renderingMethod = global::configuration.renderingMethod; if (renderingMethod == "ABuffer") { using Version = ghoul::systemcapabilities::Version; @@ -1080,7 +1063,7 @@ void RenderEngine::setRenderer(std::unique_ptr renderer) { _renderer = std::move(renderer); _renderer->setResolution(renderingResolution()); - _renderer->setNAaSamples(_nAaSamples); + _renderer->enableFXAA(true); _renderer->setHDRExposure(_hdrExposure); _renderer->initialize(); } From d5615f089fc14fd40723f32e80fa32f3e8fc7b47 Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Mon, 19 Aug 2019 15:13:12 -0400 Subject: [PATCH 5/8] Removed ToyVolume asset loading. --- data/assets/default.scene | 1 - 1 file changed, 1 deletion(-) diff --git a/data/assets/default.scene b/data/assets/default.scene index e2e477f19b..46e59bf846 100644 --- a/data/assets/default.scene +++ b/data/assets/default.scene @@ -1,5 +1,4 @@ asset.require('./base') -asset.require('examples/volume/toyvolume') local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') From e65eb474666a6ea5e16d17ffe8dc043c83803ee9 Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Mon, 19 Aug 2019 15:14:34 -0400 Subject: [PATCH 6/8] Disabling OpenGL state checking. --- openspace.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openspace.cfg b/openspace.cfg index 03cc4e6fd6..d34aae67c9 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -167,7 +167,7 @@ LoadingScreen = { ShowNodeNames = true, ShowProgressbar = false } -CheckOpenGLState = true +CheckOpenGLState = false LogEachOpenGLCall = false ShutdownCountdown = 3 From b51eb799a571d3de520e3e32173043b72c6caf67 Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Wed, 21 Aug 2019 11:25:38 -0400 Subject: [PATCH 7/8] Clean up and re-nameing. --- modules/base/rendering/renderabletrail.cpp | 3 ++ shaders/framebuffer/fxaa.frag | 39 +++++++++++----------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp index 4ff75279d2..3d115a7809 100644 --- a/modules/base/rendering/renderabletrail.cpp +++ b/modules/base/rendering/renderabletrail.cpp @@ -367,6 +367,8 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) { glBindVertexArray(info._vaoID); if (renderLines) { + glEnable(GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); p->setUniform(c.renderPhase, RenderPhaseLines); // Subclasses of this renderer might be using the index array or might now be // so we check if there is data available and if there isn't, we use the @@ -386,6 +388,7 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) { reinterpret_cast(info.first * sizeof(unsigned int)) ); } + glDisable(GL_LINE_SMOOTH); } if (renderPoints) { // Subclasses of this renderer might be using the index array or might now be diff --git a/shaders/framebuffer/fxaa.frag b/shaders/framebuffer/fxaa.frag index 84a78bf0b6..1d6d9a362e 100644 --- a/shaders/framebuffer/fxaa.frag +++ b/shaders/framebuffer/fxaa.frag @@ -42,7 +42,7 @@ uniform sampler2D renderedTexture; in vec2 texCoord; // Relative luminance -float rgb2luma(vec3 rgb){ +float getLum(vec3 rgb){ return dot(vec3(0.2126, 0.7152, 0.0722), rgb); } @@ -54,14 +54,14 @@ void main() { // ============================ // Luma at the current fragment - float lumaCenter = rgb2luma(colorCenter.rgb); + float lumaCenter = getLum(colorCenter.rgb); // Luma at the four direct neighbours of the current fragment. - float lumaDown = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(0,-1)).rgb); - float lumaUp = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(0,1)).rgb); - float lumaLeft = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(-1,0)).rgb); - float lumaRight = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(1,0)).rgb); - + float lumaDown = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,-1)).rgb); + float lumaUp = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,1)).rgb); + float lumaLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,0)).rgb); + float lumaRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,0)).rgb); + // Find the maximum and minimum luma around the current fragment. float lumaMin = min(lumaCenter, min(min(lumaDown, lumaUp), min(lumaLeft, lumaRight))); float lumaMax = max(lumaCenter, max(max(lumaDown, lumaUp), max(lumaLeft, lumaRight))); @@ -71,7 +71,7 @@ void main() { // If the luma variation is lower that a threshold (or if we are in a really dark area), // we are not on an edge, don't perform any AA. - if (lumaRange < max(EDGE_THRESHOLD_MIN,lumaMax * EDGE_THRESHOLD_MAX)) { + if (lumaRange < max(EDGE_THRESHOLD_MIN, lumaMax * EDGE_THRESHOLD_MAX)) { aaFinalColor = colorCenter; return; } @@ -80,10 +80,10 @@ void main() { // Estimating the gradient: // ============================ // Query the 4 remaining corners lumas. - float lumaDownLeft = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(-1,-1)).rgb); - float lumaUpRight = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(1,1)).rgb); - float lumaUpLeft = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(-1,1)).rgb); - float lumaDownRight = rgb2luma(textureOffset(renderedTexture, texCoord, ivec2(1,-1)).rgb); + float lumaDownLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,-1)).rgb); + float lumaUpRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,1)).rgb); + float lumaUpLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,1)).rgb); + float lumaDownRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,-1)).rgb); // Combine the four edges lumas (using intermediary variables for future computations // with the same values). @@ -91,10 +91,10 @@ void main() { float lumaLeftRight = lumaLeft + lumaRight; // Same for corners - float lumaLeftCorners = lumaDownLeft + lumaUpLeft; - float lumaDownCorners = lumaDownLeft + lumaDownRight; + float lumaLeftCorners = lumaDownLeft + lumaUpLeft; + float lumaDownCorners = lumaDownLeft + lumaDownRight; float lumaRightCorners = lumaDownRight + lumaUpRight; - float lumaUpCorners = lumaUpRight + lumaUpLeft; + float lumaUpCorners = lumaUpRight + lumaUpLeft; // Compute an estimation of the gradient along the horizontal and vertical axis. float edgeHorizontal = abs(-2.0 * lumaLeft + lumaLeftCorners) + @@ -111,6 +111,7 @@ void main() { // Select the two neighboring texels lumas in the opposite direction to the local edge. float luma1 = isHorizontal ? lumaDown : lumaLeft; float luma2 = isHorizontal ? lumaUp : lumaRight; + // Compute gradients in this direction. float gradient1 = luma1 - lumaCenter; float gradient2 = luma2 - lumaCenter; @@ -156,8 +157,8 @@ void main() { // Read the lumas at both current extremities of the exploration segment, // and compute the delta wrt to the local average luma. - float lumaEnd1 = rgb2luma(texture(renderedTexture, uv1).rgb); - float lumaEnd2 = rgb2luma(texture(renderedTexture, uv2).rgb); + float lumaEnd1 = getLum(texture(renderedTexture, uv1).rgb); + float lumaEnd2 = getLum(texture(renderedTexture, uv2).rgb); lumaEnd1 -= lumaLocalAverage; lumaEnd2 -= lumaLocalAverage; @@ -181,12 +182,12 @@ void main() { for (int i = 2; i < ITERATIONS; i++) { // If needed, read luma in 1st direction, compute delta. if (!reached1) { - lumaEnd1 = rgb2luma(texture(renderedTexture, uv1).rgb); + lumaEnd1 = getLum(texture(renderedTexture, uv1).rgb); lumaEnd1 = lumaEnd1 - lumaLocalAverage; } // If needed, read luma in opposite direction, compute delta. if (!reached2) { - lumaEnd2 = rgb2luma(texture(renderedTexture, uv2).rgb); + lumaEnd2 = getLum(texture(renderedTexture, uv2).rgb); lumaEnd2 = lumaEnd2 - lumaLocalAverage; } // If the luma deltas at the current extremities is larger than From fea10b358d0b62f0601eebaaf29fc3c018c20eae Mon Sep 17 00:00:00 2001 From: Jonathas Costa Date: Thu, 22 Aug 2019 17:03:12 -0400 Subject: [PATCH 8/8] Clean up. --- shaders/framebuffer/fxaa.frag | 177 ++++++++++++++-------------------- 1 file changed, 70 insertions(+), 107 deletions(-) diff --git a/shaders/framebuffer/fxaa.frag b/shaders/framebuffer/fxaa.frag index 1d6d9a362e..90c7674897 100644 --- a/shaders/framebuffer/fxaa.frag +++ b/shaders/framebuffer/fxaa.frag @@ -53,25 +53,21 @@ void main() { // Detecting where to apply AA: // ============================ - // Luma at the current fragment - float lumaCenter = getLum(colorCenter.rgb); - - // Luma at the four direct neighbours of the current fragment. - float lumaDown = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,-1)).rgb); - float lumaUp = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,1)).rgb); - float lumaLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,0)).rgb); - float lumaRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,0)).rgb); + float pixelLumCenter = getLum(colorCenter.rgb); + float pixelLumDown = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,-1)).rgb); + float pixelLumUp = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,1)).rgb); + float pixelLumLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,0)).rgb); + float pixelLumRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,0)).rgb); - // Find the maximum and minimum luma around the current fragment. - float lumaMin = min(lumaCenter, min(min(lumaDown, lumaUp), min(lumaLeft, lumaRight))); - float lumaMax = max(lumaCenter, max(max(lumaDown, lumaUp), max(lumaLeft, lumaRight))); + float pixelLumMin = min(pixelLumCenter, min(min(pixelLumDown, pixelLumUp), min(pixelLumLeft, pixelLumRight))); + float pixelLumMax = max(pixelLumCenter, max(max(pixelLumDown, pixelLumUp), max(pixelLumLeft, pixelLumRight))); - // Compute the delta. - float lumaRange = lumaMax - lumaMin; + // Delta. + float pixelLumRange = pixelLumMax - pixelLumMin; - // If the luma variation is lower that a threshold (or if we are in a really dark area), + // If the pixelLum variation is lower that a threshold (or if we are in a really dark area), // we are not on an edge, don't perform any AA. - if (lumaRange < max(EDGE_THRESHOLD_MIN, lumaMax * EDGE_THRESHOLD_MAX)) { + if (pixelLumRange < max(EDGE_THRESHOLD_MIN, pixelLumMax * EDGE_THRESHOLD_MAX)) { aaFinalColor = colorCenter; return; } @@ -79,64 +75,50 @@ void main() { // ============================ // Estimating the gradient: // ============================ - // Query the 4 remaining corners lumas. - float lumaDownLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,-1)).rgb); - float lumaUpRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,1)).rgb); - float lumaUpLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,1)).rgb); - float lumaDownRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,-1)).rgb); + float pixelLumDownLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,-1)).rgb); + float pixelLumUpRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,1)).rgb); + float pixelLumUpLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,1)).rgb); + float pixelLumDownRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,-1)).rgb); - // Combine the four edges lumas (using intermediary variables for future computations - // with the same values). - float lumaDownUp = lumaDown + lumaUp; - float lumaLeftRight = lumaLeft + lumaRight; + float pixelLumDownUp = pixelLumDown + pixelLumUp; + float pixelLumLeftRight = pixelLumLeft + pixelLumRight; + float pixelLumLeftCorners = pixelLumDownLeft + pixelLumUpLeft; + float pixelLumDownCorners = pixelLumDownLeft + pixelLumDownRight; + float pixelLumRightCorners = pixelLumDownRight + pixelLumUpRight; + float pixelLumUpCorners = pixelLumUpRight + pixelLumUpLeft; - // Same for corners - float lumaLeftCorners = lumaDownLeft + lumaUpLeft; - float lumaDownCorners = lumaDownLeft + lumaDownRight; - float lumaRightCorners = lumaDownRight + lumaUpRight; - float lumaUpCorners = lumaUpRight + lumaUpLeft; - - // Compute an estimation of the gradient along the horizontal and vertical axis. - float edgeHorizontal = abs(-2.0 * lumaLeft + lumaLeftCorners) + - abs(-2.0 * lumaCenter + lumaDownUp ) * 2.0 + abs(-2.0 * lumaRight + lumaRightCorners); - float edgeVertical = abs(-2.0 * lumaUp + lumaUpCorners) + - abs(-2.0 * lumaCenter + lumaLeftRight) * 2.0 + abs(-2.0 * lumaDown + lumaDownCorners); - - // Is the local edge horizontal or vertical ? - bool isHorizontal = (edgeHorizontal >= edgeVertical); + // Compute an estimation of the gradient + float edgeHorizontal = abs(-2.0 * pixelLumLeft + pixelLumLeftCorners) + + abs(-2.0 * pixelLumCenter + pixelLumDownUp ) * 2.0 + abs(-2.0 * pixelLumRight + pixelLumRightCorners); + float edgeVertical = abs(-2.0 * pixelLumUp + pixelLumUpCorners) + + abs(-2.0 * pixelLumCenter + pixelLumLeftRight) * 2.0 + abs(-2.0 * pixelLumDown + pixelLumDownCorners); // ============================ // Choosing Edge Orientation: // ============================ - // Select the two neighboring texels lumas in the opposite direction to the local edge. - float luma1 = isHorizontal ? lumaDown : lumaLeft; - float luma2 = isHorizontal ? lumaUp : lumaRight; + bool isHorizontal = (edgeHorizontal >= edgeVertical); + float pixelLum1 = isHorizontal ? pixelLumDown : pixelLumLeft; + float pixelLum2 = isHorizontal ? pixelLumUp : pixelLumRight; - // Compute gradients in this direction. - float gradient1 = luma1 - lumaCenter; - float gradient2 = luma2 - lumaCenter; + // Gradients + float gradient1 = pixelLum1 - pixelLumCenter; + float gradient2 = pixelLum2 - pixelLumCenter; - // Which direction is the steepest ? bool is1Steepest = abs(gradient1) >= abs(gradient2); - - // Gradient in the corresponding direction, normalized. float gradientScaled = 0.25 * max(abs(gradient1), abs(gradient2)); - // Choose the step size (one pixel) according to the edge direction. + // Step size (one pixel) according to the edge direction. float stepLength = isHorizontal ? inverseScreenSize.y : inverseScreenSize.x; - // Average luma in the correct direction. - float lumaLocalAverage = 0.0; + float pixelLumLocalAverage = 0.0; if (is1Steepest) { - // Switch the direction stepLength = - stepLength; - lumaLocalAverage = 0.5 * (luma1 + lumaCenter); + pixelLumLocalAverage = 0.5 * (pixelLum1 + pixelLumCenter); } else { - lumaLocalAverage = 0.5 * (luma2 + lumaCenter); + pixelLumLocalAverage = 0.5 * (pixelLum2 + pixelLumCenter); } - // Shift UV in the correct direction by half a pixel. vec2 currentUv = texCoord; if (isHorizontal) { currentUv.y += stepLength * 0.5; @@ -147,28 +129,22 @@ void main() { // ============================ // Iterations: // ============================ - // Compute offset (for each iteration step) in the right direction. vec2 offset = isHorizontal ? vec2(inverseScreenSize.x, 0.0) : vec2(0.0, inverseScreenSize.y); - // Compute UVs to explore on each side of the edge, orthogonally. - // The QUALITY allows us to step faster. vec2 uv1 = currentUv - offset; vec2 uv2 = currentUv + offset; - // Read the lumas at both current extremities of the exploration segment, - // and compute the delta wrt to the local average luma. - float lumaEnd1 = getLum(texture(renderedTexture, uv1).rgb); - float lumaEnd2 = getLum(texture(renderedTexture, uv2).rgb); - lumaEnd1 -= lumaLocalAverage; - lumaEnd2 -= lumaLocalAverage; + // Read the pixelLums at both current extremities of the exploration segment, + // and compute the delta wrt to the local average pixelLum. + float pixelLumEnd1 = getLum(texture(renderedTexture, uv1).rgb); + float pixelLumEnd2 = getLum(texture(renderedTexture, uv2).rgb); + pixelLumEnd1 -= pixelLumLocalAverage; + pixelLumEnd2 -= pixelLumLocalAverage; - // If the luma deltas at the current extremities are larger than the local gradient, - // we have reached the side of the edge. - bool reached1 = abs(lumaEnd1) >= gradientScaled; - bool reached2 = abs(lumaEnd2) >= gradientScaled; + bool reached1 = abs(pixelLumEnd1) >= gradientScaled; + bool reached2 = abs(pixelLumEnd2) >= gradientScaled; bool reachedBoth = reached1 && reached2; - // If the side is not reached, we continue to explore in this direction. if (!reached1) { uv1 -= offset; } @@ -177,27 +153,24 @@ void main() { uv2 += offset; } - // If both sides have not been reached, continue to explore. + // Still exploring if (!reachedBoth) { for (int i = 2; i < ITERATIONS; i++) { - // If needed, read luma in 1st direction, compute delta. + // If needed, read pixelLum in 1st direction, compute delta. if (!reached1) { - lumaEnd1 = getLum(texture(renderedTexture, uv1).rgb); - lumaEnd1 = lumaEnd1 - lumaLocalAverage; + pixelLumEnd1 = getLum(texture(renderedTexture, uv1).rgb); + pixelLumEnd1 = pixelLumEnd1 - pixelLumLocalAverage; } - // If needed, read luma in opposite direction, compute delta. + // If needed, read pixelLum in opposite direction, compute delta. if (!reached2) { - lumaEnd2 = getLum(texture(renderedTexture, uv2).rgb); - lumaEnd2 = lumaEnd2 - lumaLocalAverage; + pixelLumEnd2 = getLum(texture(renderedTexture, uv2).rgb); + pixelLumEnd2 = pixelLumEnd2 - pixelLumLocalAverage; } - // If the luma deltas at the current extremities is larger than - // the local gradient, we have reached the side of the edge. - reached1 = abs(lumaEnd1) >= gradientScaled; - reached2 = abs(lumaEnd2) >= gradientScaled; + reached1 = abs(pixelLumEnd1) >= gradientScaled; + reached2 = abs(pixelLumEnd2) >= gradientScaled; reachedBoth = reached1 && reached2; - // If the side is not reached, we continue to explore in this direction, - // with a variable quality. + // If the side is not reached if (!reached1) { uv1 -= offset * QUALITY[i]; } @@ -206,7 +179,7 @@ void main() { uv2 += offset * QUALITY[i]; } - // If both sides have been reached, stop the exploration. + // If both sides have been reached if (reachedBoth) { break; } @@ -216,55 +189,45 @@ void main() { // ============================ // Estimating the offset: // ============================ - // Compute the distances to each extremity of the edge. float distance1 = isHorizontal ? (texCoord.x - uv1.x) : (texCoord.y - uv1.y); float distance2 = isHorizontal ? (uv2.x - texCoord.x) : (uv2.y - texCoord.y); - // In which direction is the extremity of the edge closer ? bool isDirection1 = distance1 < distance2; float distanceFinal = min(distance1, distance2); - // Length of the edge. float edgeThickness = (distance1 + distance2); - // UV offset: read in the direction of the closest side of the edge. + // Read in the direction of the closest side of the edge. float pixelOffset = - distanceFinal / edgeThickness + 0.5; - // Is the luma at center smaller than the local average ? - bool isLumaCenterSmaller = lumaCenter < lumaLocalAverage; + bool ispixelLumCenterSmaller = pixelLumCenter < pixelLumLocalAverage; - // If the luma at center is smaller than at its neighbour, the delta luma at + // If the pixelLum at center is smaller than at its neighbour, the delta pixelLum at // each end should be positive (same variation). - // (in the direction of the closer side of the edge.) - bool correctVariation = ((isDirection1 ? lumaEnd1 : lumaEnd2) < 0.0) != isLumaCenterSmaller; + bool correctVariation = ((isDirection1 ? pixelLumEnd1 : pixelLumEnd2) < 0.0) != ispixelLumCenterSmaller; - // If the luma variation is incorrect, do not offset. + // If the pixelLum variation is incorrect, do not offset. float finalOffset = correctVariation ? pixelOffset : 0.0; // ============================ // Subpixel antialiasing: // ============================ - // Sub-pixel shifting - // Full weighted average of the luma over the 3x3 neighborhood. - float lumaAverage = (1.0/12.0) * (2.0 * (lumaDownUp + lumaLeftRight) + - lumaLeftCorners + lumaRightCorners); - // Ratio of the delta between the global average and the center luma, over the luma range in the 3x3 neighborhood. - float subPixelOffset1 = clamp(abs(lumaAverage - lumaCenter) / lumaRange, 0.0, 1.0); - float subPixelOffset2 = (-2.0 * subPixelOffset1 + 3.0) * subPixelOffset1 * subPixelOffset1; - // Compute a sub-pixel offset based on this delta. + float pixelLumAverage = (1.0/12.0) * (2.0 * (pixelLumDownUp + pixelLumLeftRight) + + pixelLumLeftCorners + pixelLumRightCorners); + + float subPixelOffset1 = clamp(abs(pixelLumAverage - pixelLumCenter) / pixelLumRange, 0.0, 1.0); + float subPixelOffset2 = (-2.0 * subPixelOffset1 + 3.0) * subPixelOffset1 * subPixelOffset1; float subPixelOffsetFinal = subPixelOffset2 * subPixelOffset2 * SUBPIXEL_QUALITY; - // Pick the biggest of the two offsets. + // Biggest of the two offsets. finalOffset = max(finalOffset, subPixelOffsetFinal); - // Compute the final UV coordinates. - vec2 finalUv = texCoord; + vec2 finalUV = texCoord; if (isHorizontal) { - finalUv.y += finalOffset * stepLength; + finalUV.y += finalOffset * stepLength; } else { - finalUv.x += finalOffset * stepLength; + finalUV.x += finalOffset * stepLength; } - // Read the color at the new UV coordinates, and use it. - aaFinalColor = texture(renderedTexture, finalUv); + aaFinalColor = texture(renderedTexture, finalUV); } \ No newline at end of file