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;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user