diff --git a/docs/how-to-create-new-effects.md b/docs/how-to-create-new-effects.md index fc9a3fb..db82aca 100644 --- a/docs/how-to-create-new-effects.md +++ b/docs/how-to-create-new-effects.md @@ -91,7 +91,7 @@ Please study this code carefully, all of it is explained with inline comments. // vec2 iTexCoord: Texture coordinates for retrieving the window input color. // 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 uTime: A steadily increasing value in seconds. +// 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. diff --git a/extension.js b/extension.js index 26cca45..f11aba8 100644 --- a/extension.js +++ b/extension.js @@ -502,14 +502,14 @@ class Extension { actor.add_effect_with_name('burn-my-windows-effect', shader); // Set one-time uniforms. - shader.beginAnimation(this._settings, forOpening, actor); + shader.beginAnimation(this._settings, forOpening, duration * 0.001, actor); // Set other uniforms each frame. transition.connect('new-frame', (t) => { if (testMode) { - shader.updateAnimation(0.5, 0.001 * duration * 0.5); + shader.updateAnimation(0.5); } else { - shader.updateAnimation(t.get_progress(), 0.001 * t.get_elapsed_time()); + shader.updateAnimation(t.get_progress()); } }); diff --git a/resources/shaders/common.glsl b/resources/shaders/common.glsl index 798ff43..a1026c0 100644 --- a/resources/shaders/common.glsl +++ b/resources/shaders/common.glsl @@ -22,7 +22,7 @@ // vec2 iTexCoord: Texture coordinates for retrieving the window input color. // 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 uTime: A steadily increasing value in seconds. +// 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. @@ -37,6 +37,7 @@ uniform float forOpening; uniform sampler2D sampler; +uniform float uDuration; uniform float textureWidth; uniform float textureHeight; uniform float animationProgress; @@ -69,6 +70,7 @@ void setOutputColor(vec4 outColor) { uniform float forOpening; uniform sampler2D sampler; +uniform float uDuration; uniform float textureWidth; uniform float textureHeight; uniform float animationProgress; @@ -102,7 +104,7 @@ void setOutputColor(vec4 outColor) { uniform bool uForOpening; uniform sampler2D uTexture; uniform float uProgress; -uniform float uTime; +uniform float uDuration; uniform vec2 uSize; uniform float uPadding; diff --git a/resources/shaders/energize-a.frag b/resources/shaders/energize-a.frag index e8ccd43..f94ba5e 100644 --- a/resources/shaders/energize-a.frag +++ b/resources/shaders/energize-a.frag @@ -70,14 +70,14 @@ void main() { scaledUV /= uScale; // Add molecule particles. - vec2 uv = scaledUV + vec2(0, 0.1 * uTime); + vec2 uv = scaledUV + vec2(0, 0.1 * uProgress * uDuration); uv *= 0.010598 * vec2(0.5 * uSize.x, uSize.y); - float particles = 0.2 * pow((simplex3D(vec3(uv, 0.0 * uTime))), 3.0); + float particles = 0.2 * pow((simplex3D(vec3(uv, 0.0 * uProgress * uDuration))), 3.0); // Add more molecule particles. for (int i = 1; i <= 3; ++i) { vec2 uv = scaledUV * 0.12154 / pow(1.5, i) * uSize; - float atoms = simplex3D(vec3(uv, 2.0 * uTime / i)); + float atoms = simplex3D(vec3(uv, 2.0 * uProgress * uDuration / i)); particles += 0.5 * pow(0.2 * (1.0 / (1.0 - atoms) - 1.0), 2); } diff --git a/resources/shaders/energize-b.frag b/resources/shaders/energize-b.frag index 32dad1f..703c5e3 100644 --- a/resources/shaders/energize-b.frag +++ b/resources/shaders/energize-b.frag @@ -100,7 +100,7 @@ void main() { // Add glimmering atoms. vec2 atomUV = iTexCoord.st + vec2(0, -0.025 * progress / SHOWER_TIME); atomUV *= 0.2 * uSize / uScale; - float atoms = pow((simplex3D(vec3(atomUV, uTime))), 5.0); + float atoms = pow((simplex3D(vec3(atomUV, uProgress * uDuration))), 5.0); oColor.rgb += uColor * atoms * masks.z; oColor.a += atoms * masks.z; diff --git a/resources/shaders/fire.frag b/resources/shaders/fire.frag index 44b0d65..0ebce5c 100644 --- a/resources/shaders/fire.frag +++ b/resources/shaders/fire.frag @@ -90,10 +90,12 @@ vec2 effectMask(float hideTime, float fadeWidth, float edgeFadeWidth) { void main() { // Get a noise value which moves vertically in time. vec2 uv = iTexCoord.st * uSize / vec2(400, 600) / uScale; - uv.y += uTime * uMovementSpeed; + uv.y += uProgress * uDuration * uMovementSpeed; - float noise = u3DNoise ? simplex3DFractal(vec3(uv * 4.0, uTime * uMovementSpeed * 1.5)) - : simplex2DFractal(uv * 4.0); + float noise = + u3DNoise + ? simplex3DFractal(vec3(uv * 4.0, uProgress * uDuration * uMovementSpeed * 1.5)) + : simplex2DFractal(uv * 4.0); // Modulate noise by effect mask. vec2 effectMask = effectMask(HIDE_TIME, FADE_WIDTH, EDGE_FADE); diff --git a/resources/shaders/matrix.frag b/resources/shaders/matrix.frag index 4547474..5191238 100644 --- a/resources/shaders/matrix.frag +++ b/resources/shaders/matrix.frag @@ -36,7 +36,7 @@ float getText(vec2 fragCoord) { // Choose random letter. uv += floor(hash22(floor(hash22(block) * vec2(12.9898, 78.233) + - LETTER_FLICKER_SPEED * uTime + 42.254)) * + LETTER_FLICKER_SPEED * uProgress * uDuration + 42.254)) * LETTER_TILES); return texture2D(uFontTexture, uv / LETTER_TILES).r; diff --git a/resources/shaders/wisps.frag b/resources/shaders/wisps.frag index 90d36de..e6e57d9 100644 --- a/resources/shaders/wisps.frag +++ b/resources/shaders/wisps.frag @@ -47,7 +47,8 @@ float getWisps(vec2 texCoords, float gridSize, vec2 seed) { float radius = mix(0.5, 1.0, hash12(cellID * seed * 19.1249)) * WISPS_RADIUS; float roundness = mix(-1.0, 1.0, hash12(cellID * seed * 7.51949)); - vec2 offset = vec2(sin(speed * (uTime + 1)) * roundness, cos(speed * (uTime + 1))); + vec2 offset = vec2(sin(speed * (uProgress * uDuration + 1)) * roundness, + cos(speed * (uProgress * uDuration + 1))); offset *= 0.5 - 0.5 * radius / gridSize; offset = vec2(offset.x * cos(rotation) - offset.y * sin(rotation), offset.x * sin(rotation) + offset.y * cos(rotation)); diff --git a/src/Shader.js b/src/Shader.js index 718179f..2ae1ad0 100644 --- a/src/Shader.js +++ b/src/Shader.js @@ -48,7 +48,7 @@ var Shader = GObject.registerClass( Signals: { 'begin-animation': {param_types: [Gio.Settings.$gtype, GObject.TYPE_BOOLEAN, Clutter.Actor.$gtype]}, - 'update-animation': {param_types: [GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE]} + 'update-animation': {param_types: [GObject.TYPE_DOUBLE]} } }, class Shader extends Shell.GLSLEffect { // -------------------------------------------- @@ -68,17 +68,16 @@ var Shader = GObject.registerClass( // Store standard uniform locations. this._uForOpening = this.get_uniform_location('uForOpening'); this._uProgress = this.get_uniform_location('uProgress'); - this._uTime = this.get_uniform_location('uTime'); + this._uDuration = this.get_uniform_location('uDuration'); 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) { + beginAnimation(settings, forOpening, duration, actor) { - // Reset progress values. + // Reset progress value. this._progress = 0; - this._time = 0; // This is not necessarily symmetric, but I haven't figured out a way to // get the actual values... @@ -86,17 +85,18 @@ var Shader = GObject.registerClass( this.set_uniform_float(this._uPadding, 1, [padding]); this.set_uniform_float(this._uForOpening, 1, [forOpening]); + this.set_uniform_float(this._uDuration, 1, [duration]); this.set_uniform_float(this._uSize, 2, [actor.width, actor.height]); this.emit('begin-animation', settings, forOpening, actor); } // This is called at each frame during the animation. - updateAnimation(progress, time) { - // Store the current time and progress values. The corresponding signal is emitted - // each frame in vfunc_paint_target. + updateAnimation(progress) { + // Store the current progress value. The corresponding signal is emitted each frame + // in vfunc_paint_target. We do not emit it here, as the pipeline which may be used + // by handlers must not have been created yet. this._progress = progress; - this._time = time; } // This is called by the constructor. This means, it's only called when the @@ -121,9 +121,8 @@ var Shader = GObject.registerClass( // We use this vfunc to trigger the update as it allows calling this.get_pipeline() in // the handler. This could still be null if called from the updateAnimation() above. vfunc_paint_target(...params) { - this.emit('update-animation', this._progress, this._time); + this.emit('update-animation', this._progress); this.set_uniform_float(this._uProgress, 1, [this._progress]); - this.set_uniform_float(this._uTime, 1, [this._time]); super.vfunc_paint_target(...params); }