diff --git a/docs/changelog.md b/docs/changelog.md index 791654e..75c0558 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -8,6 +8,7 @@ * The standard uniforms of all shaders have been updated: The window size is now passed as a `vec2` and there is a new `bool uForOpening` which is set to `true` if a window-open animation is ongoing, to `false` otherwise. * Refactored how the size and opacity transitions of the window actors are set up. Effects can now only specify a desired actor scale which will not change during the animation. All dynamic scaling and fading must be implemented in the shaders now. +* The shaders are now aware of the actual window size (e.g. excluding the area where the shadow is drawn). For instance, this fixes the drawing of the effects outside the window bounds for `libadwaita` apps. #### Bug Fixes diff --git a/docs/how-to-create-new-effects.md b/docs/how-to-create-new-effects.md index 35029ce..03d880e 100644 --- a/docs/how-to-create-new-effects.md +++ b/docs/how-to-create-new-effects.md @@ -92,6 +92,7 @@ Please study this code carefully, all of it is explained with inline comments. // float uProgress: A value which transitions from 0 to 1 during the entire animation. // float uTime: A steadily increasing value 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). #include "common/uniforms.glsl" // The width of the fading effect is loaded from the settings. diff --git a/resources/shaders/common/edgeMask.glsl b/resources/shaders/common/edgeMask.glsl index 8ad5f08..d14e981 100644 --- a/resources/shaders/common/edgeMask.glsl +++ b/resources/shaders/common/edgeMask.glsl @@ -11,11 +11,22 @@ float getEdgeMask(vec2 uv, vec2 maxUV, float fadeWidth) { return mask; } -float getAbsoluteEdgeMask(float fadePixels) { - vec2 uv = cogl_tex_coord_in[0].st * uSize; - return getEdgeMask(uv, uSize, fadePixels); +// Returns an edge mask which fades to zero at the boundaries of the actor. The width of +// the fade zone is given in pixels. This uses the standard uniforms uSize and uPadding. +// This means that the fading zone is not actually at the actors boundaries but at the +// position of the window border in the texture. +// The offset paramter controls whether the fading is placed inside the window borders +// (offset = 0), ontop the window borders (offset = 0.5) or outside the window borders +// (offset = 1). +float getAbsoluteEdgeMask(float fadePixels, float offset) { + float padding = max(0, uPadding - fadePixels * offset); + vec2 uv = cogl_tex_coord_in[0].st * uSize - padding; + return getEdgeMask(uv, uSize - 2.0 * padding, fadePixels); } +// Returns an edge mask which fades to zero at the boundaries of the actor. The width of +// the fade zone is given relative to the actor size. This neither uses uSize and +// uPadding. float getRelativeEdgeMask(float fadeAmount) { vec2 uv = cogl_tex_coord_in[0].st; return getEdgeMask(uv, vec2(1.0), fadeAmount); diff --git a/resources/shaders/common/uniforms.glsl b/resources/shaders/common/uniforms.glsl index a7db848..ab7589a 100644 --- a/resources/shaders/common/uniforms.glsl +++ b/resources/shaders/common/uniforms.glsl @@ -4,8 +4,10 @@ // uProgress: A value which transitions from 0 to 1 during the entire animation. // uTime: A steadily increasing value in seconds. // uSize: The size of uTexture in pixels. +// uPadding: The empty area around the actual window (e.g. where the shadow is drawn). uniform bool uForOpening; uniform sampler2D uTexture; uniform float uProgress; uniform float uTime; -uniform vec2 uSize; \ No newline at end of file +uniform vec2 uSize; +uniform float uPadding; \ No newline at end of file diff --git a/resources/shaders/energize-a.glsl b/resources/shaders/energize-a.glsl index 7b5d167..054058d 100644 --- a/resources/shaders/energize-a.glsl +++ b/resources/shaders/energize-a.glsl @@ -30,7 +30,7 @@ vec2 getMasks(float progress) { atomMask *= smoothstep(1.0, 0.0, fadeOutProgress); // Fade-out the masks at the window edges. - float edgeFade = getAbsoluteEdgeMask(EDGE_FADE_WIDTH); + float edgeFade = getAbsoluteEdgeMask(EDGE_FADE_WIDTH, 0.5); atomMask *= edgeFade; float heartMask = getRelativeEdgeMask(0.5); diff --git a/resources/shaders/energize-b.glsl b/resources/shaders/energize-b.glsl index 34a8b35..7283fd7 100644 --- a/resources/shaders/energize-b.glsl +++ b/resources/shaders/energize-b.glsl @@ -47,7 +47,7 @@ vec4 getMasks(float progress) { streakMask = max(streakMask, showerMask); // Fade-out the masks at the window edges. - float edgeFade = getAbsoluteEdgeMask(EDGE_FADE); + float edgeFade = getAbsoluteEdgeMask(EDGE_FADE, 0.5); streakMask *= edgeFade; showerMask *= edgeFade; diff --git a/resources/shaders/fire.glsl b/resources/shaders/fire.glsl index 99e6704..12e395a 100644 --- a/resources/shaders/fire.glsl +++ b/resources/shaders/fire.glsl @@ -72,7 +72,7 @@ vec2 effectMask(float hideTime, float fadeWidth, float edgeFadeWidth) { } // Fade at window borders. - effectMask *= getAbsoluteEdgeMask(edgeFadeWidth); + effectMask *= getAbsoluteEdgeMask(edgeFadeWidth, 0.5); if (uForOpening) { windowMask = 1.0 - windowMask; diff --git a/resources/shaders/matrix.glsl b/resources/shaders/matrix.glsl index 490f696..8b5010c 100644 --- a/resources/shaders/matrix.glsl +++ b/resources/shaders/matrix.glsl @@ -52,7 +52,7 @@ vec2 getRain(vec2 fragCoord) { float windowAlpha = 1 - clamp(uSize.y * distToDrop, 0, FADE_WIDTH) / FADE_WIDTH; // Fade at window borders. - rainAlpha *= getAbsoluteEdgeMask(EDGE_FADE); + rainAlpha *= getAbsoluteEdgeMask(EDGE_FADE, 0.5); // Add some variation to the drop start and end position. float shorten = diff --git a/src/Shader.js b/src/Shader.js index 4d53a35..bb7ec03 100644 --- a/src/Shader.js +++ b/src/Shader.js @@ -70,10 +70,17 @@ var Shader = GObject.registerClass( this._uProgress = this.get_uniform_location('uProgress'); this._uTime = this.get_uniform_location('uTime'); this._uSize = this.get_uniform_location('uSize'); + this._uPadding = this.get_uniform_location('uPadding'); } // This is called once each time the shader is used. beginAnimation(settings, forOpening, actor) { + + // This is not necessarily symmetric, but I haven't figured out a way to + // get the actual values... + const padding = (actor.width - actor.meta_window.get_frame_rect().width) / 2; + + this.set_uniform_float(this._uPadding, 1, [padding]); this.set_uniform_float(this._uForOpening, 1, [forOpening]); this.set_uniform_float(this._uSize, 2, [actor.width, actor.height]);