#version 440 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; vec2 itemSize; vec2 rectSize; float radius; float glowSize; float innerGlow; float lineWidth; float phase; float intensity; vec4 color1; vec4 color2; vec4 color3; vec4 color4; }; const float TAU = 6.28318530718; float sdRoundBox(vec2 p, vec2 halfSize, float r) { vec2 q = abs(p) - (halfSize - r); return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r; } vec3 palette(float t) { t = fract(t) * 4.0; float f = smoothstep(0.0, 1.0, fract(t)); if (t < 1.0) return mix(color1.rgb, color2.rgb, f); if (t < 2.0) return mix(color2.rgb, color3.rgb, f); if (t < 3.0) return mix(color3.rgb, color4.rgb, f); return mix(color4.rgb, color1.rgb, f); } float hash(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); } void main() { vec2 p = (qt_TexCoord0 - 0.5) * itemSize; float r = clamp(radius, 0.0, min(rectSize.x, rectSize.y) * 0.5); float d = sdRoundBox(p, rectSize * 0.5, r); // ~1px antialiasing width float aa = max(fwidth(d), 0.75); // Coverage of the shape: 1 inside, 0 outside, soft across the edge float inside = 1.0 - smoothstep(-aa, aa, d); // Only skip work when clearly outside and there's no outer glow if (glowSize <= 0.0 && d > aa) { fragColor = vec4(0.0); return; } float ang = atan(p.y, p.x); float a2 = phase * TAU; float u = ang / TAU + 0.5 + phase; u += 0.07 * sin(ang * 2.0 + a2) + 0.04 * sin(ang * 3.0 - a2 * 2.0); vec3 col = palette(u); float g = 0.0; if (d > 0.0) { float t = clamp(d / max(glowSize, 0.001), 0.0, 1.0); g = (glowSize > 0.0) ? pow(1.0 - t, 3.0) : 0.0; } else if (innerGlow > 0.0) { float t = clamp(-d / innerGlow, 0.0, 1.0); g = pow(1.0 - t, 3.0); } float pulse = 0.9 + 0.1 * sin(a2 * 2.0 + ang); g *= pulse; // Line: inside only, with a soft inner edge AND a soft outer edge float line = 0.0; if (lineWidth > 0.0) { float inner = 1.0 - smoothstep(lineWidth - aa, lineWidth + aa, -d); line = inner * inside; } float a = clamp(g * intensity + line * 0.9, 0.0, 1.0); // Antialias the outer silhouette when there is no outer glow if (glowSize <= 0.0) a *= inside; col = mix(col, vec3(1.0), line * 0.25); a += (hash(gl_FragCoord.xy) - 0.5) / 255.0; a = clamp(a, 0.0, 1.0); fragColor = vec4(col * a, a) * qt_Opacity; }