diff --git a/src/scenegraph/shaders.qrc b/src/scenegraph/shaders.qrc
index f0f8f22c..b9545645 100644
--- a/src/scenegraph/shaders.qrc
+++ b/src/scenegraph/shaders.qrc
@@ -1,11 +1,13 @@
header_es.glsl
header_desktop.glsl
header_desktop_core.glsl
shadowedrectangle.vert
+ shadowedrectangle_core.vert
shadowedrectangle.frag
+ shadowedrectangle_core.frag
diff --git a/src/scenegraph/shadowedrectangle_core.frag b/src/scenegraph/shadowedrectangle_core.frag
new file mode 100644
index 00000000..b7990584
--- /dev/null
+++ b/src/scenegraph/shadowedrectangle_core.frag
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 Arjen Hiemstra
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+// This is based on the 2D SDF functions provided by Inigo Quilez:
+// https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
+
+uniform lowp float opacity;
+uniform lowp float size;
+uniform lowp float radius;
+uniform lowp vec4 color;
+uniform lowp vec4 shadowColor;
+uniform lowp vec2 offset;
+uniform lowp vec2 aspect;
+
+in lowp vec2 uv;
+
+const lowp float minimum_shadow_radius = 0.05;
+
+// Calculate the distance to a rectangle with rounded corners.
+// \param point The point to calculate the distance of.
+// \param rect The rectangle to calculate the distance of.
+// \param translation The amount of translation to apply to the rectangle.
+// \param radius A vec4 with the radius of each corner.
+lowp float sdf_rounded_rectangle(in lowp vec2 point, in lowp vec2 rect, in lowp vec2 translation, in lowp vec4 radius)
+{
+ radius.xy = (point.x > 0.0) ? radius.xy : radius.zw;
+ radius.x = (point.y > 0.0) ? radius.x : radius.y;
+ lowp vec2 d = abs(point - translation) - rect + radius.x;
+ return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - radius.x;
+}
+
+void main()
+{
+ // Scaling factor that is the inverse of the amount of scaling applied to the geometry.
+ lowp float inverse_scale = 1.0 / (1.0 + size + length(offset * 2.0));
+
+ // Correction factor to round the corners of a larger shadow.
+ // We want to account for size in regards to shadow radius, so that a larger shadow is
+ // more rounded, but only if we are not already rounding the corners due to corner radius.
+ lowp float size_factor = 0.5 * (minimum_shadow_radius / max(radius, minimum_shadow_radius));
+
+ lowp float shadowRadius = radius + size * size_factor;
+
+ lowp vec4 col = vec4(0.0);
+
+ // Calculate the shadow's distance field.
+ lowp float shadow = sdf_rounded_rectangle(uv, aspect * inverse_scale, offset * inverse_scale, vec4(shadowRadius * inverse_scale));
+ // Render it, interpolating the color over the distance.
+ col = mix(col, shadowColor * sign(size), shadowColor.a * (1.0 - smoothstep(-size * 0.5, size * 0.5, shadow)));
+
+ // Calculate the main rectangle distance field.
+ lowp float rect = sdf_rounded_rectangle(uv, aspect * inverse_scale, vec2(0.0), vec4(radius * inverse_scale));
+
+ lowp float g = fwidth(rect);
+
+ // First, remove anything that was rendered by the shadow if it is inside the rectangle.
+ // This allows us to use colors with alpha without rendering artifacts.
+ col = mix(col, vec4(0.0), 1.0 - smoothstep(0.001 - g, 0.001 + g, rect));
+
+ // Then, render it again but this time with the proper color and properly alpha blended.
+ col = mix(col, color, color.a * (1.0 - smoothstep(0.001 - g, 0.001 + g, rect)));
+
+ gl_FragColor = col * opacity;
+}
diff --git a/src/scenegraph/shadowedrectangle_core.vert b/src/scenegraph/shadowedrectangle_core.vert
new file mode 100644
index 00000000..8daeaadb
--- /dev/null
+++ b/src/scenegraph/shadowedrectangle_core.vert
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020 Arjen Hiemstra
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2, 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 Library General Public License for more details
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+uniform mat4 matrix;
+uniform vec2 aspect;
+uniform vec2 offset;
+
+in vec4 in_vertex;
+in vec2 in_uv;
+
+out vec2 uv;
+
+void main() {
+ uv = (-1.0 + 2.0 * in_uv) * aspect;
+ gl_Position = matrix * in_vertex;
+}