[vlc-commits] [Git][videolan/vlc][master] 5 commits: qt: support hollowing in `RoundedRectangleShadow.frag`
Steve Lhomme (@robUx4)
gitlab at videolan.org
Mon May 19 13:55:17 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
ed43bb6e by Fatih Uzunoglu at 2025-05-19T13:24:29+00:00
qt: support hollowing in `RoundedRectangleShadow.frag`
Hollowing only makes sense when there is compensation.
- - - - -
b446a5c8 by Fatih Uzunoglu at 2025-05-19T13:24:29+00:00
qml: add property `hollow` to `RoundedRectangleShadow`
- - - - -
42cb339d by Fatih Uzunoglu at 2025-05-19T13:24:29+00:00
qml: use `RoundedRectangleShadow` instead of `RectangularGlow` for the window shadow
- - - - -
6448e518 by Fatih Uzunoglu at 2025-05-19T13:24:29+00:00
qt: get rid of obsolete `RectangularGlow.qml`
CSD window shadow no longer uses `RectangularGlow.qml`,
and there are no other places use it or potentially use
it.
- - - - -
cd2c8fb5 by Fatih Uzunoglu at 2025-05-19T13:24:29+00:00
qt: get rid of `RectangularGlow.frag`
- - - - -
11 changed files:
- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/qml/MainInterface.qml
- modules/gui/qt/meson.build
- − modules/gui/qt/shaders/HollowRectangularGlow.frag
- − modules/gui/qt/shaders/RectangularGlow.frag
- modules/gui/qt/shaders/RoundedRectangleShadow.frag
- + modules/gui/qt/shaders/RoundedRectangleShadow_hollow.frag
- modules/gui/qt/shaders/meson.build
- modules/gui/qt/shaders/shaders.qrc
- − modules/gui/qt/widgets/qml/RectangularGlow.qml
- modules/gui/qt/widgets/qml/RoundedRectangleShadow.qml
Changes:
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -1303,7 +1303,6 @@ libqml_module_widgets_a_QML = \
widgets/qml/PartialEffect.qml \
widgets/qml/ViewHeader.qml \
widgets/qml/ProgressIndicator.qml \
- widgets/qml/RectangularGlow.qml \
widgets/qml/ImageExt.qml \
widgets/qml/ScrollBarExt.qml \
widgets/qml/FastBlend.qml \
@@ -1356,8 +1355,6 @@ libqt_plugin_la_SHADER := shaders/FadingEdge.frag \
shaders/Noise.frag \
shaders/RectFilter.frag \
shaders/SubTexture.vert \
- shaders/HollowRectangularGlow.frag \
- shaders/RectangularGlow.frag \
shaders/SDFAARoundedTexture.frag \
shaders/SDFAARoundedTexture_cropsupport_bordersupport.frag \
shaders/DitheredTexture.frag \
@@ -1365,7 +1362,8 @@ libqt_plugin_la_SHADER := shaders/FadingEdge.frag \
shaders/FastBlend_additive.frag \
shaders/FastBlend_multiply.frag \
shaders/FastBlend_screen.frag \
- shaders/RoundedRectangleShadow.frag
+ shaders/RoundedRectangleShadow.frag \
+ shaders/RoundedRectangleShadow_hollow.frag
if ENABLE_QT
libqt_plugin_la_LIBADD += libqml_module_dialogs.a \
=====================================
modules/gui/qt/maininterface/qml/MainInterface.qml
=====================================
@@ -319,34 +319,24 @@ Item {
//draw the window drop shadow ourselve when the windowing system doesn't
//provide them but support extended frame
- Widgets.RectangularGlow {
+ Widgets.RoundedRectangleShadow {
id: effect
- z: -1
+ parent: g_mainInterface
hollow: Window.window && (Window.window.color.a < 1.0) // the interface may be translucent if the window has backdrop blur
blending: false // stacked below everything, no need for blending even though it is not opaque
visible: _extendedFrameVisible && !MainCtx.platformHandlesShadowsWithCSD()
- anchors.fill: g_mainInterface
- spread: 0.0
- color: "black"
opacity: 0.5
- cornerRadius: glowRadius
- states: [
- State {
- when: MainCtx.intfMainWindow.active
- PropertyChanges {
- target: effect
- glowRadius: MainCtx.windowExtendedMargin * 0.7
- }
- },
- State {
- when: !MainCtx.intfMainWindow.active
- PropertyChanges {
- target: effect
- glowRadius: MainCtx.windowExtendedMargin * 0.5
- }
- }
- ]
- Behavior on glowRadius {
+
+ // Blur radius can not be greater than (margin / compensationFactor), as in that case it would need bigger
+ // size than the window to compensate. If you want bigger blur radius, either decrease the compensation
+ // factor which can lead to visible clipping, or increase the window extended margin:
+ property real activeBlurRadius: (MainCtx.windowExtendedMargin / effect.compensationFactor)
+
+ blurRadius: MainCtx.intfMainWindow.active ? activeBlurRadius
+ : (activeBlurRadius / 2.0)
+
+ Behavior on blurRadius {
+ // FIXME: Use UniformAnimator instead
NumberAnimation {
duration: VLCStyle.duration_veryShort
}
=====================================
modules/gui/qt/meson.build
=====================================
@@ -898,7 +898,6 @@ qml_modules += {
'widgets/qml/PartialEffect.qml',
'widgets/qml/ViewHeader.qml',
'widgets/qml/ProgressIndicator.qml',
- 'widgets/qml/RectangularGlow.qml',
qml_blureffect_file,
'widgets/qml/ImageExt.qml',
'widgets/qml/ScrollBarExt.qml',
=====================================
modules/gui/qt/shaders/HollowRectangularGlow.frag deleted
=====================================
@@ -1,58 +0,0 @@
-#version 440
-/*****************************************************************************
- * Copyright (C) 2024 VLC authors and VideoLAN
- * Copyright (C) 2022 The Qt Company Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * ( at your option ) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-layout(location = 0) in vec2 qt_TexCoord0;
-layout(location = 0) out vec4 fragColor;
-
-layout(std140, binding = 0) uniform buf {
- // qt_Matrix and qt_Opacity must always be both present
- // if the built-in vertex shader is used.
- mat4 qt_Matrix;
- float qt_Opacity;
- vec4 color;
- float relativeSizeX;
- float relativeSizeY;
- float spread;
- float width;
- float height;
- float cornerRadius;
- float inverseSpread;
-};
-
-float linearstep(float e0, float e1, float x)
-{
- return clamp((x - e0) / (e1 - e0), 0.0, 1.0);
-}
-
-void main()
-{
- // discard inner rectangle:
- float radius = ((relativeSizeX * width - cornerRadius * 2.0) / (inverseSpread * inverseSpread)) + cornerRadius;
- if ((qt_TexCoord0.x >= (radius / width) && qt_TexCoord0.x <= (1.0 - (radius / width))) &&
- (qt_TexCoord0.y >= (radius / height) && qt_TexCoord0.y <= (1.0 - (radius / height))))
- discard;
-
- float alpha =
- smoothstep(0.0, relativeSizeX, 0.5 - abs(0.5 - qt_TexCoord0.x)) *
- smoothstep(0.0, relativeSizeY, 0.5 - abs(0.5 - qt_TexCoord0.y));
-
- float spreadMultiplier = linearstep(spread, 1.0 - spread, alpha);
- fragColor = color * qt_Opacity * spreadMultiplier * alpha;
-}
=====================================
modules/gui/qt/shaders/RectangularGlow.frag deleted
=====================================
@@ -1,47 +0,0 @@
-#version 440
-/*****************************************************************************
- * Copyright (C) 2022 The Qt Company Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * ( at your option ) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-layout(location = 0) in vec2 qt_TexCoord0;
-layout(location = 0) out vec4 fragColor;
-
-layout(std140, binding = 0) uniform buf {
- // qt_Matrix and qt_Opacity must always be both present
- // if the built-in vertex shader is used.
- mat4 qt_Matrix;
- float qt_Opacity;
- vec4 color;
- float relativeSizeX;
- float relativeSizeY;
- float spread;
-};
-
-float linearstep(float e0, float e1, float x)
-{
- return clamp((x - e0) / (e1 - e0), 0.0, 1.0);
-}
-
-void main()
-{
- float alpha =
- smoothstep(0.0, relativeSizeX, 0.5 - abs(0.5 - qt_TexCoord0.x)) *
- smoothstep(0.0, relativeSizeY, 0.5 - abs(0.5 - qt_TexCoord0.y));
-
- float spreadMultiplier = linearstep(spread, 1.0 - spread, alpha);
- fragColor = color * qt_Opacity * spreadMultiplier * spreadMultiplier;
-}
=====================================
modules/gui/qt/shaders/RoundedRectangleShadow.frag
=====================================
@@ -105,6 +105,12 @@ void main()
vec2 compensatedOffset = vec2(blurRadius, blurRadius) * compensationFactor;
vec2 denormalCoord = size * qt_TexCoord0;
+#ifdef HOLLOW
+ if (denormalCoord.x >= compensatedOffset.x && denormalCoord.x <= (size.x - compensatedOffset.x) &&
+ denormalCoord.y >= compensatedOffset.y && denormalCoord.y <= (size.y - compensatedOffset.y))
+ discard;
+#endif
+
float shadow = roundedBoxShadow(compensatedOffset,
size - compensatedOffset,
denormalCoord,
=====================================
modules/gui/qt/shaders/RoundedRectangleShadow_hollow.frag
=====================================
@@ -0,0 +1,131 @@
+#version 440
+
+// WARNING: This file must be in sync with RoundedRectangleShadow.frag
+// TODO: Generate this shader at build time.
+#define HOLLOW
+
+// TODO: Dithering is not necessary with light colors. It is pretty much
+// necessary with dark colors due to premultiplied alpha to prevent
+// color banding. So, this should ideally be used only when the
+// background color is dark. When the build system starts supporting
+// defines to feed qsb, we can have the non-dithering version as well.
+#define DITHERING
+
+/*****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#extension GL_GOOGLE_include_directive : enable
+
+#include "Common.glsl"
+
+// This is provided by the default vertex shader even when there is no texture:
+layout(location = 0) in vec2 qt_TexCoord0;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+
+ float blurRadius;
+ float radius;
+ float compensationFactor;
+
+ vec2 size;
+ vec4 color;
+};
+
+// Evan Wallace's Fast Rounded Rectangle Shadows
+// https://madebyevan.com/shaders/fast-rounded-rectangle-shadows/
+// License: CC0 (http://creativecommons.org/publicdomain/zero/1.0/)
+/// <roundedboxshadow>
+
+// A standard gaussian function, used for weighting samples
+float gaussian(float x, float sigma) {
+ const float pi = 3.141592653589793;
+ return exp(-(x * x) / (2.0 * sigma * sigma)) / (sqrt(2.0 * pi) * sigma);
+}
+
+// This approximates the error function, needed for the gaussian integral
+vec2 erf(vec2 x) {
+ vec2 s = sign(x), a = abs(x);
+ x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
+ x *= x;
+ return s - s / (x * x);
+}
+
+// Return the blurred mask along the x dimension
+float roundedBoxShadowX(float x, float y, float sigma, float corner, vec2 halfSize) {
+ float delta = min(halfSize.y - corner - abs(y), 0.0);
+ float curved = halfSize.x - corner + sqrt(max(0.0, corner * corner - delta * delta));
+ vec2 integral = 0.5 + 0.5 * erf((x + vec2(-curved, curved)) * (sqrt(0.5) / sigma));
+ return integral.y - integral.x;
+}
+
+// Return the mask for the shadow of a box from lower to upper
+float roundedBoxShadow(vec2 lower, vec2 upper, vec2 point, float sigma, float corner) {
+ // Center everything to make the math easier
+ vec2 center = (lower + upper) * 0.5;
+ vec2 halfSize = (upper - lower) * 0.5;
+ point -= center;
+
+ // The signal is only non-zero in a limited range, so don't waste samples
+ float low = point.y - halfSize.y;
+ float high = point.y + halfSize.y;
+ float start = clamp(-3.0 * sigma, low, high);
+ float end = clamp(3.0 * sigma, low, high);
+
+ // Accumulate samples (we can get away with surprisingly few samples)
+ float step = (end - start) / 4.0;
+ float y = start + step * 0.5;
+ float value = 0.0;
+ for (int i = 0; i < 4; i++) {
+ value += roundedBoxShadowX(point.x, point.y - y, sigma, corner, halfSize) * gaussian(y, sigma) * step;
+ y += step;
+ }
+
+ return value;
+}
+
+/// </roundedboxshadow>
+
+void main()
+{
+ vec2 compensatedOffset = vec2(blurRadius, blurRadius) * compensationFactor;
+ vec2 denormalCoord = size * qt_TexCoord0;
+
+#ifdef HOLLOW
+ if (denormalCoord.x >= compensatedOffset.x && denormalCoord.x <= (size.x - compensatedOffset.x) &&
+ denormalCoord.y >= compensatedOffset.y && denormalCoord.y <= (size.y - compensatedOffset.y))
+ discard;
+#endif
+
+ float shadow = roundedBoxShadow(compensatedOffset,
+ size - compensatedOffset,
+ denormalCoord,
+ blurRadius,
+ radius / 2.);
+
+ fragColor = color * shadow * qt_Opacity; // premultiplied
+
+#ifdef DITHERING
+ float r = rand(qt_TexCoord0) - 0.5;
+ vec4 noise = vec4(r,r,r,r) * DITHERING_STRENGTH;
+ fragColor += noise * step(DITHERING_CUTOFF, fragColor.a); // additive
+#endif
+}
=====================================
modules/gui/qt/shaders/meson.build
=====================================
@@ -13,8 +13,6 @@ shader_sources = [
'Noise.frag',
'RectFilter.frag',
'SubTexture.vert',
- 'HollowRectangularGlow.frag',
- 'RectangularGlow.frag',
'SDFAARoundedTexture.frag',
'SDFAARoundedTexture_cropsupport_bordersupport.frag',
'DitheredTexture.frag',
@@ -23,6 +21,7 @@ shader_sources = [
'FastBlend_multiply.frag',
'FastBlend_screen.frag',
'RoundedRectangleShadow.frag',
+ 'RoundedRectangleShadow_hollow.frag',
]
shader_files = files(shader_sources)
=====================================
modules/gui/qt/shaders/shaders.qrc
=====================================
@@ -7,8 +7,6 @@
<file alias="Noise.frag.qsb">Noise.frag.qsb</file>
<file alias="RectFilter.frag.qsb">RectFilter.frag.qsb</file>
<file alias="SubTexture.vert.qsb">SubTexture.vert.qsb</file>
- <file alias="HollowRectangularGlow.frag.qsb">HollowRectangularGlow.frag.qsb</file>
- <file alias="RectangularGlow.frag.qsb">RectangularGlow.frag.qsb</file>
<file alias="SDFAARoundedTexture.frag.qsb">SDFAARoundedTexture.frag.qsb</file>
<file alias="SDFAARoundedTexture_cropsupport_bordersupport.frag.qsb">SDFAARoundedTexture_cropsupport_bordersupport.frag.qsb</file>
<file alias="DitheredTexture.frag.qsb">DitheredTexture.frag.qsb</file>
@@ -17,5 +15,6 @@
<file alias="FastBlend_multiply.frag.qsb">FastBlend_multiply.frag.qsb</file>
<file alias="FastBlend_screen.frag.qsb">FastBlend_screen.frag.qsb</file>
<file alias="RoundedRectangleShadow.frag.qsb">RoundedRectangleShadow.frag.qsb</file>
+ <file alias="RoundedRectangleShadow_hollow.frag.qsb">RoundedRectangleShadow_hollow.frag.qsb</file>
</qresource>
</RCC>
=====================================
modules/gui/qt/widgets/qml/RectangularGlow.qml deleted
=====================================
@@ -1,64 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2024 VLC authors and VideoLAN
- * Copyright (C) 2020 The Qt Company Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * ( at your option ) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-import QtQuick
-
-Item {
- id: rootItem
-
- property real glowRadius: 0.0
-
- property real spread: 0.0
-
- property color color: "white"
-
- property real cornerRadius: glowRadius
-
- property alias blending: shaderItem.blending
-
- property alias cullMode: shaderItem.cullMode
-
- property bool hollow: false
-
- ShaderEffect {
- id: shaderItem
-
- x: (parent.width - width) / 2.0
- y: (parent.height - height) / 2.0
- width: parent.width + rootItem.glowRadius * 2 + cornerRadius * 2
- height: parent.height + rootItem.glowRadius * 2 + cornerRadius * 2
-
- function clampedCornerRadius() {
- var maxCornerRadius = Math.min(rootItem.width, rootItem.height) / 2 + glowRadius;
- return Math.max(0, Math.min(rootItem.cornerRadius, maxCornerRadius))
- }
-
- property color color: rootItem.color
- property real inverseSpread: 1.0 - rootItem.spread
- property real relativeSizeX: ((inverseSpread * inverseSpread) * rootItem.glowRadius + cornerRadius * 2.0) / width
- property real relativeSizeY: relativeSizeX * (width / height)
- property real spread: rootItem.spread / 2.0
- property real cornerRadius: clampedCornerRadius()
-
- fragmentShader: rootItem.hollow ? "qrc:///shaders/HollowRectangularGlow.frag.qsb"
- : "qrc:///shaders/RectangularGlow.frag.qsb"
-
- cullMode: ShaderEffect.BackFaceCulling
- }
-}
=====================================
modules/gui/qt/widgets/qml/RoundedRectangleShadow.qml
=====================================
@@ -51,11 +51,15 @@ ShaderEffect {
// to prevent overlapping shadows (breaks batching) and to decrease the shader coverage:
property real compensationFactor: 2.0
+ // Do not paint in the non-compensated inner area - only makes sense if there is compensation:
+ property bool hollow: false
+
blending: true
supportsAtlasTextures: true // irrelevant, but nevertheless...
// cullMode: ShaderEffect.BackFaceCulling // problematic with item layers
- fragmentShader: "qrc:///shaders/RoundedRectangleShadow.frag.qsb"
+ fragmentShader: hollow ? "qrc:///shaders/RoundedRectangleShadow_hollow.frag.qsb"
+ : "qrc:///shaders/RoundedRectangleShadow.frag.qsb"
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/09dc8b44f9b7b3b98ba62be58939185be4e532e6...cd2c8fb5520e688a27a251adafcfa8b5b0eb9f6c
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/09dc8b44f9b7b3b98ba62be58939185be4e532e6...cd2c8fb5520e688a27a251adafcfa8b5b0eb9f6c
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list