////////////////////////////////////////////////////////////////////////////////////////// // ) ( // // ( /( ( ( ) ( ( ( ( )\ ) ( ( // // )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( // // ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ // // | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) // // | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< // // |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ // // |__/ // ////////////////////////////////////////////////////////////////////////////////////////// // SPDX-FileCopyrightText: Justin Garza // SPDX-License-Identifier: GPL-3.0-or-later // The content from common.glsl is automatically prepended to each shader effect. This // provides the standard input: // vec2 iTexCoord: Texture coordinates for retrieving the window input color. // bool uIsFullscreen: True if the window is maximized or in fullscreen mode. // bool uForOpening: True if a window-open animation is ongoing, false otherwise. // float uProgress: A value which transitions from 0 to 1 during the animation. // float uDuration: The duration of the current animation in seconds. // vec2 uSize: The size of uTexture in pixels. // float uPadding: The empty area around the actual window (e.g. where the shadow // is drawn). For now, this will only be set on GNOME. // Furthermore, there are two global methods for reading the window input color and // setting the shader output color. Both methods assume straight alpha: // vec4 getInputColor(vec2 coords) // void setOutputColor(vec4 outColor) // The width of the fading effect is loaded from the settings. uniform float uColorSpeed; uniform bool uRandomColorOffset; uniform float uColorOffset; uniform float uColorSaturation; uniform float uFadeOut; uniform float uBlur; uniform vec2 uSeed; /* this controls the end shape -5.0 large Star -3.0 Star 1.0 Dimond 2.0 Circle 3.0 Squircle 5.0 Square */ uniform float uEdgeShape; // the size of the edge color uniform float uEdgeSize; // soft <--> hard uniform float uEdgeHardness; // A simple blur function vec4 blur(vec2 uv, float radius, float samples) { vec4 color = vec4(0.0); const float tau = 6.28318530718; const float directions = 15.0; for (float d = 0.0; d < tau; d += tau / directions) { for (float s = 0.0; s < 1.0; s += 1.0 / samples) { vec2 offset = vec2(cos(d), sin(d)) * radius * (1.0 - s) / uSize; color += getInputColor(uv + offset); } } return color / samples / directions; } void main() { // This gradually dissolves from [1..0] from the outside to the center. We // switch the direction for opening and closing. float progress = uForOpening ? uProgress : 1.0 - uProgress; // adjusting for Gnome if (uPadding > 0.0) { progress = remap(progress, 0.0, ((uSize.x - (uPadding * 2.0)) / uSize.x), 0.0, 1.0); } // Get the color from the window texture. vec4 oColor = getInputColor(iTexCoord.st); // Calculate the aspect ratio of the render area float aspect = uSize.x / uSize.y; // standard uv vec2 uv = iTexCoord.st; // tuv is for when progress is near 0 vec2 tuv = uv; tuv -= 0.5; // Shift UV coordinates to center (from [-0.5 to 0.5]) tuv.x *= aspect; // Scale x-coordinate to match aspect ratio tuv += 0.5; // Shift UV coordinates back (from [0 to 1]) // mixing the UVs uv = mix(tuv, uv, easeOutExpo(progress)); // this controls the shape // -1.0 would be a diamond-ish // 0.0 would be a rounded diamond // 1.0 would be a circle // 2.0 will be sqircle // 1000.0 will be very square float p = mix(uEdgeShape, 1000.0, easeInExpo(progress)); // this will be used later to make a mask float m = mix(0.0, 1.0, clamp(pow(abs(uv.x - 0.5) * 2.0, p) + pow(abs(uv.y - 0.5) * 2.0, p), 0.0, 1.0)); // this calculates the edge of the effect float edge = abs(m - progress); float e = mix(0.0, uEdgeSize, 1.0 - progress); edge = remap(edge, 0.0, e, 0.0, 1.0); edge = clamp(edge, 0.0, 1.0); edge = 1.0 - edge; // this is the mask float mask = (m > progress) ? 0.0 : 1.0; // we need two of these float mask0 = mix(mask, mask + edge, 1.0 - uEdgeHardness); float mask1 = mix(edge, edge * mask, uEdgeHardness); // calculate color vec3 color = cos(progress * uColorSpeed + uv.xyx + vec3(0, 2, 4)).xyz; // coloroffset float colorOffset = (uRandomColorOffset) ? hash12(uSeed) : uColorOffset; color = offsetHue(color, colorOffset + 0.10); // clamp and saturate color = clamp(color * uColorSaturation, vec3(0.0), vec3(1.0)); // save this for later float oColorAlpha = oColor.a; // blur-ify if (uBlur > 0.0) { // used for blur later ... // calculate this before saturating it float b = (color.r + color.g + color.b) / 3.0; oColor = blur(iTexCoord.st, b * uBlur * mask1, 7.0); } // apply masks and colors oColor.a *= mask0; // i was doing this to try to adjust for light mode // i don;t like the way these make the effect look // ...maybe a toggle for it later /* float oColorPercent = (oColor.r + oColor.g + oColor.b)/3.0; oColor.r = mix(oColor.r , 1.0 - oColor.r, mask1 * oColorPercent); oColor.g = mix(oColor.g , 1.0 - oColor.g, mask1 * oColorPercent); oColor.b = mix(oColor.b , 1.0 - oColor.b, mask1 * oColorPercent); // --or oColor.r = mix(oColor.r , 0.0, mask1 * oColorPercent); oColor.g = mix(oColor.g , 0.0, mask1 * oColorPercent); oColor.b = mix(oColor.b , 0.0, mask1 * oColorPercent); */ oColor += mask1 * vec4(color.rgb, 1.0); oColor.a *= oColorAlpha; // i want to fade out the last ~10% of the animation float lastfade = remap(progress, 0.0, uFadeOut, 0.0, 1.0); lastfade = clamp(lastfade, 0.0, 1.0); lastfade = easeInSine(lastfade); // apply the lastfade oColor.a *= lastfade; setOutputColor(oColor); }