summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/dms/Shaders/frag
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/dms/Shaders/frag')
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/ripple.frag61
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_disc.frag126
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_fade.frag91
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_iris_bloom.frag119
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_pixelate.frag125
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_portal.frag124
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_stripes.frag205
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_wipe.frag129
8 files changed, 980 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/ripple.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/ripple.frag
new file mode 100644
index 0000000..2552bb6
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/ripple.frag
@@ -0,0 +1,61 @@
+#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 widthPx;
+ float heightPx;
+ float cornerRadiusPx;
+ float rippleCenterX;
+ float rippleCenterY;
+ float rippleRadius;
+ float rippleOpacity;
+ float offsetX;
+ float offsetY;
+ float parentWidth;
+ float parentHeight;
+ vec4 rippleCol;
+} ubuf;
+
+float sdRoundRect(vec2 p, vec2 b, float r) {
+ vec2 q = abs(p) - (b - vec2(r));
+ return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;
+}
+
+void main() {
+ if (ubuf.rippleOpacity <= 0.0 || ubuf.rippleRadius <= 0.0) {
+ fragColor = vec4(0.0);
+ return;
+ }
+
+ vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx) + vec2(ubuf.offsetX, ubuf.offsetY);
+
+ float circleD = length(px - vec2(ubuf.rippleCenterX, ubuf.rippleCenterY)) - ubuf.rippleRadius;
+ float aaCircle = max(fwidth(circleD), 0.001);
+ float circleMask = 1.0 - smoothstep(-aaCircle, aaCircle, circleD);
+ if (circleMask <= 0.0) {
+ fragColor = vec4(0.0);
+ return;
+ }
+
+ float rrMask = 1.0;
+ if (ubuf.cornerRadiusPx > 0.0) {
+ vec2 halfSize = vec2(ubuf.parentWidth, ubuf.parentHeight) * 0.5;
+ float r = clamp(ubuf.cornerRadiusPx, 0.0, min(halfSize.x, halfSize.y));
+ float rrD = sdRoundRect(px - halfSize, halfSize, r);
+ float aaRR = max(fwidth(rrD), 0.001);
+ rrMask = 1.0 - smoothstep(-aaRR, aaRR, rrD);
+ }
+
+ float mask = circleMask * rrMask;
+ if (mask <= 0.0) {
+ fragColor = vec4(0.0);
+ return;
+ }
+
+ float a = ubuf.rippleCol.a * ubuf.rippleOpacity * mask * ubuf.qt_Opacity;
+ fragColor = vec4(ubuf.rippleCol.rgb * a, a);
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_disc.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_disc.frag
new file mode 100644
index 0000000..254ae41
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_disc.frag
@@ -0,0 +1,126 @@
+// ===== 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
+
+ float fillMode; // 0=stretch, 1=fit, 2=crop, 3=tile, 4=tileV, 5=tileH, 6=pad
+ float imageWidth1;
+ float imageHeight1;
+ float imageWidth2;
+ float imageHeight2;
+ float screenWidth;
+ float screenHeight;
+ vec4 fillColor;
+} ubuf;
+
+vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = uv;
+
+ if (ubuf.fillMode < 0.5) {
+ transformedUV = uv;
+ }
+ else if (ubuf.fillMode < 1.5) {
+ 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 < 2.5) {
+ 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 < 3.5) {
+ transformedUV = fract(uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight));
+ }
+ else if (ubuf.fillMode < 4.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(uv.x, fract(tileUV.y));
+ }
+ else if (ubuf.fillMode < 5.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(fract(tileUV.x), uv.y);
+ }
+ else {
+ 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);
+ }
+
+ return transformedUV;
+}
+
+vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
+
+ if (ubuf.fillMode >= 2.5 && ubuf.fillMode <= 5.5) {
+ return texture(tex, 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;
+
+ // Sample textures with fill mode
+ vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1);
+ vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2);
+
+ // 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);
+ float radius = ubuf.progress * (maxDist + adjustedSmoothness);
+
+ // 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);
+
+ if (ubuf.progress <= 0.0) fragColor = color1;
+
+ fragColor *= ubuf.qt_Opacity;
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_fade.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_fade.frag
new file mode 100644
index 0000000..31a404d
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_fade.frag
@@ -0,0 +1,91 @@
+// ===== 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=stretch, 1=fit, 2=crop, 3=tile, 4=tileV, 5=tileH, 6=pad
+ 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)
+} ubuf;
+
+vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = uv;
+
+ if (ubuf.fillMode < 0.5) {
+ transformedUV = uv;
+ }
+ else if (ubuf.fillMode < 1.5) {
+ 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 < 2.5) {
+ 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 < 3.5) {
+ transformedUV = fract(uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight));
+ }
+ else if (ubuf.fillMode < 4.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(uv.x, fract(tileUV.y));
+ }
+ else if (ubuf.fillMode < 5.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(fract(tileUV.x), uv.y);
+ }
+ else {
+ 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);
+ }
+
+ return transformedUV;
+}
+
+vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
+
+ if (ubuf.fillMode >= 2.5 && ubuf.fillMode <= 5.5) {
+ return texture(tex, 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;
+
+ // Sample textures with fill mode
+ vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1);
+ vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2);
+
+ // Mix the two textures based on progress value
+ fragColor = mix(color1, color2, ubuf.progress) * ubuf.qt_Opacity;
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_iris_bloom.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_iris_bloom.frag
new file mode 100644
index 0000000..548d5bd
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_iris_bloom.frag
@@ -0,0 +1,119 @@
+// ===== wp_iris_bloom.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 centerX;
+ float centerY;
+ float smoothness;
+ float aspectRatio;
+
+ float fillMode; // 0=stretch, 1=fit, 2=crop, 3=tile, 4=tileV, 5=tileH, 6=pad
+ float imageWidth1;
+ float imageHeight1;
+ float imageWidth2;
+ float imageHeight2;
+ float screenWidth;
+ float screenHeight;
+ vec4 fillColor;
+} ubuf;
+
+vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = uv;
+
+ if (ubuf.fillMode < 0.5) {
+ transformedUV = uv;
+ }
+ else if (ubuf.fillMode < 1.5) {
+ 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 < 2.5) {
+ 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 < 3.5) {
+ transformedUV = fract(uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight));
+ }
+ else if (ubuf.fillMode < 4.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(uv.x, fract(tileUV.y));
+ }
+ else if (ubuf.fillMode < 5.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(fract(tileUV.x), uv.y);
+ }
+ else {
+ 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);
+ }
+
+ return transformedUV;
+}
+
+vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
+
+ if (ubuf.fillMode >= 2.5 && ubuf.fillMode <= 5.5) {
+ return texture(tex, 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;
+ vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1);
+ vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2);
+
+ float edgeSoft = mix(0.001, 0.45, ubuf.smoothness * ubuf.smoothness);
+
+ vec2 center = vec2(ubuf.centerX, ubuf.centerY);
+ vec2 acUv = vec2(uv.x * ubuf.aspectRatio, uv.y);
+ vec2 acCenter = vec2(center.x * ubuf.aspectRatio, center.y);
+ vec2 q = acUv - acCenter;
+
+ float maxX = max(center.x * ubuf.aspectRatio, (1.0 - center.x) * ubuf.aspectRatio);
+ float maxY = max(center.y, 1.0 - center.y);
+ float maxDist = length(vec2(maxX, maxY));
+
+ float p = ubuf.progress;
+ p = p * p * (3.0 - 2.0 * p);
+
+ float radius = p * maxDist;
+
+ // squash factor for the "eye" slit
+ float squash = mix(0.2, 1.0, p);
+ q.y /= squash;
+
+ float dist = length(q);
+ float t = smoothstep(radius - edgeSoft, radius + edgeSoft, dist);
+
+ vec4 col = mix(color2, color1, t);
+
+ if (ubuf.progress <= 0.0) col = color1;
+ if (ubuf.progress >= 1.0) col = color2;
+
+ fragColor = col * ubuf.qt_Opacity;
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_pixelate.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_pixelate.frag
new file mode 100644
index 0000000..2b6fb53
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_pixelate.frag
@@ -0,0 +1,125 @@
+// ===== wp_pixelate.frag =====
+#version 450
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source1; // Current wallpaper (underlay)
+layout(binding = 2) uniform sampler2D source2; // Next wallpaper (pixelated overlay → sharp)
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+ float progress; // 0..1
+ float centerX; // (unused, API compat)
+ float centerY; // (unused)
+ float smoothness; // controls starting block size (0..1)
+ float aspectRatio; // (unused)
+
+ float fillMode; // 0=stretch, 1=fit, 2=crop, 3=tile, 4=tileV, 5=tileH, 6=pad
+ float imageWidth1;
+ float imageHeight1;
+ float imageWidth2;
+ float imageHeight2;
+ float screenWidth;
+ float screenHeight;
+ vec4 fillColor;
+} ubuf;
+
+vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = uv;
+
+ if (ubuf.fillMode < 0.5) {
+ transformedUV = uv;
+ }
+ else if (ubuf.fillMode < 1.5) {
+ 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 < 2.5) {
+ 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 < 3.5) {
+ transformedUV = fract(uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight));
+ }
+ else if (ubuf.fillMode < 4.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(uv.x, fract(tileUV.y));
+ }
+ else if (ubuf.fillMode < 5.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(fract(tileUV.x), uv.y);
+ }
+ else {
+ 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);
+ }
+
+ return transformedUV;
+}
+
+vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
+
+ if (ubuf.fillMode >= 2.5 && ubuf.fillMode <= 5.5) {
+ return texture(tex, 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);
+}
+
+vec2 quantizeUV(vec2 uv, float cellPx) {
+ vec2 screenSize = vec2(max(1.0, ubuf.screenWidth), max(1.0, ubuf.screenHeight));
+ float cell = max(1.0, ceil(cellPx)); // integer pixel cells
+ vec2 grid = floor(uv * screenSize / cell) * cell + 0.5 * cell;
+ return grid / screenSize;
+}
+
+void main() {
+ vec2 uv = qt_TexCoord0;
+
+ vec4 oldCol = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1);
+
+ float p = clamp(ubuf.progress, 0.0, 1.0);
+ float pe = p * p * (3.0 - 2.0 * p); // smootherstep for opacity
+
+ // Screen-relative starting cell size:
+ // smoothness=0 → ~10% of min(screen), smoothness=1 → ~80% of min(screen)
+ float s = clamp(ubuf.smoothness, 0.0, 1.0);
+ float minSide = min(max(1.0, ubuf.screenWidth), max(1.0, ubuf.screenHeight));
+ float startPx = mix(minSide * 0.10, minSide * 0.80, s); // big and obvious even on small screens
+
+ // Cell size shrinks continuously from startPx → 1 as p grows
+ float cellPx = mix(startPx, 1.0, p);
+
+ // Sample next as pixelated overlay
+ vec2 uvq = quantizeUV(uv, cellPx);
+ vec4 newPix = sampleWithFillMode(source2, uvq, ubuf.imageWidth2, ubuf.imageHeight2);
+
+ // As we approach the end, sharpen the next from pixelated → full-res
+ float sharpen = smoothstep(0.75, 1.0, p); // only near the end
+ vec4 newFull = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2);
+ vec4 newCol = mix(newPix, newFull, sharpen);
+
+ vec4 outColor = mix(oldCol, newCol, pe);
+
+ // Snaps
+ if (p <= 0.0) outColor = oldCol;
+ if (p >= 1.0) outColor = newFull;
+
+ fragColor = outColor * ubuf.qt_Opacity;
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_portal.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_portal.frag
new file mode 100644
index 0000000..21e939c
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_portal.frag
@@ -0,0 +1,124 @@
+// ===== wp_portal.frag =====
+#version 450
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D source1; // Current wallpaper (shrinks away)
+layout(binding = 2) uniform sampler2D source2; // Next wallpaper (underneath)
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+ float progress; // 0..1
+ float centerX; // 0..1
+ float centerY; // 0..1
+ float smoothness; // 0..1 (edge softness)
+ float aspectRatio; // width / height
+
+ float fillMode; // 0=stretch, 1=fit, 2=crop, 3=tile, 4=tileV, 5=tileH, 6=pad
+ float imageWidth1;
+ float imageHeight1;
+ float imageWidth2;
+ float imageHeight2;
+ float screenWidth;
+ float screenHeight;
+ vec4 fillColor;
+} ubuf;
+
+vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = uv;
+
+ if (ubuf.fillMode < 0.5) {
+ transformedUV = uv;
+ }
+ else if (ubuf.fillMode < 1.5) {
+ 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 < 2.5) {
+ 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 < 3.5) {
+ transformedUV = fract(uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight));
+ }
+ else if (ubuf.fillMode < 4.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(uv.x, fract(tileUV.y));
+ }
+ else if (ubuf.fillMode < 5.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(fract(tileUV.x), uv.y);
+ }
+ else {
+ 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);
+ }
+
+ return transformedUV;
+}
+
+vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
+
+ if (ubuf.fillMode >= 2.5 && ubuf.fillMode <= 5.5) {
+ return texture(tex, 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;
+
+ vec4 oldCol = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1);
+ vec4 newCol = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2);
+
+ // Edge softness
+ float edgeSoft = mix(0.001, 0.45, ubuf.smoothness * ubuf.smoothness);
+
+ // Aspect-corrected distance from center (keep circle round)
+ vec2 center = vec2(ubuf.centerX, ubuf.centerY);
+ vec2 acUv = vec2(uv.x * ubuf.aspectRatio, uv.y);
+ vec2 acCenter = vec2(center.x * ubuf.aspectRatio, center.y);
+ float dist = length(acUv - acCenter);
+
+ // Max radius from center to cover screen
+ float maxDistX = max(center.x * ubuf.aspectRatio, (1.0 - center.x) * ubuf.aspectRatio);
+ float maxDistY = max(center.y, 1.0 - center.y);
+ float maxDist = length(vec2(maxDistX, maxDistY));
+
+ // Smooth easing for a friendly feel
+ float p = ubuf.progress;
+ p = p * p * (3.0 - 2.0 * p);
+
+ // Portal radius shrinks from full to zero (bias by edgeSoft so it vanishes cleanly)
+ float radius = (1.0 - p) * (maxDist + edgeSoft) - edgeSoft;
+
+ // Inside circle = old wallpaper; outside = new wallpaper
+ float t = smoothstep(radius - edgeSoft, radius + edgeSoft, dist);
+ // When radius is large: t ~ 0 inside (old), ~1 outside (new)
+ // As radius shrinks, old area collapses to center.
+
+ vec4 col = mix(oldCol, newCol, t);
+
+ // Snaps
+ if (ubuf.progress <= 0.0) col = oldCol; // full old at start
+ if (ubuf.progress >= 1.0) col = newCol; // full new at end
+
+ fragColor = col * ubuf.qt_Opacity;
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_stripes.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_stripes.frag
new file mode 100644
index 0000000..fcc216b
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_stripes.frag
@@ -0,0 +1,205 @@
+// ===== 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
+
+ float fillMode; // 0=stretch, 1=fit, 2=crop, 3=tile, 4=tileV, 5=tileH, 6=pad
+ float imageWidth1;
+ float imageHeight1;
+ float imageWidth2;
+ float imageHeight2;
+ float screenWidth;
+ float screenHeight;
+ vec4 fillColor;
+} ubuf;
+
+vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = uv;
+
+ if (ubuf.fillMode < 0.5) {
+ transformedUV = uv;
+ }
+ else if (ubuf.fillMode < 1.5) {
+ 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 < 2.5) {
+ 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 < 3.5) {
+ transformedUV = fract(uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight));
+ }
+ else if (ubuf.fillMode < 4.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(uv.x, fract(tileUV.y));
+ }
+ else if (ubuf.fillMode < 5.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(fract(tileUV.x), uv.y);
+ }
+ else {
+ 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);
+ }
+
+ return transformedUV;
+}
+
+vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
+
+ if (ubuf.fillMode >= 2.5 && ubuf.fillMode <= 5.5) {
+ return texture(tex, 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;
+
+ // Sample textures with fill mode
+ vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1);
+ vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2);
+
+ // 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 gentler easing curve
+ stripeProgress = stripeProgress * stripeProgress * (3.0 - 2.0 * stripeProgress); // Smootherstep instead of smoothstep
+
+ // 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 * 2.0; // Simplified margin calculation
+ 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;
+}
diff --git a/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_wipe.frag b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_wipe.frag
new file mode 100644
index 0000000..5fc6d32
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Shaders/frag/wp_wipe.frag
@@ -0,0 +1,129 @@
+// ===== 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)
+
+ float fillMode; // 0=stretch, 1=fit, 2=crop, 3=tile, 4=tileV, 5=tileH, 6=pad
+ float imageWidth1;
+ float imageHeight1;
+ float imageWidth2;
+ float imageHeight2;
+ float screenWidth;
+ float screenHeight;
+ vec4 fillColor;
+} ubuf;
+
+vec2 calculateUV(vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = uv;
+
+ if (ubuf.fillMode < 0.5) {
+ transformedUV = uv;
+ }
+ else if (ubuf.fillMode < 1.5) {
+ 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 < 2.5) {
+ 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 < 3.5) {
+ transformedUV = fract(uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight));
+ }
+ else if (ubuf.fillMode < 4.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(uv.x, fract(tileUV.y));
+ }
+ else if (ubuf.fillMode < 5.5) {
+ vec2 tileUV = uv * vec2(ubuf.screenWidth, ubuf.screenHeight) / vec2(imgWidth, imgHeight);
+ transformedUV = vec2(fract(tileUV.x), uv.y);
+ }
+ else {
+ 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);
+ }
+
+ return transformedUV;
+}
+
+vec4 sampleWithFillMode(sampler2D tex, vec2 uv, float imgWidth, float imgHeight) {
+ vec2 transformedUV = calculateUV(uv, imgWidth, imgHeight);
+
+ if (ubuf.fillMode >= 2.5 && ubuf.fillMode <= 5.5) {
+ return texture(tex, 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;
+
+ // Sample textures with fill mode
+ vec4 color1 = sampleWithFillMode(source1, uv, ubuf.imageWidth1, ubuf.imageHeight1);
+ vec4 color2 = sampleWithFillMode(source2, uv, ubuf.imageWidth2, ubuf.imageHeight2);
+
+ // 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;
+}