diff --git a/modules/globebrowsing/shaders/asdf_blur_fs.glsl b/modules/globebrowsing/shaders/asdf_blur_fs.glsl new file mode 100644 index 0000000000..039ded939d --- /dev/null +++ b/modules/globebrowsing/shaders/asdf_blur_fs.glsl @@ -0,0 +1,87 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2023 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include "fragment.glsl" + +uniform sampler2D tex0; +uniform vec2 resolution; +uniform vec2 direction; +uniform int kernelSize; + +in vec2 uv; + +vec4 blur5(sampler2D tex, vec2 uv, vec2 res, vec2 dir) { + vec4 color = vec4(0.0); + vec2 off1 = vec2(1.3333333333333333) * dir; + color += texture2D(tex, uv) * 0.29411764705882354; + color += texture2D(tex, uv + (off1 / res)) * 0.35294117647058826; + color += texture2D(tex, uv - (off1 / res)) * 0.35294117647058826; + return color; +} + +vec4 blur9(sampler2D tex, vec2 uv, vec2 res, vec2 dir) { + vec4 color = vec4(0.0); + vec2 off1 = vec2(1.3846153846) * dir; + vec2 off2 = vec2(3.2307692308) * dir; + color += texture2D(tex, uv) * 0.2270270270; + color += texture2D(tex, uv + (off1 / res)) * 0.3162162162; + color += texture2D(tex, uv - (off1 / res)) * 0.3162162162; + color += texture2D(tex, uv + (off2 / res)) * 0.0702702703; + color += texture2D(tex, uv - (off2 / res)) * 0.0702702703; + return color; +} + +vec4 blur13(sampler2D tex, vec2 uv, vec2 res, vec2 dir) { + vec4 color; + vec2 off1 = vec2(1.3846153846) * dir; + vec2 off2 = vec2(3.2307692308) * dir; + vec2 off3 = vec2(5.176470588235294) * dir; + color += texture2D(tex, uv) * 0.1964825501511404; + color += texture2D(tex, uv + (off1 / res)) * 0.2969069646728344; + color += texture2D(tex, uv - (off1 / res)) * 0.2969069646728344; + color += texture2D(tex, uv + (off2 / res)) * 0.09447039785044732; + color += texture2D(tex, uv - (off2 / res)) * 0.09447039785044732; + color += texture2D(tex, uv + (off3 / res)) * 0.010381362401148057; + color += texture2D(tex, uv - (off3 / res)) * 0.010381362401148057; + + return color; +} + +Fragment getFragment() { + Fragment frag; + frag.disableLDR2HDR = true; + if (kernelSize == 0) { + frag.color = texture(tex0, uv); + } + if (kernelSize == 5) { + frag.color = blur5(tex0, uv, resolution, direction); + } + if (kernelSize == 9) { + frag.color = blur9(tex0, uv, resolution, direction); + } + if (kernelSize == 13) { + frag.color = blur13(tex0, uv, resolution, direction); + } + return frag; +} diff --git a/modules/globebrowsing/shaders/asdf_blur_vs.glsl b/modules/globebrowsing/shaders/asdf_blur_vs.glsl new file mode 100644 index 0000000000..a00b584ed0 --- /dev/null +++ b/modules/globebrowsing/shaders/asdf_blur_vs.glsl @@ -0,0 +1,35 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2023 * + * * + * 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 vec2 vertex_position; + +out vec2 uv; + +void main() +{ + uv = (vertex_position + 1) * 0.5; + gl_Position = vec4(vertex_position, 0.0, 1.0); +} diff --git a/modules/globebrowsing/shaders/asdf_gs.glsl b/modules/globebrowsing/shaders/asdf_gs.glsl index f38d581683..566ff3ec4a 100644 --- a/modules/globebrowsing/shaders/asdf_gs.glsl +++ b/modules/globebrowsing/shaders/asdf_gs.glsl @@ -29,6 +29,7 @@ layout (triangle_strip, max_vertices = 6) out; uniform vec2 viewport; uniform float lineWidth; +uniform int nPoints; void main() { @@ -98,12 +99,14 @@ void main() gl_Position = pos; EmitVertex(); - pos = p2; - pos.xy -= nn * lineWidth * 0.5; - pos.xy = 2 * pos.xy / viewport - 1; - pos.xyz *= pos.w; - gl_Position = pos; - EmitVertex(); + if (gl_PrimitiveIDIn < nPoints - 3) { + pos = p2; + pos.xy -= nn * lineWidth * 0.5; + pos.xy = 2 * pos.xy / viewport - 1; + pos.xyz *= pos.w; + gl_Position = pos; + EmitVertex(); + } EndPrimitive(); } diff --git a/modules/globebrowsing/src/renderableglobe.cpp b/modules/globebrowsing/src/renderableglobe.cpp index 5f7daeb40c..e223a9da50 100644 --- a/modules/globebrowsing/src/renderableglobe.cpp +++ b/modules/globebrowsing/src/renderableglobe.cpp @@ -69,7 +69,6 @@ namespace { // Global flags to modify the RenderableGlobe constexpr bool LimitLevelByAvailableData = true; - constexpr bool PerformFrustumCulling = false; constexpr bool PreformHorizonCulling = true; // Shadow structure diff --git a/modules/globebrowsing/src/tileprovider/asdftileprovider.cpp b/modules/globebrowsing/src/tileprovider/asdftileprovider.cpp index b9bad3886c..e667272dd7 100644 --- a/modules/globebrowsing/src/tileprovider/asdftileprovider.cpp +++ b/modules/globebrowsing/src/tileprovider/asdftileprovider.cpp @@ -48,6 +48,13 @@ namespace { Points, }; + enum class KernelSize { + Disabled = 0, + Five = 5, + Nine = 9, + Thirteen = 13 + }; + constexpr openspace::properties::Property::PropertyInfo JSONPathInfo = { "JSON", "JSON", @@ -83,6 +90,14 @@ namespace { openspace::properties::Property::Visibility::User }; + constexpr openspace::properties::Property::PropertyInfo KernelSizeInfo = { + "KernelSize", + "Kernel size", + "Specifies the kernel size of the gaussian blur filter used to smooth out" + "the edges of rendered path.", + openspace::properties::Property::Visibility::User + }; + constexpr openspace::properties::Property::PropertyInfo RenderFullAsdfInfo = { "RenderFullAsdf", "Render Full Asdf", @@ -126,6 +141,15 @@ namespace { // [[codegen::verbatim(RenderingModeInfo.description)]] std::optional renderingMode; + + enum class [[codegen::map(KernelSize)]] KernelSize { + Disabled = 0, + Five = 5, + Nine = 9, + Thirteen = 13 + }; + // [[codegen::verbatim(KernelSizeInfo.description)]] + std::optional kernelSize; }; #include "asdftileprovider_codegen.cpp" @@ -142,6 +166,8 @@ AsdfTileProvider::AsdfTileProvider(const ghoul::Dictionary& dictionary) : _renderFullAsdf(RenderFullAsdfInfo, false), _renderingMode(RenderingModeInfo, openspace::properties::OptionProperty::DisplayType::Dropdown), + _kernelSize(KernelSizeInfo, + openspace::properties::OptionProperty::DisplayType::Dropdown), _start(0.0), _fbo(0), _vao(0), @@ -173,6 +199,14 @@ AsdfTileProvider::AsdfTileProvider(const ghoul::Dictionary& dictionary) : }); addProperty(_renderingMode); + _kernelSize.addOptions({ + { static_cast(KernelSize::Disabled), "Disabled" }, + { static_cast(KernelSize::Five), "5" }, + { static_cast(KernelSize::Nine), "9" }, + { static_cast(KernelSize::Thirteen), "13" }, + }); + addProperty(_kernelSize); + const Parameters p = codegen::bake(dictionary); _JSONPath = p.JSON; _startTime = p.startTime; @@ -183,6 +217,9 @@ AsdfTileProvider::AsdfTileProvider(const ghoul::Dictionary& dictionary) : if (p.renderingMode.has_value()) { _renderingMode = static_cast(codegen::map(*p.renderingMode)); } + if (p.kernelSize.has_value()) { + _kernelSize = static_cast(codegen::map(*p.kernelSize)); + } } AsdfTileProvider::~AsdfTileProvider() {} @@ -276,6 +313,17 @@ void AsdfTileProvider::internalInitialize() { GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER ); + glTexParameteri( + GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR + ); + glTexParameteri( + GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR + ); + glTexImage2D( GL_TEXTURE_2D, 0, @@ -289,6 +337,70 @@ void AsdfTileProvider::internalInitialize() { ); glBindTexture(GL_TEXTURE_2D, 0); + static constexpr GLfloat vertices[] = { + -1.f, -1.f, + 1.f, -1.f, + -1.f, 1.f, + -1.f, 1.f, + 1.f, -1.f, + 1.f, 1.f, + }; + + glGenVertexArrays(1, &_quadVao); + glBindVertexArray(_quadVao); + glGenBuffers(1, &_quadVbo); + glBindBuffer(GL_ARRAY_BUFFER, _quadVbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 0, + 2, + GL_FLOAT, + GL_FALSE, + 2 * sizeof(GL_FLOAT), + reinterpret_cast(0) + ); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + _texture2 = std::make_unique( + glm::uvec3(_rendertargetDimensions.x, _rendertargetDimensions.y, 1), + GL_TEXTURE_2D + ); + + glBindTexture(GL_TEXTURE_2D, *_texture2); + glTexParameteri( + GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, + GL_LINEAR + ); + glTexParameteri( + GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR + ); + + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA, + static_cast(_rendertargetDimensions.x), + static_cast(_rendertargetDimensions.y), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + nullptr + ); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenFramebuffers(1, &_fbo2); + + _program2 = global::renderEngine->buildRenderProgram( + "AsdfProgram2", + absPath("${MODULE_GLOBEBROWSING}/shaders/asdf_blur_vs.glsl"), + absPath("${MODULE_GLOBEBROWSING}/shaders/asdf_blur_fs.glsl") + ); + update(); } @@ -433,7 +545,6 @@ void AsdfTileProvider::update() { static_cast(_rendertargetDimensions.y) ); - //glClearColor(.2f, .2f, .2f, 0.f); glClearColor(.0f, .0f, .0f, 0.f); glClear(GL_COLOR_BUFFER_BIT); @@ -441,8 +552,7 @@ void AsdfTileProvider::update() { _program->setUniform("viewport", glm::vec2(_rendertargetDimensions.x, _rendertargetDimensions.y)); _program->setUniform("lineWidth", _lineWidth); - const float blend = 2.0; - //_program->setUniform("blendFactor", blend); + _program->setUniform("nPoints", static_cast(points.size()-1)); _program->setUniform("color", _color); _program->setUniform("projectionMatrix", projection); @@ -464,6 +574,68 @@ void AsdfTileProvider::update() { glDrawArrays(GL_POINTS, 0, points.size()); } + if (_kernelSize.value() != static_cast(KernelSize::Disabled)) { + // Two-pass blur + + // First pass - horizontally + glBindFramebuffer(GL_FRAMEBUFFER, _fbo2); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + *_texture2.get(), + 0 + ); + + glViewport( + 0, + 0, + static_cast(_rendertargetDimensions.x), + static_cast(_rendertargetDimensions.y) + ); + glClear(GL_COLOR_BUFFER_BIT); + + _program2->activate(); + _program2->setUniform("resolution", + glm::vec2(_rendertargetDimensions.x, _rendertargetDimensions.y)); + _program2->setUniform("direction", glm::vec2(1, 0)); + _program2->setUniform("kernelSize", _kernelSize.value()); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, *_texture.get()); + glBindVertexArray(_quadVao); + glDrawArrays(GL_TRIANGLES, 0, 6); + + // First pass - vertically + glBindFramebuffer(GL_FRAMEBUFFER, _fbo); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + *_texture.get(), + 0 + ); + + glViewport( + 0, + 0, + static_cast(_rendertargetDimensions.x), + static_cast(_rendertargetDimensions.y) + ); + glClear(GL_COLOR_BUFFER_BIT); + + _program2->activate(); + _program2->setUniform("resolution", + glm::vec2(_rendertargetDimensions.x, _rendertargetDimensions.y)); + _program2->setUniform("direction", glm::vec2(0, 1)); + _program2->setUniform("kernelSize", _kernelSize.value()); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, *_texture2.get()); + glBindVertexArray(_quadVao); + glDrawArrays(GL_TRIANGLES, 0, 6); + } + // Reset FBO, shader program and viewport glUseProgram(prevProgram); glBindFramebuffer(GL_FRAMEBUFFER, prevFBO); diff --git a/modules/globebrowsing/src/tileprovider/asdftileprovider.h b/modules/globebrowsing/src/tileprovider/asdftileprovider.h index e023d1c60d..6366e1e546 100644 --- a/modules/globebrowsing/src/tileprovider/asdftileprovider.h +++ b/modules/globebrowsing/src/tileprovider/asdftileprovider.h @@ -62,6 +62,7 @@ private: properties::FloatProperty _lineWidth; properties::BoolProperty _renderFullAsdf; properties::OptionProperty _renderingMode; + properties::OptionProperty _kernelSize; struct Feature { double _lat, _lon; @@ -70,12 +71,17 @@ private: double _start = 0.0; GLuint _fbo = 0; + GLuint _fbo2 = 0; GLuint _vao = 0; GLuint _vbo = 0; + GLuint _quadVao = 0; + GLuint _quadVbo = 0; GeodeticPatch _bounds; glm::ivec2 _rendertargetDimensions; std::unique_ptr _program; + std::unique_ptr _program2; std::unique_ptr _texture; + std::unique_ptr _texture2; std::vector _features; };