better quickshell

This commit is contained in:
2026-03-06 14:12:18 +01:00
parent d4f83bc941
commit ca514ac2fa
158 changed files with 14613 additions and 7286 deletions
@@ -0,0 +1,98 @@
#version 450
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(binding = 1) uniform sampler2D source;
layout(std140, binding = 0) uniform buf {
mat4 qt_Matrix;
float qt_Opacity;
// Custom properties with non-conflicting names
float itemWidth;
float itemHeight;
float sourceWidth;
float sourceHeight;
float cornerRadius;
float imageOpacity;
int fillMode;
} ubuf;
// Function to calculate the signed distance from a point to a rounded box
float roundedBoxSDF(vec2 centerPos, vec2 boxSize, float radius) {
vec2 d = abs(centerPos) - boxSize + radius;
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - radius;
}
void main() {
// Get size from uniforms
vec2 itemSize = vec2(ubuf.itemWidth, ubuf.itemHeight);
vec2 sourceSize = vec2(ubuf.sourceWidth, ubuf.sourceHeight);
float cornerRadius = ubuf.cornerRadius;
float itemOpacity = ubuf.imageOpacity;
int fillMode = ubuf.fillMode;
// Work in pixel space for accurate rounded rectangle calculation
vec2 pixelPos = qt_TexCoord0 * itemSize;
// Calculate UV coordinates based on fill mode
vec2 imageUV = qt_TexCoord0;
// fillMode constants from Qt:
// Image.Stretch = 0
// Image.PreserveAspectFit = 1
// Image.PreserveAspectCrop = 2
// Image.Tile = 3
// Image.TileVertically = 4
// Image.TileHorizontally = 5
// Image.Pad = 6
// Rounded corners always apply to full item bounds
vec2 roundedSize = itemSize;
vec2 roundedCenter = itemSize * 0.5;
// Track if pixel is in letterbox area (for PreserveAspectFit)
bool inLetterbox = false;
if (fillMode == 1) { // PreserveAspectFit
float itemAspect = itemSize.x / itemSize.y;
float sourceAspect = sourceSize.x / sourceSize.y;
if (sourceAspect > itemAspect) {
// Image is wider than item, letterbox top/bottom
imageUV.y = (qt_TexCoord0.y - 0.5) * (sourceAspect / itemAspect) + 0.5;
} else {
// Image is taller than item, letterbox left/right
imageUV.x = (qt_TexCoord0.x - 0.5) * (itemAspect / sourceAspect) + 0.5;
}
// Check if in letterbox area
inLetterbox = (imageUV.x < 0.0 || imageUV.x > 1.0 || imageUV.y < 0.0 || imageUV.y > 1.0);
} else if (fillMode == 2) { // PreserveAspectCrop
float itemAspect = itemSize.x / itemSize.y;
float sourceAspect = sourceSize.x / sourceSize.y;
if (sourceAspect > itemAspect) {
// Image is wider than item, crop left/right.
imageUV.x = (qt_TexCoord0.x - 0.5) * (itemAspect / sourceAspect) + 0.5;
} else {
// Image is taller than item, crop top/bottom.
imageUV.y = (qt_TexCoord0.y - 0.5) * (sourceAspect / itemAspect) + 0.5;
}
}
// For Stretch (0) or other modes, use qt_TexCoord0 as-is
// Calculate distance to rounded rectangle edge using the correct bounds
vec2 centerOffset = pixelPos - roundedCenter;
float distance = roundedBoxSDF(centerOffset, roundedSize * 0.5, cornerRadius);
// Create smooth alpha mask for edge with anti-aliasing
float alpha = 1.0 - smoothstep(-0.5, 0.5, distance);
// Sample the texture (or use transparent for letterbox)
vec4 color = inLetterbox ? vec4(0.0) : texture(source, imageUV);
// Apply the rounded mask and opacity
float finalAlpha = color.a * alpha * itemOpacity * ubuf.qt_Opacity;
fragColor = vec4(color.rgb * finalAlpha, finalAlpha);
}
@@ -0,0 +1,123 @@
#version 450
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 time;
float itemWidth;
float itemHeight;
vec4 bgColor;
float cornerRadius;
float alternative;
} ubuf;
// Signed distance function for rounded rectangle
float roundedBoxSDF(vec2 center, vec2 size, float radius) {
vec2 q = abs(center) - size + radius;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
}
float hash(vec2 p) {
p = fract(p * vec2(234.34, 435.345));
p += dot(p, p + 34.23);
return fract(p.x * p.y);
}
// Perlin-like noise
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
f = f * f * (3.0 - 2.0 * f); // Smooth interpolation
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}
// Turbulent noise for natural fog
float turbulence(vec2 p, float iTime) {
float t = 0.0;
float scale = 1.0;
for(int i = 0; i < 5; i++) {
t += abs(noise(p * scale + iTime * 0.1 * scale)) / scale;
scale *= 2.0;
}
return t;
}
void main() {
vec2 uv = qt_TexCoord0;
vec4 col = vec4(ubuf.bgColor.rgb, 1.0);
// Different parameters for fog vs clouds
float timeSpeed, layerScale1, layerScale2, layerScale3;
float flowSpeed1, flowSpeed2;
float densityMin, densityMax;
float baseOpacity;
float pulseAmount;
if (ubuf.alternative > 0.5) {
// Fog: slower, larger scale, more uniform
timeSpeed = 0.03;
layerScale1 = 1.0;
layerScale2 = 2.5;
layerScale3 = 2.0;
flowSpeed1 = 0.00;
flowSpeed2 = 0.02;
densityMin = 0.1;
densityMax = 0.9;
baseOpacity = 0.75;
pulseAmount = 0.05;
} else {
// Clouds: faster, smaller scale, puffier
timeSpeed = 0.08;
layerScale1 = 2.0;
layerScale2 = 4.0;
layerScale3 = 6.0;
flowSpeed1 = 0.03;
flowSpeed2 = 0.04;
densityMin = 0.35;
densityMax = 0.75;
baseOpacity = 0.4;
pulseAmount = 0.15;
}
float iTime = ubuf.time * timeSpeed;
// Create flowing patterns with multiple layers
vec2 flow1 = vec2(iTime * flowSpeed1, iTime * flowSpeed1 * 0.7);
vec2 flow2 = vec2(-iTime * flowSpeed2, iTime * flowSpeed2 * 0.8);
float fog1 = noise(uv * layerScale1 + flow1);
float fog2 = noise(uv * layerScale2 + flow2);
float fog3 = turbulence(uv * layerScale3, iTime);
float fogPattern = fog1 * 0.5 + fog2 * 0.3 + fog3 * 0.2;
float fogDensity = smoothstep(densityMin, densityMax, fogPattern);
// Gentle pulsing
float pulse = sin(iTime * 0.4) * pulseAmount + (1.0 - pulseAmount);
fogDensity *= pulse;
vec3 hazeColor = vec3(0.88, 0.90, 0.93);
float hazeOpacity = fogDensity * baseOpacity;
vec3 fogContribution = hazeColor * hazeOpacity;
float fogAlpha = hazeOpacity;
vec3 resultRGB = fogContribution + col.rgb * (1.0 - fogAlpha);
float resultAlpha = fogAlpha + col.a * (1.0 - fogAlpha);
// Calculate corner mask
vec2 pixelPos = qt_TexCoord0 * vec2(ubuf.itemWidth, ubuf.itemHeight);
vec2 center = pixelPos - vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
vec2 halfSize = vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
float dist = roundedBoxSDF(center, halfSize, ubuf.cornerRadius);
float cornerMask = 1.0 - smoothstep(-1.0, 0.0, dist);
// Apply global opacity and corner mask
float finalAlpha = resultAlpha * ubuf.qt_Opacity * cornerMask;
fragColor = vec4(resultRGB * (finalAlpha / max(resultAlpha, 0.001)), finalAlpha);
}
@@ -0,0 +1,84 @@
#version 450
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(binding = 1) uniform sampler2D source;
layout(std140, binding = 0) uniform buf {
mat4 qt_Matrix;
float qt_Opacity;
float time;
float itemWidth;
float itemHeight;
vec4 bgColor;
float cornerRadius;
} ubuf;
// Signed distance function for rounded rectangle
float roundedBoxSDF(vec2 center, vec2 size, float radius) {
vec2 q = abs(center) - size + radius;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
}
vec3 hash3(vec2 p) {
vec3 q = vec3(dot(p, vec2(127.1, 311.7)),
dot(p, vec2(269.5, 183.3)),
dot(p, vec2(419.2, 371.9)));
return fract(sin(q) * 43758.5453);
}
float noise(vec2 x, float iTime) {
vec2 p = floor(x);
vec2 f = fract(x);
float va = 0.0;
for (int j = -2; j <= 2; j++) {
for (int i = -2; i <= 2; i++) {
vec2 g = vec2(float(i), float(j));
vec3 o = hash3(p + g);
vec2 r = g - f + o.xy;
float d = sqrt(dot(r, r));
float ripple = max(mix(smoothstep(0.99, 0.999, max(cos(d - iTime * 2.0 + (o.x + o.y) * 5.0), 0.0)), 0.0, d), 0.0);
va += ripple;
}
}
return va;
}
void main() {
vec2 uv = qt_TexCoord0;
float iTime = ubuf.time * 0.07;
// Aspect ratio correction for circular ripples
float aspect = ubuf.itemWidth / ubuf.itemHeight;
vec2 uvAspect = vec2(uv.x * aspect, uv.y);
float f = noise(6.0 * uvAspect, iTime) * smoothstep(0.0, 0.2, sin(uv.x * 3.141592) * sin(uv.y * 3.141592));
// Calculate normal from noise for distortion
float normalScale = 0.5;
vec2 e = normalScale / vec2(ubuf.itemWidth, ubuf.itemHeight);
vec2 eAspect = vec2(e.x * aspect, e.y);
float cx = noise(6.0 * (uvAspect + eAspect), iTime) * smoothstep(0.0, 0.2, sin((uv.x + e.x) * 3.141592) * sin(uv.y * 3.141592));
float cy = noise(6.0 * (uvAspect + eAspect.yx), iTime) * smoothstep(0.0, 0.2, sin(uv.x * 3.141592) * sin((uv.y + e.y) * 3.141592));
vec2 n = vec2(cx - f, cy - f);
// Scale distortion back to texture space (undo aspect correction for X)
vec2 distortion = vec2(n.x / aspect, n.y);
// Sample source with distortion
vec4 col = texture(source, uv + distortion);
// Apply rounded corner mask
vec2 pixelPos = qt_TexCoord0 * vec2(ubuf.itemWidth, ubuf.itemHeight);
vec2 center = pixelPos - vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
vec2 halfSize = vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
float dist = roundedBoxSDF(center, halfSize, ubuf.cornerRadius);
float cornerMask = 1.0 - smoothstep(-1.0, 0.0, dist);
// Output with premultiplied alpha
float finalAlpha = col.a * ubuf.qt_Opacity * cornerMask;
fragColor = vec4(col.rgb * finalAlpha, finalAlpha);
}
@@ -0,0 +1,75 @@
#version 450
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 time;
float itemWidth;
float itemHeight;
vec4 bgColor;
float cornerRadius;
} ubuf;
// Signed distance function for rounded rectangle
float roundedBoxSDF(vec2 center, vec2 size, float radius) {
vec2 q = abs(center) - size + radius;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
}
void main() {
// Aspect ratio correction
float aspect = ubuf.itemWidth / ubuf.itemHeight;
vec2 uv = qt_TexCoord0;
uv.x *= aspect;
uv.y = 1.0 - uv.y;
float iTime = ubuf.time * 0.15;
float snow = 0.0;
for (int k = 0; k < 6; k++) {
for (int i = 0; i < 12; i++) {
float cellSize = 2.0 + (float(i) * 3.0);
float downSpeed = 0.3 + (sin(iTime * 0.4 + float(k + i * 20)) + 1.0) * 0.00008;
vec2 uvAnim = uv + vec2(
0.01 * sin((iTime + float(k * 6185)) * 0.6 + float(i)) * (5.0 / float(i + 1)),
downSpeed * (iTime + float(k * 1352)) * (1.0 / float(i + 1))
);
vec2 uvStep = (ceil((uvAnim) * cellSize - vec2(0.5, 0.5)) / cellSize);
float x = fract(sin(dot(uvStep.xy, vec2(12.9898 + float(k) * 12.0, 78.233 + float(k) * 315.156))) * 43758.5453 + float(k) * 12.0) - 0.5;
float y = fract(sin(dot(uvStep.xy, vec2(62.2364 + float(k) * 23.0, 94.674 + float(k) * 95.0))) * 62159.8432 + float(k) * 12.0) - 0.5;
float randomMagnitude1 = sin(iTime * 2.5) * 0.7 / cellSize;
float randomMagnitude2 = cos(iTime * 1.65) * 0.7 / cellSize;
float d = 5.0 * distance((uvStep.xy + vec2(x * sin(y), y) * randomMagnitude1 + vec2(y, x) * randomMagnitude2), uvAnim.xy);
float omiVal = fract(sin(dot(uvStep.xy, vec2(32.4691, 94.615))) * 31572.1684);
if (omiVal < 0.03) {
float newd = (x + 1.0) * 0.4 * clamp(1.9 - d * (15.0 + (x * 6.3)) * (cellSize / 1.4), 0.0, 1.0);
snow += newd;
}
}
}
// Blend white snow over background color
float snowAlpha = clamp(snow * 2.0, 0.0, 1.0);
vec3 snowColor = vec3(1.0);
vec3 blended = mix(ubuf.bgColor.rgb, snowColor, snowAlpha);
// Apply rounded corner mask
vec2 pixelPos = qt_TexCoord0 * vec2(ubuf.itemWidth, ubuf.itemHeight);
vec2 center = pixelPos - vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
vec2 halfSize = vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
float dist = roundedBoxSDF(center, halfSize, ubuf.cornerRadius);
float cornerMask = 1.0 - smoothstep(-1.0, 0.0, dist);
// Output with premultiplied alpha
float finalAlpha = ubuf.qt_Opacity * cornerMask;
fragColor = vec4(blended * finalAlpha, finalAlpha);
}
@@ -0,0 +1,130 @@
#version 450
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 time;
float itemWidth;
float itemHeight;
vec4 bgColor;
float cornerRadius;
} ubuf;
// Signed distance function for rounded rectangle
float roundedBoxSDF(vec2 center, vec2 size, float radius) {
vec2 q = abs(center) - size + radius;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
}
float hash(vec2 p) {
p = fract(p * vec2(234.34, 435.345));
p += dot(p, p + 34.23);
return fract(p.x * p.y);
}
vec2 hash2(vec2 p) {
p = fract(p * vec2(234.34, 435.345));
p += dot(p, p + 34.23);
return fract(vec2(p.x * p.y, p.y * p.x));
}
float stars(vec2 uv, float density, float iTime) {
vec2 gridUV = uv * density;
vec2 gridID = floor(gridUV);
vec2 gridPos = fract(gridUV);
float starField = 0.0;
// Check neighboring cells for stars
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
vec2 offset = vec2(float(x), float(y));
vec2 cellID = gridID + offset;
// Random position within cell
vec2 starPos = hash2(cellID);
// Only create a star for some cells (sparse distribution)
float starChance = hash(cellID + vec2(12.345, 67.890));
if (starChance > 0.85) {
// Star position in grid space
vec2 toStar = (offset + starPos - gridPos);
float dist = length(toStar) * density; // Scale distance to pixel space
float starSize = 1.5;
// Star brightness variation
float brightness = hash(cellID + vec2(23.456, 78.901)) * 0.6 + 0.4;
// Twinkling effect
float twinkleSpeed = hash(cellID + vec2(34.567, 89.012)) * 3.0 + 2.0;
float twinklePhase = iTime * twinkleSpeed + hash(cellID) * 6.28;
float twinkle = pow(sin(twinklePhase) * 0.5 + 0.5, 3.0); // Sharp on/off
// Sharp star core
float star = 0.0;
if (dist < starSize) {
star = 1.0 * brightness * (0.3 + twinkle * 0.7);
// Add tiny cross-shaped glow for brighter stars
if (brightness > 0.7) {
float crossGlow = max(
exp(-abs(toStar.x) * density * 5.0),
exp(-abs(toStar.y) * density * 5.0)
) * 0.3 * twinkle;
star += crossGlow;
}
}
starField += star;
}
}
}
return starField;
}
void main() {
vec2 uv = qt_TexCoord0;
float iTime = ubuf.time * 0.01;
// Base background color
vec4 col = vec4(ubuf.bgColor.rgb, 1.0);
// Aspect ratio for consistent stars
float aspect = ubuf.itemWidth / ubuf.itemHeight;
vec2 uvAspect = vec2(uv.x * aspect, uv.y);
// Generate multiple layers of stars at different densities
float stars1 = stars(uvAspect, 40.0, iTime); // Tiny distant stars
float stars2 = stars(uvAspect + vec2(0.5, 0.3), 25.0, iTime * 1.3); // Small stars
float stars3 = stars(uvAspect + vec2(0.25, 0.7), 15.0, iTime * 0.9); // Bigger stars
// Star colors with slight variation
vec3 starColor1 = vec3(0.85, 0.9, 1.0); // Faint blue-white
vec3 starColor2 = vec3(0.95, 0.97, 1.0); // White
vec3 starColor3 = vec3(1.0, 0.98, 0.95); // Warm white
// Combine star layers
vec3 starsRGB = starColor1 * stars1 * 0.6 +
starColor2 * stars2 * 0.8 +
starColor3 * stars3 * 1.0;
float starsAlpha = clamp(stars1 * 0.6 + stars2 * 0.8 + stars3, 0.0, 1.0);
// Apply rounded corner mask
vec2 pixelPos = qt_TexCoord0 * vec2(ubuf.itemWidth, ubuf.itemHeight);
vec2 center = pixelPos - vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
vec2 halfSize = vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
float dist = roundedBoxSDF(center, halfSize, ubuf.cornerRadius);
float cornerMask = 1.0 - smoothstep(-1.0, 0.0, dist);
// Add stars on top
vec3 resultRGB = starsRGB * starsAlpha + col.rgb * (1.0 - starsAlpha);
float resultAlpha = starsAlpha + col.a * (1.0 - starsAlpha);
// Apply global opacity and corner mask
float finalAlpha = resultAlpha * ubuf.qt_Opacity * cornerMask;
fragColor = vec4(resultRGB * (finalAlpha / max(resultAlpha, 0.001)), finalAlpha);
}
@@ -0,0 +1,148 @@
#version 450
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 time;
float itemWidth;
float itemHeight;
vec4 bgColor;
float cornerRadius;
} ubuf;
// Signed distance function for rounded rectangle
float roundedBoxSDF(vec2 center, vec2 size, float radius) {
vec2 q = abs(center) - size + radius;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
}
float hash(vec2 p) {
p = fract(p * vec2(234.34, 435.345));
p += dot(p, p + 34.23);
return fract(p.x * p.y);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}
// God rays originating from sun position
float sunRays(vec2 uv, vec2 sunPos, float iTime) {
vec2 toSun = uv - sunPos;
float angle = atan(toSun.y, toSun.x);
float dist = length(toSun);
float rayCount = 7;
// Radial pattern
float rays = sin(angle * rayCount + sin(iTime * 0.25)) * 0.5 + 0.5;
rays = pow(rays, 3.0);
// Fade with distance
float falloff = 1.0 - smoothstep(0.0, 1.2, dist);
return rays * falloff * 0.15;
}
// Atmospheric shimmer / heat haze
float atmosphericShimmer(vec2 uv, float iTime) {
// Multiple layers of noise for complexity
float n1 = noise(uv * 5.0 + vec2(iTime * 0.1, iTime * 0.05));
float n2 = noise(uv * 8.0 - vec2(iTime * 0.08, iTime * 0.12));
float n3 = noise(uv * 12.0 + vec2(iTime * 0.15, -iTime * 0.1));
return (n1 * 0.5 + n2 * 0.3 + n3 * 0.2) * 0.15;
}
float sunCore(vec2 uv, vec2 sunPos, float iTime) {
vec2 toSun = uv - sunPos;
float dist = length(toSun);
// Main bright spot
float mainFlare = exp(-dist * 15.0) * 2.0;
// Secondary reflection spots along the line
float flares = 0.0;
for (int i = 1; i <= 3; i++) {
vec2 flarePos = sunPos + toSun * float(i) * 0.3;
float flareDist = length(uv - flarePos);
float flareSize = 0.02 + float(i) * 0.01;
flares += smoothstep(flareSize * 2.0, flareSize * 0.5, flareDist) * (0.3 / float(i));
}
// Pulsing effect
float pulse = sin(iTime) * 0.1 + 0.9;
return (mainFlare + flares) * pulse;
}
void main() {
vec2 uv = qt_TexCoord0;
float iTime = ubuf.time * 0.08;
// Sample the source
vec4 col = vec4(ubuf.bgColor.rgb, 1.0);
vec2 sunPos = vec2(0.85, 0.2);
// Aspect ratio correction
float aspect = ubuf.itemWidth / ubuf.itemHeight;
vec2 uvAspect = vec2(uv.x * aspect, uv.y);
vec2 sunPosAspect = vec2(sunPos.x * aspect, sunPos.y);
// Generate sunny effects
float rays = sunRays(uvAspect, sunPosAspect, iTime);
float shimmerEffect = atmosphericShimmer(uv, iTime);
float flare = sunCore(uvAspect, sunPosAspect, iTime);
// Warm sunny colors
vec3 sunColor = vec3(1.0, 0.95, 0.7); // Warm golden yellow
vec3 skyColor = vec3(0.9, 0.95, 1.0); // Light blue tint
vec3 shimmerColor = vec3(1.0, 0.98, 0.85); // Subtle warm shimmer
// Apply rounded corner mask
vec2 pixelPos = qt_TexCoord0 * vec2(ubuf.itemWidth, ubuf.itemHeight);
vec2 center = pixelPos - vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
vec2 halfSize = vec2(ubuf.itemWidth, ubuf.itemHeight) * 0.5;
float dist = roundedBoxSDF(center, halfSize, ubuf.cornerRadius);
float cornerMask = 1.0 - smoothstep(-1.0, 0.0, dist);
vec3 resultRGB = col.rgb;
float resultAlpha = col.a;
// Add sun rays
vec3 raysContribution = sunColor * rays;
float raysAlpha = rays * 0.4;
resultRGB = raysContribution + resultRGB * (1.0 - raysAlpha);
resultAlpha = raysAlpha + resultAlpha * (1.0 - raysAlpha);
// Add atmospheric shimmer
vec3 shimmerContribution = shimmerColor * shimmerEffect;
float shimmerAlpha = shimmerEffect * 0.1;
resultRGB = shimmerContribution + resultRGB * (1.0 - shimmerAlpha);
resultAlpha = shimmerAlpha + resultAlpha * (1.0 - shimmerAlpha);
// Add bright sun core
vec3 flareContribution = sunColor * flare;
float flareAlpha = clamp(flare, 0.0, 1.0) * 0.6;
resultRGB = flareContribution + resultRGB * (1.0 - flareAlpha);
resultAlpha = flareAlpha + resultAlpha * (1.0 - flareAlpha);
// Overall warm sunny tint
resultRGB = mix(resultRGB, resultRGB * vec3(1.08, 1.04, 0.98), 0.15);
// Apply global opacity and corner mask
float finalAlpha = resultAlpha * ubuf.qt_Opacity * cornerMask;
fragColor = vec4(resultRGB * (finalAlpha / max(resultAlpha, 0.001)), finalAlpha);
}