diff --git a/es-app/src/MediaViewer.cpp b/es-app/src/MediaViewer.cpp index acb5d052b..9c364df24 100644 --- a/es-app/src/MediaViewer.cpp +++ b/es-app/src/MediaViewer.cpp @@ -199,26 +199,16 @@ void MediaViewer::render(const glm::mat4& /*parentTrans*/) if (Settings::getInstance()->getBool("MediaViewerVideoScanlines")) shaders = Renderer::Shader::SCANLINES; if (Settings::getInstance()->getBool("MediaViewerVideoBlur")) { - shaders |= Renderer::Shader::BLUR_HORIZONTAL; - const float resolutionModifier {mRenderer->getScreenResolutionModifier()}; - // clang-format off - if (resolutionModifier < 1) - videoParameters.blurPasses = 2; // Below 1080 - else if (resolutionModifier >= 4) - videoParameters.blurPasses = 12; // 8K - else if (resolutionModifier >= 2.9) - videoParameters.blurPasses = 10; // 6K - else if (resolutionModifier >= 2.6) - videoParameters.blurPasses = 8; // 5K - else if (resolutionModifier >= 2) - videoParameters.blurPasses = 5; // 4K - else if (resolutionModifier >= 1.3) - videoParameters.blurPasses = 3; // 1440 - else if (resolutionModifier >= 1) - videoParameters.blurPasses = 2; // 1080 - // clang-format on + if (mRenderer->getScreenRotation() == 90 || mRenderer->getScreenRotation() == 270) + shaders |= Renderer::Shader::BLUR_VERTICAL; + else + shaders |= Renderer::Shader::BLUR_HORIZONTAL; } + // We run two passes to make the blur smoother. + videoParameters.blurPasses = 2; + videoParameters.blurStrength = 1.35f; + if (shaders != 0) mRenderer->shaderPostprocessing(shaders, videoParameters); } diff --git a/es-app/src/Screensaver.cpp b/es-app/src/Screensaver.cpp index cc065902f..ba731faae 100644 --- a/es-app/src/Screensaver.cpp +++ b/es-app/src/Screensaver.cpp @@ -324,26 +324,17 @@ void Screensaver::renderScreensaver() if (Settings::getInstance()->getBool("ScreensaverVideoScanlines")) shaders = Renderer::Shader::SCANLINES; if (Settings::getInstance()->getBool("ScreensaverVideoBlur")) { - shaders |= Renderer::Shader::BLUR_HORIZONTAL; - const float resolutionModifier {mRenderer->getScreenResolutionModifier()}; - // clang-format off - if (resolutionModifier < 1) - videoParameters.blurPasses = 2; // Below 1080 - else if (resolutionModifier >= 4) - videoParameters.blurPasses = 12; // 8K - else if (resolutionModifier >= 2.9) - videoParameters.blurPasses = 10; // 6K - else if (resolutionModifier >= 2.6) - videoParameters.blurPasses = 8; // 5K - else if (resolutionModifier >= 2) - videoParameters.blurPasses = 5; // 4K - else if (resolutionModifier >= 1.3) - videoParameters.blurPasses = 3; // 1440 - else if (resolutionModifier >= 1) - videoParameters.blurPasses = 2; // 1080 - // clang-format on + if (mRenderer->getScreenRotation() == 90 || + mRenderer->getScreenRotation() == 270) + shaders |= Renderer::Shader::BLUR_VERTICAL; + else + shaders |= Renderer::Shader::BLUR_HORIZONTAL; } + // We run two passes to make the blur smoother. + videoParameters.blurPasses = 2; + videoParameters.blurStrength = 1.35f; + if (shaders != 0) mRenderer->shaderPostprocessing(shaders, videoParameters); diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 637a8b2c1..fbc054be7 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -513,23 +513,10 @@ void Window::render() // degrees. if (Settings::getInstance()->getBool("MenuBlurBackground") || mRenderer->getScreenRotation() == 90 || mRenderer->getScreenRotation() == 270) { - const float resolutionModifier {mRenderer->getScreenResolutionModifier()}; - // clang-format off - if (resolutionModifier < 1) - backgroundParameters.blurPasses = 2; // Below 1080 - else if (resolutionModifier >= 4) - backgroundParameters.blurPasses = 12; // 8K - else if (resolutionModifier >= 2.9) - backgroundParameters.blurPasses = 10; // 6K - else if (resolutionModifier >= 2.6) - backgroundParameters.blurPasses = 8; // 5K - else if (resolutionModifier >= 2) - backgroundParameters.blurPasses = 5; // 4K - else if (resolutionModifier >= 1.3) - backgroundParameters.blurPasses = 3; // 1440 - else if (resolutionModifier >= 1) - backgroundParameters.blurPasses = 2; // 1080 - // clang-format on + + // We run two passes to make the blur smoother. + backgroundParameters.blurPasses = 2; + backgroundParameters.blurStrength = 1.35f; // Also dim the background slightly. if (Settings::getInstance()->getString("MenuColorScheme") == "light") diff --git a/es-core/src/renderers/Renderer.h b/es-core/src/renderers/Renderer.h index e1dd749b2..a66586337 100644 --- a/es-core/src/renderers/Renderer.h +++ b/es-core/src/renderers/Renderer.h @@ -67,6 +67,7 @@ public: float saturation; float dimming; float reflectionsFalloff; + float blurStrength; unsigned int shaders; unsigned int shaderFlags; @@ -76,6 +77,7 @@ public: , saturation {1.0f} , dimming {1.0f} , reflectionsFalloff {0.0f} + , blurStrength {0.0f} , shaders {0} , shaderFlags {0} { @@ -94,6 +96,7 @@ public: , saturation {1.0f} , dimming {1.0f} , reflectionsFalloff {0.0f} + , blurStrength {0.0f} , shaders {0} , shaderFlags {0} { @@ -104,6 +107,7 @@ public: float opacity; float saturation; float dimming; + float blurStrength; unsigned int blurPasses; unsigned int shaders; @@ -111,6 +115,7 @@ public: : opacity {1.0f} , saturation {1.0f} , dimming {1.0f} + , blurStrength {0.0f} , blurPasses {1} , shaders {0} { diff --git a/es-core/src/renderers/RendererOpenGL.cpp b/es-core/src/renderers/RendererOpenGL.cpp index 8eb2ceb5c..e62da151e 100644 --- a/es-core/src/renderers/RendererOpenGL.cpp +++ b/es-core/src/renderers/RendererOpenGL.cpp @@ -294,9 +294,9 @@ bool RendererOpenGL::createContext() textureHeight = static_cast(getScreenWidth()); } - mPostProcTexture1 = createTexture(TextureType::BGRA, false, false, false, false, textureWidth, + mPostProcTexture1 = createTexture(TextureType::BGRA, false, true, false, false, textureWidth, textureHeight, nullptr); - mPostProcTexture2 = createTexture(TextureType::BGRA, false, false, false, false, textureWidth, + mPostProcTexture2 = createTexture(TextureType::BGRA, false, true, false, false, textureWidth, textureHeight, nullptr); // Attach textures to the shader framebuffers. @@ -522,7 +522,8 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices, mBlurHorizontalShader->setAttribPointers(); GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, GL_DYNAMIC_DRAW)); - mBlurHorizontalShader->setTextureSize({width, height}); + mBlurHorizontalShader->setBlurStrength((vertices->blurStrength / getScreenWidth()) * + getScreenResolutionModifier()); mBlurHorizontalShader->setFlags(vertices->shaderFlags); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); mLastShader = mBlurHorizontalShader; @@ -540,7 +541,8 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices, mBlurVerticalShader->setAttribPointers(); GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, GL_DYNAMIC_DRAW)); - mBlurVerticalShader->setTextureSize({width, height}); + mBlurVerticalShader->setBlurStrength((vertices->blurStrength / getScreenHeight()) * + getScreenResolutionModifier()); mBlurVerticalShader->setFlags(vertices->shaderFlags); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); mLastShader = mBlurVerticalShader; @@ -621,6 +623,7 @@ void RendererOpenGL::shaderPostprocessing(unsigned int shaders, vertices->opacity = parameters.opacity; vertices->saturation = parameters.saturation; vertices->dimming = parameters.dimming; + vertices->blurStrength = parameters.blurStrength; vertices->shaderFlags = ShaderFlags::POST_PROCESSING | ShaderFlags::PREMULTIPLIED; if (screenRotation == 90 || screenRotation == 270) diff --git a/es-core/src/renderers/ShaderOpenGL.cpp b/es-core/src/renderers/ShaderOpenGL.cpp index 7d04d8c71..2b34aca58 100644 --- a/es-core/src/renderers/ShaderOpenGL.cpp +++ b/es-core/src/renderers/ShaderOpenGL.cpp @@ -24,6 +24,7 @@ ShaderOpenGL::ShaderOpenGL() , mShaderSaturation {0} , mShaderDimming {0} , mShaderReflectionsFalloff {0} + , mBlurStrength {0} , mShaderFlags {0} { } @@ -128,6 +129,7 @@ void ShaderOpenGL::getVariableLocations(GLuint programID) mShaderSaturation = glGetUniformLocation(mProgramID, "saturation"); mShaderDimming = glGetUniformLocation(mProgramID, "dimming"); mShaderReflectionsFalloff = glGetUniformLocation(mProgramID, "reflectionsFalloff"); + mBlurStrength = glGetUniformLocation(mProgramID, "blurStrength"); mShaderFlags = glGetUniformLocation(mProgramID, "shaderFlags"); } @@ -198,6 +200,12 @@ void ShaderOpenGL::setReflectionsFalloff(GLfloat falloff) GL_CHECK_ERROR(glUniform1f(mShaderReflectionsFalloff, falloff)); } +void ShaderOpenGL::setBlurStrength(GLfloat blurStrength) +{ + if (mBlurStrength != -1) + GL_CHECK_ERROR(glUniform1f(mBlurStrength, blurStrength)); +} + void ShaderOpenGL::setFlags(GLuint flags) { if (mShaderFlags != -1) diff --git a/es-core/src/renderers/ShaderOpenGL.h b/es-core/src/renderers/ShaderOpenGL.h index f8f594d3e..d50d6268f 100644 --- a/es-core/src/renderers/ShaderOpenGL.h +++ b/es-core/src/renderers/ShaderOpenGL.h @@ -74,6 +74,7 @@ public: void setSaturation(GLfloat saturation); void setDimming(GLfloat dimming); void setReflectionsFalloff(GLfloat falloff); + void setBlurStrength(GLfloat blurStrength); void setFlags(GLuint flags); // Sets the shader program to use the loaded shaders. void activateShaders(); @@ -101,6 +102,7 @@ private: GLint mShaderSaturation; GLint mShaderDimming; GLint mShaderReflectionsFalloff; + GLint mBlurStrength; GLint mShaderFlags; }; diff --git a/resources/shaders/glsl/blur_horizontal.glsl b/resources/shaders/glsl/blur_horizontal.glsl index a4b3a2945..4428bb308 100644 --- a/resources/shaders/glsl/blur_horizontal.glsl +++ b/resources/shaders/glsl/blur_horizontal.glsl @@ -1,14 +1,11 @@ +// SPDX-License-Identifier: MIT // -// Implementation based on the article "Efficient Gaussian blur with linear sampling" -// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ -// A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX -// can be found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask +// EmulationStation Desktop Edition +// blur_horizontal.glsl // -// Taken from the RetroArch project and modified for ES-DE. +// Horizontal gaussian blur. // -#define HW 1.00 - // Vertex section of code: #if defined(VERTEX) @@ -31,8 +28,8 @@ precision mediump float; #endif uniform uint shaderFlags; -uniform vec2 textureSize; uniform sampler2D textureSampler; +uniform float blurStrength; in vec2 texCoord; out vec4 FragColor; @@ -45,32 +42,48 @@ out vec4 FragColor; void main() { - vec4 SourceSize; - vec2 PIXEL_SIZE; + vec4 color = vec4(0.0); + float hstep = 1.0f; + float vstep = 0.0f; + vec2 tc; if (0x0u != (shaderFlags & 0x10u)) { - SourceSize = vec4(textureSize.yx, 1.0 / textureSize.xy); - PIXEL_SIZE = vec2(SourceSize.w, SourceSize.z); + // Screen rotated 90 or 270 degrees. + tc = texCoord.yx; } else { - SourceSize = vec4(textureSize.xy, 1.0 / textureSize.xy); - PIXEL_SIZE = vec2(SourceSize.z, SourceSize.w); + tc = texCoord.xy; } - float sampleOffsets[5] = float[5](0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130); - float sampleWeights[5] = - float[5](0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196); + // 9-tap filter. + color += texture(textureSampler, + vec2(tc.x - 4.0 * blurStrength * hstep, tc.y - 4.0 * blurStrength * vstep)) * + 0.0162162162; + color += texture(textureSampler, + vec2(tc.x - 3.0 * blurStrength * hstep, tc.y - 3.0 * blurStrength * vstep)) * + 0.0540540541; + color += texture(textureSampler, + vec2(tc.x - 2.0 * blurStrength * hstep, tc.y - 2.0 * blurStrength * vstep)) * + 0.1216216216; + color += texture(textureSampler, + vec2(tc.x - 1.0 * blurStrength * hstep, tc.y - 1.0 * blurStrength * vstep)) * + 0.1945945946; - vec4 color = texture(textureSampler, texCoord) * sampleWeights[0]; - for (int i = 1; i < 5; i++) { - color += - texture(textureSampler, texCoord + vec2(sampleOffsets[i] * HW * PIXEL_SIZE.x, 0.0)) * - sampleWeights[i]; - color += - texture(textureSampler, texCoord - vec2(sampleOffsets[i] * HW * PIXEL_SIZE.x, 0.0)) * - sampleWeights[i]; - } + color += texture(textureSampler, vec2(tc.x, tc.y)) * 0.2270270270; - FragColor = vec4(color); + color += texture(textureSampler, + vec2(tc.x + 1.0 * blurStrength * hstep, tc.y + 1.0 * blurStrength * vstep)) * + 0.1945945946; + color += texture(textureSampler, + vec2(tc.x + 2.0 * blurStrength * hstep, tc.y + 2.0 * blurStrength * vstep)) * + 0.1216216216; + color += texture(textureSampler, + vec2(tc.x + 3.0 * blurStrength * hstep, tc.y + 3.0 * blurStrength * vstep)) * + 0.0540540541; + color += texture(textureSampler, + vec2(tc.x + 4.0 * blurStrength * hstep, tc.y + 4.0 * blurStrength * vstep)) * + 0.0162162162; + + FragColor = vec4(color.rgb, 1.0); } #endif diff --git a/resources/shaders/glsl/blur_vertical.glsl b/resources/shaders/glsl/blur_vertical.glsl index 69f89e21a..ce7e551d7 100644 --- a/resources/shaders/glsl/blur_vertical.glsl +++ b/resources/shaders/glsl/blur_vertical.glsl @@ -1,14 +1,11 @@ +// SPDX-License-Identifier: MIT // -// Implementation based on the article "Efficient Gaussian blur with linear sampling" -// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ -// A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX -// can be found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask +// EmulationStation Desktop Edition +// blur_vertical.glsl // -// Taken from the RetroArch project and modified for ES-DE. +// Vertical gaussian blur. // -#define VW 1.00 - // Vertex section of code: #if defined(VERTEX) @@ -31,8 +28,8 @@ precision mediump float; #endif uniform uint shaderFlags; -uniform vec2 textureSize; uniform sampler2D textureSampler; +uniform float blurStrength; in vec2 texCoord; out vec4 FragColor; @@ -45,32 +42,48 @@ out vec4 FragColor; void main() { - vec4 SourceSize; - vec2 PIXEL_SIZE; + vec4 color = vec4(0.0); + float hstep = 0.0f; + float vstep = 1.0f; + vec2 tc; if (0x0u != (shaderFlags & 0x10u)) { - SourceSize = vec4(textureSize.xy, 1.0 / textureSize.yx); - PIXEL_SIZE = vec2(SourceSize.w, SourceSize.z); + // Screen rotated 90 or 270 degrees. + tc = texCoord.yx; } else { - SourceSize = vec4(textureSize.xy, 1.0 / textureSize.xy); - PIXEL_SIZE = vec2(SourceSize.z, SourceSize.w); + tc = texCoord.xy; } - float sampleOffsets[5] = float[5](0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130); - float sampleWeights[5] = - float[5](0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196); + // 9-tap filter. + color += texture(textureSampler, + vec2(tc.x - 4.0 * blurStrength * hstep, tc.y - 4.0 * blurStrength * vstep)) * + 0.0162162162; + color += texture(textureSampler, + vec2(tc.x - 3.0 * blurStrength * hstep, tc.y - 3.0 * blurStrength * vstep)) * + 0.0540540541; + color += texture(textureSampler, + vec2(tc.x - 2.0 * blurStrength * hstep, tc.y - 2.0 * blurStrength * vstep)) * + 0.1216216216; + color += texture(textureSampler, + vec2(tc.x - 1.0 * blurStrength * hstep, tc.y - 1.0 * blurStrength * vstep)) * + 0.1945945946; - vec4 color = texture(textureSampler, texCoord) * sampleWeights[0]; - for (int i = 1; i < 5; i++) { - color += - texture(textureSampler, texCoord + vec2(0.0, sampleOffsets[i] * VW * PIXEL_SIZE.y)) * - sampleWeights[i]; - color += - texture(textureSampler, texCoord - vec2(0.0, sampleOffsets[i] * VW * PIXEL_SIZE.y)) * - sampleWeights[i]; - } + color += texture(textureSampler, vec2(tc.x, tc.y)) * 0.2270270270; - FragColor = vec4(color); + color += texture(textureSampler, + vec2(tc.x + 1.0 * blurStrength * hstep, tc.y + 1.0 * blurStrength * vstep)) * + 0.1945945946; + color += texture(textureSampler, + vec2(tc.x + 2.0 * blurStrength * hstep, tc.y + 2.0 * blurStrength * vstep)) * + 0.1216216216; + color += texture(textureSampler, + vec2(tc.x + 3.0 * blurStrength * hstep, tc.y + 3.0 * blurStrength * vstep)) * + 0.0540540541; + color += texture(textureSampler, + vec2(tc.x + 4.0 * blurStrength * hstep, tc.y + 4.0 * blurStrength * vstep)) * + 0.0162162162; + + FragColor = vec4(color.rgb, 1.0); } #endif