the current renderer instance
Optionaloptions: { anchor?: number; frequency?: number; speed?: number; strength?: number } = {}
effect options
Optionalanchor?: numberthe row of the sprite that stays put, as a fraction of its height from the top (1 = the bottom row)
Optionalfrequency?: numberhow much the sway bends along the height: low values lean the whole sprite as one, high ones ripple it
Optionalspeed?: numberhow fast it sways, in radians per second
Optionalstrength?: numberhow far the top moves each way, as a fraction of the sprite's width
Readonlydestroyedtrue once destroy has been called. Distinct from
enabled — which also toggles transiently across a context
lost / restored cycle — to give callers a stable signal for
"this effect has been explicitly released."
whether this effect is active (false in Canvas mode, false after
destroy, and false while the WebGL context is suspended
between an ONCONTEXT_LOST and the matching ONCONTEXT_RESTORED
event).
When true, a renderable will NOT auto-destroy this effect when it is
removed from its postEffects (via the shader setter,
Renderable#removePostEffect, Renderable#clearPostEffects)
or when the renderable itself is destroyed. Set this on an effect shared
across several renderables so one of them going away doesn't free the GL
program still used by the others — you then own its lifecycle and call
destroy yourself.
how fast it sways, in radians per second
Create an independent copy of this effect, swaying the same way. A plain ShaderEffect#clone would copy the uniforms but not the speed, nor the wrapping of the time that keeps the sway smooth.
a new effect
destroy this shader effect. Idempotent — calling destroy twice is safe. Unsubscribes from the renderer's context-lost / restored events so a destroyed effect is not auto-reactivated.
set the wave amplitude
displacement strength in UV space
set the row the wave fades out at
a fraction of the sprite's height from the top (0..1); 0 waves every row alike
set the wave frequency
number of waves
set how far the top moves each way
a fraction of the sprite's width
Bind an extra texture to a named sampler2D uniform in this shader, so
a custom effect can read a second texture — a noise map, mask, gradient,
flow/lookup table — besides the sprite/target it post-processes (uSampler).
The engine uploads, caches, and re-binds it to a reserved texture unit each
time the effect draws, and points the sampler uniform at it — no raw WebGL
texture-unit juggling.
Declare the sampler in your fragment (uniform sampler2D <name>;) and pass
that name here. Any engine texture works — a Texture2d asset
(NoiseTexture2d, TextureAtlas, …) can be passed directly, or a raw
drawable source. No-op in Canvas mode.
the sampler2D uniform name declared in the fragment
the texture: an engine texture asset, or a raw drawable source
Optionalrepeat: "repeat" | "no-repeat" | "repeat-x" | "repeat-y" = "no-repeat"
wrap mode; use "repeat" for a tiled/scrolled texture
this effect for chaining
// "water": distort the sprite by a static noise texture scrolled over time
const noise = new me.NoiseTexture2d({ width: 256, height: 256, seamless: true });
const water = new me.ShaderEffect(renderer, `
uniform sampler2D uNoise;
uniform float uTime;
vec4 apply(vec4 color, vec2 uv) {
vec2 flow = texture2D(uNoise, uv + uTime * 0.03).rg - 0.5;
return texture2D(uSampler, uv + flow * 0.02);
}`);
water.setTexture("uNoise", noise, "repeat");
waterSprite.addPostEffect(water);
// each frame, in your Stage's update(dt):
water.setTime(me.timer.getTime() / 1000);
advance the sway to a moment in time
the time, in seconds (any clock: only its rate matters)
this effect for chaining
Set the uniform to the given value
the uniform name
the value to assign to that
uniform. Scalars (float, int, bool) take a number or a boolean;
vectors and matrices take an array, a Float32Array, or any object
exposing toArray() — which is every Vector2d,
Vector3d, Color and Matrix3d.
Sprites drawn one after the other through the same effect share one draw call. A new value draws the sprites queued before it first, so each sprite draws with the values it was given; the value it already has changes nothing, and keeps the draw shared.
A shader effect that leans a sprite from side to side, as if a breeze went through it: each row is drawn a little to the left or right by a sine of the time, and by more the further above its anchor row it is, so the top sways most and everything from the anchor down stays put. For grass, trees, reeds or a whole background layer: anything planted at its bottom.
Everything is measured across the sprite itself: its strength is a fraction of the sprite's width and its anchor a row of the sprite, so a sprite sways the same whether it has a texture of its own or is cut from an atlas, and whatever else it draws through.
It is a WaveEffect with an anchor and sway-sized defaults, so it shares its shader rather than adding one. The other difference is the time: SwayEffect#setTime wraps the phase to one turn on the CPU before the shader sees it. A raw clock grows without bound, and a medium-precision float, the default on most phones, runs out of digits a few minutes into a session and the sway starts to stutter; a wrapped phase never grows.
See
Renderable#addPostEffect for usage
Example