fedora
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
#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;
|
||||
vec4 targetColor;
|
||||
float colorizeMode; // 0.0 = dock mode (grayscale), 1.0 = tray mode (intensity), 2.0 = distro mode (luminance with better contrast)
|
||||
} ubuf;
|
||||
|
||||
void main() {
|
||||
vec4 tex = texture(source, qt_TexCoord0);
|
||||
|
||||
float intensity;
|
||||
|
||||
if (ubuf.colorizeMode < 0.5) {
|
||||
// Dock mode: Convert to grayscale using proper luminance weights
|
||||
intensity = dot(tex.rgb, vec3(0.299, 0.587, 0.114));
|
||||
} else if (ubuf.colorizeMode < 1.5) {
|
||||
// Tray mode: Use the maximum RGB channel value as intensity
|
||||
intensity = max(max(tex.r, tex.g), tex.b);
|
||||
|
||||
// Normalize intensity to make all icons more uniform
|
||||
intensity = smoothstep(0.1, 0.9, intensity);
|
||||
} else {
|
||||
// Distro mode: Brightness boost with proper alpha handling
|
||||
float maxChannel = max(max(tex.r, tex.g), tex.b);
|
||||
|
||||
intensity = maxChannel * 1.5;
|
||||
intensity = min(intensity, 1.0);
|
||||
intensity = intensity * 0.7 + 0.3;
|
||||
|
||||
intensity = intensity * tex.a;
|
||||
|
||||
fragColor = vec4(ubuf.targetColor.rgb * intensity, tex.a) * ubuf.qt_Opacity;
|
||||
}
|
||||
|
||||
fragColor = vec4(ubuf.targetColor.rgb * intensity, tex.a) * ubuf.qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf
|
||||
{
|
||||
mat4 qt_Matrix;
|
||||
vec4 params; // x=opacity, y=fixedVal, z=mode, w=padding
|
||||
};
|
||||
|
||||
// Compatibility function for GLSL ES to avoid % operator issues
|
||||
int mod_compat(float a, float b) {
|
||||
return int(a - floor(a / b) * b);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float x = qt_TexCoord0.x;
|
||||
float y = 1.0 - qt_TexCoord0.y; // Flip Y direction
|
||||
|
||||
// Unpack vector
|
||||
float opacity = params.x;
|
||||
float fixedVal = params.y;
|
||||
float mode = params.z + 0.1; // +0.1 safely handles float rounding
|
||||
|
||||
// Build permutation matrices for swizzling
|
||||
vec3 base = vec3(x, y, fixedVal);
|
||||
|
||||
// Determine Mode Logic
|
||||
// 0: (Red/Hue) 1: (Green/Sat) 2: (Blue/Val)
|
||||
int perm = mod_compat(mode, 3.0);
|
||||
|
||||
float isHSV = step(3.0, mode);
|
||||
|
||||
// Branchless Selection
|
||||
vec3 mask = vec3(
|
||||
float(perm == 0),
|
||||
float(perm == 1),
|
||||
float(perm == 2));
|
||||
|
||||
// Swizzle fo shizzle
|
||||
// If perm 0: base.zxy -> (fixedVal, x, y)
|
||||
// If perm 1: base.xzy -> (x, fixedVal, y)
|
||||
// If perm 2: base.xyz -> (x, y, fixedVal)
|
||||
vec3 rgb_base = (base.zxy * mask.x) + (base.xzy * mask.y) + (base.xyz * mask.z);
|
||||
|
||||
// Final mix
|
||||
vec3 finalColor = mix(rgb_base, hsv2rgb(rgb_base), isHSV);
|
||||
|
||||
fragColor = vec4(finalColor, 1.0) * opacity;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D dataSource;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
vec4 lineColor1;
|
||||
vec4 lineColor2;
|
||||
float count1;
|
||||
float count2;
|
||||
float scroll1;
|
||||
float scroll2;
|
||||
float lineWidth;
|
||||
float graphFillOpacity;
|
||||
float texWidth;
|
||||
float resY;
|
||||
float aaSize;
|
||||
};
|
||||
|
||||
// Sample normalized value from data texture
|
||||
// channel 0 = primary (R), channel 1 = secondary (G)
|
||||
float fetchData(float idx, int ch) {
|
||||
float i = clamp(idx, 0.0, texWidth - 1.0);
|
||||
float u = (floor(i) + 0.5) / texWidth;
|
||||
vec4 t = texture(dataSource, vec2(u, 0.5));
|
||||
return ch == 0 ? t.r : t.g;
|
||||
}
|
||||
|
||||
// Cubic Hermite interpolation with reduced tangent scale for smooth curves
|
||||
float cubicHermite(float y0, float y1, float y2, float y3, float t) {
|
||||
float m1 = (y2 - y0) * 0.25;
|
||||
float m2 = (y3 - y1) * 0.25;
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
return (2.0 * t3 - 3.0 * t2 + 1.0) * y1
|
||||
+ (t3 - 2.0 * t2 + t) * m1
|
||||
+ (-2.0 * t3 + 3.0 * t2) * y2
|
||||
+ (t3 - t2) * m2;
|
||||
}
|
||||
|
||||
// Evaluate curve at fractional data index
|
||||
float evalCurve(float dataIdx, int ch) {
|
||||
float i = floor(dataIdx);
|
||||
float t = dataIdx - i;
|
||||
return cubicHermite(
|
||||
fetchData(i - 1.0, ch),
|
||||
fetchData(i, ch),
|
||||
fetchData(i + 1.0, ch),
|
||||
fetchData(i + 2.0, ch),
|
||||
t
|
||||
);
|
||||
}
|
||||
|
||||
// Squared distance from point p to line segment a→b
|
||||
float segDistSq(vec2 p, vec2 a, vec2 b) {
|
||||
vec2 ab = b - a;
|
||||
float len2 = dot(ab, ab);
|
||||
float t = len2 > 0.0 ? clamp(dot(p - a, ab) / len2, 0.0, 1.0) : 0.0;
|
||||
vec2 proj = a + t * ab;
|
||||
vec2 d = p - proj;
|
||||
return dot(d, d);
|
||||
}
|
||||
|
||||
// Minimum distance from fragment to curve via multi-segment sampling.
|
||||
// Samples the curve at 9 half-pixel-spaced x-positions (±2px neighborhood)
|
||||
// and returns the minimum distance to the 8 line segments between them.
|
||||
float curveDistance(float dataIdx, float pixStep, float normY, int ch) {
|
||||
vec2 frag = vec2(0.0, normY * resY);
|
||||
|
||||
float px = -2.0;
|
||||
float py = evalCurve(dataIdx - 2.0 * pixStep, ch) * resY;
|
||||
vec2 d0 = frag - vec2(px, py);
|
||||
float best = dot(d0, d0);
|
||||
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
float cx = -2.0 + float(i) * 0.5;
|
||||
float cy = evalCurve(dataIdx + cx * pixStep, ch) * resY;
|
||||
best = min(best, segDistSq(frag, vec2(px, py), vec2(cx, cy)));
|
||||
px = cx;
|
||||
py = cy;
|
||||
}
|
||||
|
||||
return sqrt(best);
|
||||
}
|
||||
|
||||
// Premultiplied alpha over compositing
|
||||
vec4 blendOver(vec4 src, vec4 dst) {
|
||||
return src + dst * (1.0 - src.a);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
float normY = 1.0 - uv.y; // 0 = bottom, 1 = top
|
||||
|
||||
vec4 result = vec4(0.0);
|
||||
float halfW = lineWidth * 0.5;
|
||||
|
||||
// Primary line
|
||||
if (count1 >= 4.0) {
|
||||
float segs = count1 - 3.0;
|
||||
float di = 2.0 + scroll1 + uv.x * segs;
|
||||
float pixStep = dFdx(di);
|
||||
float cy = evalCurve(di, 0);
|
||||
float cyNext = evalCurve(di + pixStep, 0);
|
||||
|
||||
// Fill below curve (gradient: opaque at top, transparent at bottom)
|
||||
if (graphFillOpacity > 0.0 && normY <= cy) {
|
||||
float a = graphFillOpacity * normY * lineColor1.a;
|
||||
result = blendOver(vec4(lineColor1.rgb * a, a), result);
|
||||
}
|
||||
|
||||
// Multi-segment distance for accurate AA at peaks and steep sections.
|
||||
// AA width derived analytically from curve slope: (|sinθ|+|cosθ|)
|
||||
// gives the ideal SDF fwidth (~1.0–1.41) without GPU derivative noise.
|
||||
float dist = curveDistance(di, pixStep, normY, 0);
|
||||
float slope1 = (cyNext - cy) * resY;
|
||||
float aa = (abs(slope1) + 1.0) * inversesqrt(slope1 * slope1 + 1.0) * aaSize * 2.0;
|
||||
float sa = smoothstep(halfW + aa, halfW, dist) * lineColor1.a;
|
||||
result = blendOver(vec4(lineColor1.rgb * sa, sa), result);
|
||||
}
|
||||
|
||||
// Secondary line
|
||||
if (count2 >= 4.0) {
|
||||
float segs = count2 - 3.0;
|
||||
float di = 2.0 + scroll2 + uv.x * segs;
|
||||
float pixStep = dFdx(di);
|
||||
float cy = evalCurve(di, 1);
|
||||
float cyNext = evalCurve(di + pixStep, 1);
|
||||
|
||||
if (graphFillOpacity > 0.0 && normY <= cy) {
|
||||
float a = graphFillOpacity * normY * lineColor2.a;
|
||||
result = blendOver(vec4(lineColor2.rgb * a, a), result);
|
||||
}
|
||||
|
||||
float dist = curveDistance(di, pixStep, normY, 1);
|
||||
float slope2 = (cyNext - cy) * resY;
|
||||
float aa = (abs(slope2) + 1.0) * inversesqrt(slope2 * slope2 + 1.0) * aaSize * 2.0;
|
||||
float sa = smoothstep(halfW + aa, halfW, dist) * lineColor2.a;
|
||||
result = blendOver(vec4(lineColor2.rgb * sa, sa), result);
|
||||
}
|
||||
|
||||
fragColor = result * qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#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 progress;
|
||||
float borderWidth;
|
||||
vec4 progressColor;
|
||||
vec4 borderColor;
|
||||
vec4 backgroundColor;
|
||||
float borderRadius;
|
||||
} ubuf;
|
||||
|
||||
void main() {
|
||||
vec2 coord = qt_TexCoord0;
|
||||
float p = clamp(ubuf.progress, 0.0, 1.0);
|
||||
|
||||
if (ubuf.borderRadius > 0.0) {
|
||||
// Circular progress
|
||||
vec2 center = vec2(0.5, 0.5);
|
||||
vec2 dir = coord - center;
|
||||
float dist = length(dir);
|
||||
|
||||
float outerRadius = 0.5;
|
||||
float innerRadius = outerRadius - ubuf.borderWidth;
|
||||
|
||||
float angle = atan(dir.y, dir.x) + radians(90.0);
|
||||
if (angle < 0.0) angle += radians(360.0);
|
||||
float maxAngle = radians(360.0) * p;
|
||||
|
||||
bool inBorder = dist >= innerRadius && dist <= outerRadius;
|
||||
bool inProgress = inBorder && angle <= maxAngle;
|
||||
|
||||
if (inProgress) {
|
||||
fragColor = ubuf.progressColor * ubuf.qt_Opacity;
|
||||
} else if (inBorder) {
|
||||
fragColor = ubuf.borderColor * ubuf.qt_Opacity;
|
||||
} else if (dist < innerRadius) {
|
||||
fragColor = ubuf.backgroundColor * ubuf.qt_Opacity;
|
||||
} else {
|
||||
fragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
} else {
|
||||
// Rectangular progress
|
||||
bool inBorder =
|
||||
coord.x < ubuf.borderWidth ||
|
||||
coord.x > (1.0 - ubuf.borderWidth) ||
|
||||
coord.y < ubuf.borderWidth ||
|
||||
coord.y > (1.0 - ubuf.borderWidth);
|
||||
|
||||
float progressPos = p;
|
||||
bool inProgress = inBorder && coord.x <= progressPos;
|
||||
|
||||
if (inProgress) {
|
||||
fragColor = ubuf.progressColor * ubuf.qt_Opacity;
|
||||
} else if (inBorder) {
|
||||
fragColor = ubuf.borderColor * ubuf.qt_Opacity;
|
||||
} else {
|
||||
fragColor = ubuf.backgroundColor * ubuf.qt_Opacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
#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)
|
||||
// Clamp UV to prevent texture wrapping artifacts from floating-point imprecision
|
||||
vec4 color = inLetterbox ? vec4(0.0) : texture(source, clamp(imageUV, vec2(0.0), vec2(1.0)));
|
||||
|
||||
// Apply the rounded mask and opacity
|
||||
// Qt textures use premultiplied alpha (color.rgb already contains rgb * alpha),
|
||||
// so we only multiply by the external mask factors, not by color.a again
|
||||
float mask = alpha * itemOpacity * ubuf.qt_Opacity;
|
||||
fragColor = color * mask;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D dataSource;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
vec4 fillColor;
|
||||
float count;
|
||||
float texWidth;
|
||||
float vertical;
|
||||
float mirrored;
|
||||
};
|
||||
|
||||
// Sample amplitude from data texture (R channel)
|
||||
float fetchData(float idx) {
|
||||
float i = clamp(idx, 0.0, texWidth - 1.0);
|
||||
float u = (floor(i) + 0.5) / texWidth;
|
||||
return texture(dataSource, vec2(u, 0.5)).r;
|
||||
}
|
||||
|
||||
// Cubic Hermite interpolation for smooth wave curves
|
||||
float cubicHermite(float y0, float y1, float y2, float y3, float t) {
|
||||
float m1 = (y2 - y0) * 0.25;
|
||||
float m2 = (y3 - y1) * 0.25;
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
return (2.0 * t3 - 3.0 * t2 + 1.0) * y1
|
||||
+ (t3 - 2.0 * t2 + t) * m1
|
||||
+ (-2.0 * t3 + 3.0 * t2) * y2
|
||||
+ (t3 - t2) * m2;
|
||||
}
|
||||
|
||||
// Evaluate interpolated amplitude at fractional data index
|
||||
float evalCurve(float dataIdx) {
|
||||
float i = floor(dataIdx);
|
||||
float t = dataIdx - i;
|
||||
return cubicHermite(
|
||||
fetchData(i - 1.0),
|
||||
fetchData(i),
|
||||
fetchData(i + 1.0),
|
||||
fetchData(i + 2.0),
|
||||
t
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
|
||||
// Swap axes for vertical mode
|
||||
float axisPos = (vertical > 0.5) ? uv.y : uv.x;
|
||||
float crossPos = (vertical > 0.5) ? uv.x : uv.y;
|
||||
|
||||
// Map axis position to data index
|
||||
float dataIdx;
|
||||
if (mirrored > 0.5) {
|
||||
// Mirror: value[0] at center, value[count-1] at edges
|
||||
float distFromCenter = abs(axisPos - 0.5) * 2.0;
|
||||
dataIdx = distFromCenter * max(count - 1.0, 1.0);
|
||||
} else {
|
||||
// Linear: value[0] at left/top, value[count-1] at right/bottom
|
||||
dataIdx = axisPos * max(count - 1.0, 1.0);
|
||||
}
|
||||
|
||||
// Interpolated amplitude, clamped to valid range
|
||||
float amplitude = clamp(evalCurve(dataIdx), 0.0, 1.0);
|
||||
|
||||
// Wave fills center ± amplitude/2 in the cross axis
|
||||
float halfAmp = amplitude * 0.5;
|
||||
float distFromMid = abs(crossPos - 0.5);
|
||||
|
||||
// Antialiased edge (~1px smooth transition)
|
||||
float edge = fwidth(crossPos) * 1.5;
|
||||
float mask = smoothstep(halfAmp + edge, halfAmp - edge, distFromMid);
|
||||
|
||||
// Premultiplied alpha output
|
||||
float a = mask * fillColor.a;
|
||||
fragColor = vec4(fillColor.rgb * a, a) * qt_Opacity;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
// ===== wp_disc.frag =====
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D source1; // Current wallpaper
|
||||
layout(binding = 2) uniform sampler2D source2; // Next wallpaper
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float progress; // Transition progress (0.0 to 1.0)
|
||||
float centerX; // X coordinate of disc center (0.0 to 1.0)
|
||||
float centerY; // Y coordinate of disc center (0.0 to 1.0)
|
||||
float smoothness; // Edge smoothness (0.0 to 1.0, 0=sharp, 1=very smooth)
|
||||
float aspectRatio; // Width / Height of the screen
|
||||
|
||||
// Fill mode parameters
|
||||
float fillMode; // 0=center, 1=crop, 2=fit, 3=stretch, 4=repeat
|
||||
float imageWidth1; // Width of source1 image
|
||||
float imageHeight1; // Height of source1 image
|
||||
float imageWidth2; // Width of source2 image
|
||||
float imageHeight2; // Height of source2 image
|
||||
float screenWidth; // Screen width
|
||||
float screenHeight; // Screen height
|
||||
vec4 fillColor; // Fill color for empty areas (default: black)
|
||||
|
||||
// Solid color mode
|
||||
float isSolid1; // 1.0 if source1 is solid color, 0.0 otherwise
|
||||
float isSolid2; // 1.0 if source2 is solid color, 0.0 otherwise
|
||||
vec4 solidColor1; // Solid color for source1
|
||||
vec4 solidColor2; // Solid color for source2
|
||||
} ubuf;
|
||||
|
||||
// Calculate UV coordinates based on fill mode
|
||||
vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
|
||||
float imageAspect = imgWidth / imgHeight;
|
||||
float screenAspect = ubuf.screenWidth / ubuf.screenHeight;
|
||||
vec2 transformedUV = uv;
|
||||
|
||||
if (ubuf.fillMode < 0.5) {
|
||||
// Mode 0: no (center) - No resize, center image at original size
|
||||
// Convert UV to pixel coordinates, offset, then back to UV in image space
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imageOffset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - vec2(imgWidth, imgHeight)) * 0.5;
|
||||
vec2 imagePixel = screenPixel - imageOffset;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 1.5) {
|
||||
// Mode 1: crop (fill/cover) - Fill screen, crop excess (default)
|
||||
float scale = max(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (scaledImageSize - vec2(ubuf.screenWidth, ubuf.screenHeight)) / scaledImageSize;
|
||||
transformedUV = uv * (vec2(1.0) - offset) + offset * 0.5;
|
||||
}
|
||||
else if (ubuf.fillMode < 2.5) {
|
||||
// Mode 2: fit (contain) - Fit inside screen, maintain aspect ratio
|
||||
float scale = min(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - scaledImageSize) * 0.5;
|
||||
|
||||
// Convert screen UV to pixel coordinates
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
// Adjust for offset and scale
|
||||
vec2 imagePixel = (screenPixel - offset) / scale;
|
||||
// Convert back to UV coordinates in image space
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 3.5) {
|
||||
// Mode 3: stretch - Use original UV (stretches to fit)
|
||||
// No transformation needed for stretch mode
|
||||
}
|
||||
else {
|
||||
// Mode 4: repeat (tile) - Tile image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
transformedUV = screenPixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
|
||||
return transformedUV;
|
||||
}
|
||||
|
||||
// Sample texture with fill mode and handle out-of-bounds
|
||||
// If isSolid > 0.5, returns solidColor instead of sampling texture
|
||||
vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight, float isSolid, vec4 solidColor) {
|
||||
// Return solid color if in solid color mode
|
||||
if (isSolid > 0.5) {
|
||||
return solidColor;
|
||||
}
|
||||
|
||||
vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
|
||||
|
||||
// Mode 4 (repeat): use fract() to tile the image
|
||||
if (ubuf.fillMode > 3.5) {
|
||||
return texture(tex, fract(transformedUV));
|
||||
}
|
||||
|
||||
// Check if UV is out of bounds
|
||||
if (transformedUV.x < 0.0 || transformedUV.x > 1.0 ||
|
||||
transformedUV.y < 0.0 || transformedUV.y > 1.0) {
|
||||
return ubuf.fillColor;
|
||||
}
|
||||
|
||||
return texture(tex, transformedUV);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
|
||||
// Sample textures with fill mode (handles solid colors)
|
||||
vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1, ubuf.isSolid1, ubuf.solidColor1);
|
||||
vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2, ubuf.isSolid2, ubuf.solidColor2);
|
||||
|
||||
// Map smoothness from 0.0-1.0 to 0.001-0.5 range
|
||||
// Using a non-linear mapping for better control
|
||||
float mappedSmoothness = mix(0.001, 0.5, ubuf.smoothness * ubuf.smoothness);
|
||||
|
||||
// Adjust UV coordinates to compensate for aspect ratio
|
||||
// This makes distances circular instead of elliptical
|
||||
vec2 adjustedUV = vec2(uv.x * ubuf.aspectRatio, uv.y);
|
||||
vec2 adjustedCenter = vec2(ubuf.centerX * ubuf.aspectRatio, ubuf.centerY);
|
||||
|
||||
// Calculate distance in aspect-corrected space
|
||||
float dist = distance(adjustedUV, adjustedCenter);
|
||||
|
||||
// Calculate the maximum possible distance (corner to corner)
|
||||
// This ensures the disc can cover the entire screen
|
||||
float maxDistX = max(ubuf.centerX * ubuf.aspectRatio,
|
||||
(1.0 - ubuf.centerX) * ubuf.aspectRatio);
|
||||
float maxDistY = max(ubuf.centerY, 1.0 - ubuf.centerY);
|
||||
float maxDist = length(vec2(maxDistX, maxDistY));
|
||||
|
||||
// Scale progress to cover the maximum distance
|
||||
// Add extra range for smoothness to ensure complete coverage
|
||||
// Adjust smoothness for aspect ratio to maintain consistent visual appearance
|
||||
float adjustedSmoothness = mappedSmoothness * max(1.0, ubuf.aspectRatio);
|
||||
|
||||
// Start the radius from -adjustedSmoothness, this ensures the disc is completely hidden when progress=0
|
||||
float totalDistance = maxDist + 2.0 * adjustedSmoothness;
|
||||
float radius = -adjustedSmoothness + ubuf.progress * totalDistance;
|
||||
|
||||
// Use smoothstep for a smooth edge transition
|
||||
float factor = smoothstep(radius - adjustedSmoothness, radius + adjustedSmoothness, dist);
|
||||
|
||||
// Mix the textures (factor = 0 inside disc, 1 outside)
|
||||
fragColor = mix(color2, color1, factor);
|
||||
|
||||
fragColor *= ubuf.qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// ===== wp_fade.frag =====
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D source1;
|
||||
layout(binding = 2) uniform sampler2D source2;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float progress;
|
||||
|
||||
// Fill mode parameters
|
||||
float fillMode; // 0=center, 1=crop, 2=fit, 3=stretch, 4=repeat
|
||||
float imageWidth1; // Width of source1 image
|
||||
float imageHeight1; // Height of source1 image
|
||||
float imageWidth2; // Width of source2 image
|
||||
float imageHeight2; // Height of source2 image
|
||||
float screenWidth; // Screen width
|
||||
float screenHeight; // Screen height
|
||||
vec4 fillColor; // Fill color for empty areas (default: black)
|
||||
|
||||
// Solid color mode
|
||||
float isSolid1; // 1.0 if source1 is solid color, 0.0 otherwise
|
||||
float isSolid2; // 1.0 if source2 is solid color, 0.0 otherwise
|
||||
vec4 solidColor1; // Solid color for source1
|
||||
vec4 solidColor2; // Solid color for source2
|
||||
} ubuf;
|
||||
|
||||
// Calculate UV coordinates based on fill mode
|
||||
vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
|
||||
float imageAspect = imgWidth / imgHeight;
|
||||
float screenAspect = ubuf.screenWidth / ubuf.screenHeight;
|
||||
vec2 transformedUV = uv;
|
||||
|
||||
if (ubuf.fillMode < 0.5) {
|
||||
// Mode 0: no (center) - No resize, center image at original size
|
||||
// Convert UV to pixel coordinates, offset, then back to UV in image space
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imageOffset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - vec2(imgWidth, imgHeight)) * 0.5;
|
||||
vec2 imagePixel = screenPixel - imageOffset;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 1.5) {
|
||||
// Mode 1: crop (fill/cover) - Fill screen, crop excess (default)
|
||||
float scale = max(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (scaledImageSize - vec2(ubuf.screenWidth, ubuf.screenHeight)) / scaledImageSize;
|
||||
transformedUV = uv * (vec2(1.0) - offset) + offset * 0.5;
|
||||
}
|
||||
else if (ubuf.fillMode < 2.5) {
|
||||
// Mode 2: fit (contain) - Fit inside screen, maintain aspect ratio
|
||||
float scale = min(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - scaledImageSize) * 0.5;
|
||||
|
||||
// Convert screen UV to pixel coordinates
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
// Adjust for offset and scale
|
||||
vec2 imagePixel = (screenPixel - offset) / scale;
|
||||
// Convert back to UV coordinates in image space
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 3.5) {
|
||||
// Mode 3: stretch - Use original UV (stretches to fit)
|
||||
// No transformation needed for stretch mode
|
||||
}
|
||||
else {
|
||||
// Mode 4: repeat (tile) - Tile image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
transformedUV = screenPixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
|
||||
return transformedUV;
|
||||
}
|
||||
|
||||
// Sample texture with fill mode and handle out-of-bounds
|
||||
// If isSolid > 0.5, returns solidColor instead of sampling texture
|
||||
vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight, float isSolid, vec4 solidColor) {
|
||||
// Return solid color if in solid color mode
|
||||
if (isSolid > 0.5) {
|
||||
return solidColor;
|
||||
}
|
||||
|
||||
vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
|
||||
|
||||
// Mode 4 (repeat): use fract() to tile the image
|
||||
if (ubuf.fillMode > 3.5) {
|
||||
return texture(tex, fract(transformedUV));
|
||||
}
|
||||
|
||||
// Check if UV is out of bounds
|
||||
if (transformedUV.x < 0.0 || transformedUV.x > 1.0 ||
|
||||
transformedUV.y < 0.0 || transformedUV.y > 1.0) {
|
||||
return ubuf.fillColor;
|
||||
}
|
||||
|
||||
return texture(tex, transformedUV);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
|
||||
// Sample textures with fill mode (handles solid colors)
|
||||
vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1, ubuf.isSolid1, ubuf.solidColor1);
|
||||
vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2, ubuf.isSolid2, ubuf.solidColor2);
|
||||
|
||||
// Mix the two textures based on progress value
|
||||
fragColor = mix(color1, color2, ubuf.progress) * ubuf.qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
// ===== wp_honeycomb.frag =====
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D source1;
|
||||
layout(binding = 2) uniform sampler2D source2;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float progress;
|
||||
float cellSize; // Size of hexagonal cells in UV space (default 0.04)
|
||||
float centerX; // X coordinate of wave origin (0.0 to 1.0)
|
||||
float centerY; // Y coordinate of wave origin (0.0 to 1.0)
|
||||
float aspectRatio; // Width / Height of the screen
|
||||
|
||||
// Fill mode parameters
|
||||
float fillMode; // 0=center, 1=crop, 2=fit, 3=stretch, 4=repeat
|
||||
float imageWidth1; // Width of source1 image
|
||||
float imageHeight1; // Height of source1 image
|
||||
float imageWidth2; // Width of source2 image
|
||||
float imageHeight2; // Height of source2 image
|
||||
float screenWidth; // Screen width
|
||||
float screenHeight; // Screen height
|
||||
vec4 fillColor; // Fill color for empty areas (default: black)
|
||||
|
||||
// Solid color mode
|
||||
float isSolid1; // 1.0 if source1 is solid color, 0.0 otherwise
|
||||
float isSolid2; // 1.0 if source2 is solid color, 0.0 otherwise
|
||||
vec4 solidColor1; // Solid color for source1
|
||||
vec4 solidColor2; // Solid color for source2
|
||||
} ubuf;
|
||||
|
||||
// Calculate UV coordinates based on fill mode
|
||||
vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
|
||||
float imageAspect = imgWidth / imgHeight;
|
||||
float screenAspect = ubuf.screenWidth / ubuf.screenHeight;
|
||||
vec2 transformedUV = uv;
|
||||
|
||||
if (ubuf.fillMode < 0.5) {
|
||||
// Mode 0: no (center) - No resize, center image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imageOffset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - vec2(imgWidth, imgHeight)) * 0.5;
|
||||
vec2 imagePixel = screenPixel - imageOffset;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 1.5) {
|
||||
// Mode 1: crop (fill/cover) - Fill screen, crop excess (default)
|
||||
float scale = max(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (scaledImageSize - vec2(ubuf.screenWidth, ubuf.screenHeight)) / scaledImageSize;
|
||||
transformedUV = uv * (vec2(1.0) - offset) + offset * 0.5;
|
||||
}
|
||||
else if (ubuf.fillMode < 2.5) {
|
||||
// Mode 2: fit (contain) - Fit inside screen, maintain aspect ratio
|
||||
float scale = min(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - scaledImageSize) * 0.5;
|
||||
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imagePixel = (screenPixel - offset) / scale;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 3.5) {
|
||||
// Mode 3: stretch - Use original UV (stretches to fit)
|
||||
}
|
||||
else {
|
||||
// Mode 4: repeat (tile) - Tile image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
transformedUV = screenPixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
|
||||
return transformedUV;
|
||||
}
|
||||
|
||||
// Sample texture with fill mode and handle out-of-bounds
|
||||
vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight, float isSolid, vec4 solidColor) {
|
||||
if (isSolid > 0.5) {
|
||||
return solidColor;
|
||||
}
|
||||
|
||||
vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
|
||||
|
||||
if (ubuf.fillMode > 3.5) {
|
||||
return texture(tex, fract(transformedUV));
|
||||
}
|
||||
|
||||
if (transformedUV.x < 0.0 || transformedUV.x > 1.0 ||
|
||||
transformedUV.y < 0.0 || transformedUV.y > 1.0) {
|
||||
return ubuf.fillColor;
|
||||
}
|
||||
|
||||
return texture(tex, transformedUV);
|
||||
}
|
||||
|
||||
// Convert cartesian to axial hex coordinates and round to nearest hex center
|
||||
vec2 hexRound(vec2 axial) {
|
||||
// Convert axial (q,r) to cube (x,y,z) where x+y+z=0
|
||||
float x = axial.x;
|
||||
float z = axial.y;
|
||||
float y = -x - z;
|
||||
|
||||
// Round each
|
||||
float rx = round(x);
|
||||
float ry = round(y);
|
||||
float rz = round(z);
|
||||
|
||||
// Fix rounding errors by resetting the component with largest diff
|
||||
float dx = abs(rx - x);
|
||||
float dy = abs(ry - y);
|
||||
float dz = abs(rz - z);
|
||||
|
||||
if (dx > dy && dx > dz) {
|
||||
rx = -ry - rz;
|
||||
} else if (dy > dz) {
|
||||
ry = -rx - rz;
|
||||
} else {
|
||||
rz = -rx - ry;
|
||||
}
|
||||
|
||||
return vec2(rx, rz);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
|
||||
// Sample both textures at original UV
|
||||
vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1, ubuf.isSolid1, ubuf.solidColor1);
|
||||
vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2, ubuf.isSolid2, ubuf.solidColor2);
|
||||
|
||||
// Aspect-correct the UV for hex grid so cells appear as regular hexagons
|
||||
vec2 aspectUV = vec2(uv.x * ubuf.aspectRatio, uv.y);
|
||||
|
||||
// Convert to axial hex coordinates
|
||||
// Hex grid: q axis along x, r axis at 60 degrees
|
||||
float size = max(ubuf.cellSize, 0.01);
|
||||
float q = (aspectUV.x * (2.0 / 3.0)) / size;
|
||||
float r = ((-aspectUV.x / 3.0) + (sqrt(3.0) / 3.0) * aspectUV.y) / size;
|
||||
|
||||
// Round to nearest hex center
|
||||
vec2 hex = hexRound(vec2(q, r));
|
||||
|
||||
// Convert hex center back to aspect-corrected UV space
|
||||
vec2 hexCenter;
|
||||
hexCenter.x = size * (3.0 / 2.0) * hex.x;
|
||||
hexCenter.y = size * (sqrt(3.0) * (hex.y + 0.5 * hex.x));
|
||||
|
||||
// Calculate distance from this cell's center to the wave origin (aspect-corrected)
|
||||
vec2 origin = vec2(ubuf.centerX * ubuf.aspectRatio, ubuf.centerY);
|
||||
float dist = distance(hexCenter, origin);
|
||||
|
||||
// Maximum distance from origin to any corner (for normalization)
|
||||
float maxDistX = max(ubuf.centerX * ubuf.aspectRatio, (1.0 - ubuf.centerX) * ubuf.aspectRatio);
|
||||
float maxDistY = max(ubuf.centerY, 1.0 - ubuf.centerY);
|
||||
float maxDist = length(vec2(maxDistX, maxDistY));
|
||||
|
||||
// Wave expansion (same approach as disc shader):
|
||||
// Start radius behind the origin so the smoothstep zone is fully off-screen at progress=0
|
||||
float softEdge = 0.15 * maxDist;
|
||||
float totalDistance = maxDist + 2.0 * softEdge;
|
||||
float radius = -softEdge + ubuf.progress * totalDistance;
|
||||
|
||||
// factor = 0 inside the wave (revealed), 1 outside (not yet reached)
|
||||
float factor = smoothstep(radius - softEdge, radius + softEdge, dist);
|
||||
float cellProgress = 1.0 - factor;
|
||||
|
||||
fragColor = mix(color1, color2, cellProgress) * ubuf.qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// ===== wp_pixelate.frag =====
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D source1;
|
||||
layout(binding = 2) uniform sampler2D source2;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float progress;
|
||||
float maxBlockSize; // Maximum block size in pixels (default 64)
|
||||
|
||||
// Fill mode parameters
|
||||
float fillMode; // 0=center, 1=crop, 2=fit, 3=stretch, 4=repeat
|
||||
float imageWidth1; // Width of source1 image
|
||||
float imageHeight1; // Height of source1 image
|
||||
float imageWidth2; // Width of source2 image
|
||||
float imageHeight2; // Height of source2 image
|
||||
float screenWidth; // Screen width
|
||||
float screenHeight; // Screen height
|
||||
vec4 fillColor; // Fill color for empty areas (default: black)
|
||||
|
||||
// Solid color mode
|
||||
float isSolid1; // 1.0 if source1 is solid color, 0.0 otherwise
|
||||
float isSolid2; // 1.0 if source2 is solid color, 0.0 otherwise
|
||||
vec4 solidColor1; // Solid color for source1
|
||||
vec4 solidColor2; // Solid color for source2
|
||||
} ubuf;
|
||||
|
||||
// Calculate UV coordinates based on fill mode
|
||||
vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
|
||||
float imageAspect = imgWidth / imgHeight;
|
||||
float screenAspect = ubuf.screenWidth / ubuf.screenHeight;
|
||||
vec2 transformedUV = uv;
|
||||
|
||||
if (ubuf.fillMode < 0.5) {
|
||||
// Mode 0: no (center) - No resize, center image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imageOffset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - vec2(imgWidth, imgHeight)) * 0.5;
|
||||
vec2 imagePixel = screenPixel - imageOffset;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 1.5) {
|
||||
// Mode 1: crop (fill/cover) - Fill screen, crop excess (default)
|
||||
float scale = max(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (scaledImageSize - vec2(ubuf.screenWidth, ubuf.screenHeight)) / scaledImageSize;
|
||||
transformedUV = uv * (vec2(1.0) - offset) + offset * 0.5;
|
||||
}
|
||||
else if (ubuf.fillMode < 2.5) {
|
||||
// Mode 2: fit (contain) - Fit inside screen, maintain aspect ratio
|
||||
float scale = min(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - scaledImageSize) * 0.5;
|
||||
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imagePixel = (screenPixel - offset) / scale;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 3.5) {
|
||||
// Mode 3: stretch - Use original UV (stretches to fit)
|
||||
}
|
||||
else {
|
||||
// Mode 4: repeat (tile) - Tile image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
transformedUV = screenPixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
|
||||
return transformedUV;
|
||||
}
|
||||
|
||||
// Sample texture with fill mode and handle out-of-bounds
|
||||
vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight, float isSolid, vec4 solidColor) {
|
||||
if (isSolid > 0.5) {
|
||||
return solidColor;
|
||||
}
|
||||
|
||||
vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
|
||||
|
||||
if (ubuf.fillMode > 3.5) {
|
||||
return texture(tex, fract(transformedUV));
|
||||
}
|
||||
|
||||
if (transformedUV.x < 0.0 || transformedUV.x > 1.0 ||
|
||||
transformedUV.y < 0.0 || transformedUV.y > 1.0) {
|
||||
return ubuf.fillColor;
|
||||
}
|
||||
|
||||
return texture(tex, transformedUV);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
|
||||
// Triangle wave: pixelation peaks at progress=0.5
|
||||
float pixelIntensity = 1.0 - abs(2.0 * ubuf.progress - 1.0);
|
||||
|
||||
// Compute the sampling UV — snap to block grid when pixelating, pass through otherwise
|
||||
vec2 sampleUV = uv;
|
||||
if (pixelIntensity > 0.001) {
|
||||
float blockSize = ubuf.maxBlockSize * pixelIntensity;
|
||||
vec2 screenSize = vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 pixelCoord = uv * screenSize;
|
||||
vec2 snappedPixel = floor(pixelCoord / blockSize) * blockSize + blockSize * 0.5;
|
||||
sampleUV = snappedPixel / screenSize;
|
||||
}
|
||||
|
||||
// Sample both textures at the (possibly snapped) UV
|
||||
vec4 color1 = sampleWithFillMode(source1, sampleUV, ubuf.imageWidth1, ubuf.imageHeight1, ubuf.isSolid1, ubuf.solidColor1);
|
||||
vec4 color2 = sampleWithFillMode(source2, sampleUV, ubuf.imageWidth2, ubuf.imageHeight2, ubuf.isSolid2, ubuf.solidColor2);
|
||||
|
||||
// Crossfade concentrated around the peak pixelation (progress ~0.5)
|
||||
float blend = smoothstep(0.4, 0.6, ubuf.progress);
|
||||
|
||||
fragColor = mix(color1, color2, blend) * ubuf.qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
// ===== wp_stripes.frag =====
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D source1; // Current wallpaper
|
||||
layout(binding = 2) uniform sampler2D source2; // Next wallpaper
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float progress; // Transition progress (0.0 to 1.0)
|
||||
float stripeCount; // Number of stripes (default 12.0)
|
||||
float angle; // Angle of stripes in degrees (default 30.0)
|
||||
float smoothness; // Edge smoothness (0.0 to 1.0, 0=sharp, 1=very smooth)
|
||||
float aspectRatio; // Width / Height of the screen
|
||||
|
||||
// Fill mode parameters
|
||||
float fillMode; // 0=center, 1=crop, 2=fit, 3=stretch, 4=repeat
|
||||
float imageWidth1; // Width of source1 image
|
||||
float imageHeight1; // Height of source1 image
|
||||
float imageWidth2; // Width of source2 image
|
||||
float imageHeight2; // Height of source2 image
|
||||
float screenWidth; // Screen width
|
||||
float screenHeight; // Screen height
|
||||
vec4 fillColor; // Fill color for empty areas (default: black)
|
||||
|
||||
// Solid color mode
|
||||
float isSolid1; // 1.0 if source1 is solid color, 0.0 otherwise
|
||||
float isSolid2; // 1.0 if source2 is solid color, 0.0 otherwise
|
||||
vec4 solidColor1; // Solid color for source1
|
||||
vec4 solidColor2; // Solid color for source2
|
||||
} ubuf;
|
||||
|
||||
// Calculate UV coordinates based on fill mode
|
||||
vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
|
||||
float imageAspect = imgWidth / imgHeight;
|
||||
float screenAspect = ubuf.screenWidth / ubuf.screenHeight;
|
||||
vec2 transformedUV = uv;
|
||||
|
||||
if (ubuf.fillMode < 0.5) {
|
||||
// Mode 0: no (center) - No resize, center image at original size
|
||||
// Convert UV to pixel coordinates, offset, then back to UV in image space
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imageOffset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - vec2(imgWidth, imgHeight)) * 0.5;
|
||||
vec2 imagePixel = screenPixel - imageOffset;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 1.5) {
|
||||
// Mode 1: crop (fill/cover) - Fill screen, crop excess (default)
|
||||
float scale = max(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (scaledImageSize - vec2(ubuf.screenWidth, ubuf.screenHeight)) / scaledImageSize;
|
||||
transformedUV = uv * (vec2(1.0) - offset) + offset * 0.5;
|
||||
}
|
||||
else if (ubuf.fillMode < 2.5) {
|
||||
// Mode 2: fit (contain) - Fit inside screen, maintain aspect ratio
|
||||
float scale = min(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - scaledImageSize) * 0.5;
|
||||
|
||||
// Convert screen UV to pixel coordinates
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
// Adjust for offset and scale
|
||||
vec2 imagePixel = (screenPixel - offset) / scale;
|
||||
// Convert back to UV coordinates in image space
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 3.5) {
|
||||
// Mode 3: stretch - Use original UV (stretches to fit)
|
||||
// No transformation needed for stretch mode
|
||||
}
|
||||
else {
|
||||
// Mode 4: repeat (tile) - Tile image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
transformedUV = screenPixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
|
||||
return transformedUV;
|
||||
}
|
||||
|
||||
// Sample texture with fill mode and handle out-of-bounds
|
||||
// If isSolid > 0.5, returns solidColor instead of sampling texture
|
||||
vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight, float isSolid, vec4 solidColor) {
|
||||
// Return solid color if in solid color mode
|
||||
if (isSolid > 0.5) {
|
||||
return solidColor;
|
||||
}
|
||||
|
||||
vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
|
||||
|
||||
// Mode 4 (repeat): use fract() to tile the image
|
||||
if (ubuf.fillMode > 3.5) {
|
||||
return texture(tex, fract(transformedUV));
|
||||
}
|
||||
|
||||
// Check if UV is out of bounds
|
||||
if (transformedUV.x < 0.0 || transformedUV.x > 1.0 ||
|
||||
transformedUV.y < 0.0 || transformedUV.y > 1.0) {
|
||||
return ubuf.fillColor;
|
||||
}
|
||||
|
||||
return texture(tex, transformedUV);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
|
||||
// Sample textures with fill mode (handles solid colors)
|
||||
vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1, ubuf.isSolid1, ubuf.solidColor1);
|
||||
vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2, ubuf.isSolid2, ubuf.solidColor2);
|
||||
|
||||
// Map smoothness from 0.0-1.0 to 0.001-0.3 range
|
||||
// Using a non-linear mapping for better control at low values
|
||||
float mappedSmoothness = mix(0.001, 0.3, ubuf.smoothness * ubuf.smoothness);
|
||||
|
||||
// Use values directly without forcing defaults
|
||||
float stripes = (ubuf.stripeCount > 0.0) ? ubuf.stripeCount : 12.0;
|
||||
float angleRad = radians(ubuf.angle);
|
||||
float edgeSmooth = mappedSmoothness;
|
||||
|
||||
// Create a coordinate system for stripes based on angle
|
||||
// At 0°: vertical stripes (divide by x)
|
||||
// At 45°: diagonal stripes
|
||||
// At 90°: horizontal stripes (divide by y)
|
||||
|
||||
// Transform coordinates based on angle
|
||||
float cosA = cos(angleRad);
|
||||
float sinA = sin(angleRad);
|
||||
|
||||
// Project the UV position onto the stripe direction
|
||||
// This gives us the position along the stripe direction
|
||||
float stripeCoord = uv.x * cosA + uv.y * sinA;
|
||||
|
||||
// Perpendicular coordinate (for edge movement)
|
||||
float perpCoord = -uv.x * sinA + uv.y * cosA;
|
||||
|
||||
// Calculate the range of perpCoord based on angle
|
||||
// This determines how far edges need to travel to fully cover the screen
|
||||
float minPerp = min(min(0.0 * -sinA + 0.0 * cosA, 1.0 * -sinA + 0.0 * cosA),
|
||||
min(0.0 * -sinA + 1.0 * cosA, 1.0 * -sinA + 1.0 * cosA));
|
||||
float maxPerp = max(max(0.0 * -sinA + 0.0 * cosA, 1.0 * -sinA + 0.0 * cosA),
|
||||
max(0.0 * -sinA + 1.0 * cosA, 1.0 * -sinA + 1.0 * cosA));
|
||||
|
||||
// Determine which stripe we're in
|
||||
float stripePos = stripeCoord * stripes;
|
||||
int stripeIndex = int(floor(stripePos));
|
||||
|
||||
// Determine if this is an odd or even stripe
|
||||
bool isOddStripe = mod(float(stripeIndex), 2.0) != 0.0;
|
||||
|
||||
// Calculate the progress for this specific stripe with wave delay
|
||||
// Use absolute stripe position for consistent delay across all stripes
|
||||
float normalizedStripePos = clamp(stripePos / stripes, 0.0, 1.0);
|
||||
|
||||
// Increased delay and better distribution
|
||||
float maxDelay = 0.1;
|
||||
float stripeDelay = normalizedStripePos * maxDelay;
|
||||
|
||||
// Better progress mapping that uses the full 0.0-1.0 range
|
||||
// Map progress so that:
|
||||
// - First stripe starts at progress = 0.0
|
||||
// - Last stripe finishes at progress = 1.0
|
||||
float stripeProgress;
|
||||
if (ubuf.progress <= stripeDelay) {
|
||||
stripeProgress = 0.0;
|
||||
} else if (ubuf.progress >= (stripeDelay + (1.0 - maxDelay))) {
|
||||
stripeProgress = 1.0;
|
||||
} else {
|
||||
// Scale the progress within the active window for this stripe
|
||||
float activeStart = stripeDelay;
|
||||
float activeEnd = stripeDelay + (1.0 - maxDelay);
|
||||
stripeProgress = (ubuf.progress - activeStart) / (activeEnd - activeStart);
|
||||
}
|
||||
|
||||
// Use the perpendicular coordinate for edge comparison
|
||||
float yPos = perpCoord;
|
||||
|
||||
// Calculate edge position for this stripe
|
||||
// Use the actual perpendicular coordinate range for this angle
|
||||
float perpRange = maxPerp - minPerp;
|
||||
float margin = edgeSmooth; // Just enough buffer for the smoothstep zone to clear the edge
|
||||
float edgePosition;
|
||||
if (isOddStripe) {
|
||||
// Odd stripes: edge moves from max to min
|
||||
edgePosition = maxPerp + margin - stripeProgress * (perpRange + margin * 2.0);
|
||||
} else {
|
||||
// Even stripes: edge moves from min to max
|
||||
edgePosition = minPerp - margin + stripeProgress * (perpRange + margin * 2.0);
|
||||
}
|
||||
|
||||
// Determine which wallpaper to show based on rotated position
|
||||
float mask;
|
||||
if (isOddStripe) {
|
||||
// Odd stripes reveal new wallpaper from bottom
|
||||
mask = smoothstep(edgePosition - edgeSmooth, edgePosition + edgeSmooth, yPos);
|
||||
} else {
|
||||
// Even stripes reveal new wallpaper from top
|
||||
mask = 1.0 - smoothstep(edgePosition - edgeSmooth, edgePosition + edgeSmooth, yPos);
|
||||
}
|
||||
|
||||
// Mix the wallpapers
|
||||
fragColor = mix(color1, color2, mask);
|
||||
|
||||
// Force exact values at start and end to prevent any bleed-through
|
||||
if (ubuf.progress <= 0.0) {
|
||||
fragColor = color1; // Only show old wallpaper at start
|
||||
} else if (ubuf.progress >= 1.0) {
|
||||
fragColor = color2; // Only show new wallpaper at end
|
||||
} else {
|
||||
// Add manga-style edge shadow only during transition
|
||||
float edgeDist = abs(yPos - edgePosition);
|
||||
float shadowStrength = 1.0 - smoothstep(0.0, edgeSmooth * 2.5, edgeDist);
|
||||
shadowStrength *= 0.2 * (1.0 - abs(stripeProgress - 0.5) * 2.0);
|
||||
fragColor.rgb *= (1.0 - shadowStrength);
|
||||
|
||||
// Add slight vignette during transition for dramatic effect
|
||||
float vignette = 1.0 - ubuf.progress * 0.1 * (1.0 - abs(stripeProgress - 0.5) * 2.0);
|
||||
fragColor.rgb *= vignette;
|
||||
}
|
||||
|
||||
fragColor *= ubuf.qt_Opacity;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// ===== wp_wipe.frag =====
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(binding = 1) uniform sampler2D source1; // Current wallpaper
|
||||
layout(binding = 2) uniform sampler2D source2; // Next wallpaper
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float progress; // Transition progress (0.0 to 1.0)
|
||||
float direction; // 0=left, 1=right, 2=up, 3=down
|
||||
float smoothness; // Edge smoothness (0.0 to 1.0, 0=sharp, 1=very smooth)
|
||||
|
||||
// Fill mode parameters
|
||||
float fillMode; // 0=center, 1=crop, 2=fit, 3=stretch, 4=repeat
|
||||
float imageWidth1; // Width of source1 image
|
||||
float imageHeight1; // Height of source1 image
|
||||
float imageWidth2; // Width of source2 image
|
||||
float imageHeight2; // Height of source2 image
|
||||
float screenWidth; // Screen width
|
||||
float screenHeight; // Screen height
|
||||
vec4 fillColor; // Fill color for empty areas (default: black)
|
||||
|
||||
// Solid color mode
|
||||
float isSolid1; // 1.0 if source1 is solid color, 0.0 otherwise
|
||||
float isSolid2; // 1.0 if source2 is solid color, 0.0 otherwise
|
||||
vec4 solidColor1; // Solid color for source1
|
||||
vec4 solidColor2; // Solid color for source2
|
||||
} ubuf;
|
||||
|
||||
// Calculate UV coordinates based on fill mode
|
||||
vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
|
||||
float imageAspect = imgWidth / imgHeight;
|
||||
float screenAspect = ubuf.screenWidth / ubuf.screenHeight;
|
||||
vec2 transformedUV = uv;
|
||||
|
||||
if (ubuf.fillMode < 0.5) {
|
||||
// Mode 0: no (center) - No resize, center image at original size
|
||||
// Convert UV to pixel coordinates, offset, then back to UV in image space
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
vec2 imageOffset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - vec2(imgWidth, imgHeight)) * 0.5;
|
||||
vec2 imagePixel = screenPixel - imageOffset;
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 1.5) {
|
||||
// Mode 1: crop (fill/cover) - Fill screen, crop excess (default)
|
||||
float scale = max(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (scaledImageSize - vec2(ubuf.screenWidth, ubuf.screenHeight)) / scaledImageSize;
|
||||
transformedUV = uv * (vec2(1.0) - offset) + offset * 0.5;
|
||||
}
|
||||
else if (ubuf.fillMode < 2.5) {
|
||||
// Mode 2: fit (contain) - Fit inside screen, maintain aspect ratio
|
||||
float scale = min(ubuf.screenWidth / imgWidth, ubuf.screenHeight / imgHeight);
|
||||
vec2 scaledImageSize = vec2(imgWidth, imgHeight) * scale;
|
||||
vec2 offset = (vec2(ubuf.screenWidth, ubuf.screenHeight) - scaledImageSize) * 0.5;
|
||||
|
||||
// Convert screen UV to pixel coordinates
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
// Adjust for offset and scale
|
||||
vec2 imagePixel = (screenPixel - offset) / scale;
|
||||
// Convert back to UV coordinates in image space
|
||||
transformedUV = imagePixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
else if (ubuf.fillMode < 3.5) {
|
||||
// Mode 3: stretch - Use original UV (stretches to fit)
|
||||
// No transformation needed for stretch mode
|
||||
}
|
||||
else {
|
||||
// Mode 4: repeat (tile) - Tile image at original size
|
||||
vec2 screenPixel = uv * vec2(ubuf.screenWidth, ubuf.screenHeight);
|
||||
transformedUV = screenPixel / vec2(imgWidth, imgHeight);
|
||||
}
|
||||
|
||||
return transformedUV;
|
||||
}
|
||||
|
||||
// Sample texture with fill mode and handle out-of-bounds
|
||||
// If isSolid > 0.5, returns solidColor instead of sampling texture
|
||||
vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight, float isSolid, vec4 solidColor) {
|
||||
// Return solid color if in solid color mode
|
||||
if (isSolid > 0.5) {
|
||||
return solidColor;
|
||||
}
|
||||
|
||||
vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
|
||||
|
||||
// Mode 4 (repeat): use fract() to tile the image
|
||||
if (ubuf.fillMode > 3.5) {
|
||||
return texture(tex, fract(transformedUV));
|
||||
}
|
||||
|
||||
// Check if UV is out of bounds
|
||||
if (transformedUV.x < 0.0 || transformedUV.x > 1.0 ||
|
||||
transformedUV.y < 0.0 || transformedUV.y > 1.0) {
|
||||
return ubuf.fillColor;
|
||||
}
|
||||
|
||||
return texture(tex, transformedUV);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = qt_TexCoord0;
|
||||
|
||||
// Sample textures with fill mode (handles solid colors)
|
||||
vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1, ubuf.isSolid1, ubuf.solidColor1);
|
||||
vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2, ubuf.isSolid2, ubuf.solidColor2);
|
||||
|
||||
// Map smoothness from 0.0-1.0 to 0.001-0.5 range
|
||||
// Using a non-linear mapping for better control
|
||||
float mappedSmoothness = mix(0.001, 0.5, ubuf.smoothness * ubuf.smoothness);
|
||||
|
||||
float edge = 0.0;
|
||||
float factor = 0.0;
|
||||
|
||||
// Extend the progress range to account for smoothness
|
||||
// This ensures the transition completes fully at the edges
|
||||
float extendedProgress = ubuf.progress * (1.0 + 2.0 * mappedSmoothness) - mappedSmoothness;
|
||||
|
||||
// Calculate edge position based on direction
|
||||
// As progress goes from 0 to 1, we reveal source2 (new wallpaper)
|
||||
if (ubuf.direction < 0.5) {
|
||||
// Wipe from right to left (new image enters from right)
|
||||
edge = 1.0 - extendedProgress;
|
||||
factor = smoothstep(edge - mappedSmoothness, edge + mappedSmoothness, uv.x);
|
||||
fragColor = mix(color1, color2, factor);
|
||||
}
|
||||
else if (ubuf.direction < 1.5) {
|
||||
// Wipe from left to right (new image enters from left)
|
||||
edge = extendedProgress;
|
||||
factor = smoothstep(edge - mappedSmoothness, edge + mappedSmoothness, uv.x);
|
||||
fragColor = mix(color2, color1, factor);
|
||||
}
|
||||
else if (ubuf.direction < 2.5) {
|
||||
// Wipe from bottom to top (new image enters from bottom)
|
||||
edge = 1.0 - extendedProgress;
|
||||
factor = smoothstep(edge - mappedSmoothness, edge + mappedSmoothness, uv.y);
|
||||
fragColor = mix(color1, color2, factor);
|
||||
}
|
||||
else {
|
||||
// Wipe from top to bottom (new image enters from top)
|
||||
edge = extendedProgress;
|
||||
factor = smoothstep(edge - mappedSmoothness, edge + mappedSmoothness, uv.y);
|
||||
fragColor = mix(color2, color1, factor);
|
||||
}
|
||||
|
||||
fragColor *= ubuf.qt_Opacity;
|
||||
}
|
||||
Reference in New Issue
Block a user