the current renderer instance
Optionaloptions: { color?: Color; intensity?: number } = {}
initial uniform values
Optionalcolor?: Colorcenter color (0..255 RGB, and its alpha scales the gradient); defaults to opaque white
Optionalintensity?: numberpeak alpha at the center (0..1+)
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.
Create an independent copy of this effect, compiled as its own GL program. Use it when several renderables need the same effect with different uniform values — a single instance has a single set of uniforms, shared by everything it is assigned to.
The clone copies the recipe: the fragment source, float precision,
every uniform value set so far, and any extra textures bound via
setTexture (the clone uploads and owns its own GL copies).
It does NOT copy ownership or lifecycle state — in particular the
clone's shared flag is always reset to false, even when
cloning a shared shader (such as one returned by loader.getShader()):
the clone is caller-owned and will be auto-destroyed by the renderable
it is assigned to, exactly like a hand-constructed effect. Set
shared = true on the clone yourself if you intend to reuse it across
several renderables.
a new, caller-owned effect (shared === false)
// the loader's shader is ONE shared program — one uniform state for all
sprite.addPostEffect(loader.getShader("flash"));
// the boss needs its own intensity — clone a private, caller-owned copy
const bossFlash = loader.getShader("flash").clone();
boss.addPostEffect(bossFlash);
bossFlash.setUniform("uIntensity", 0.9);
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 center color. Its alpha scales the whole gradient, on top of the falloff, so a half-transparent color gives a half-strength spot.
0..255 RGB color, with its alpha
Set the peak intensity. Acts as a brightness multiplier on the falloff curve; values above 1 over-saturate the center of the gradient.
0..1+ multiplier
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);
Set the shader's uTime uniform (elapsed time, in seconds). A convenience
over setUniform("uTime", ...); call it once per frame from your update
loop to animate a shader that declares uniform float uTime (e.g. scrolling
a static noise texture's UVs, pulsing, waving). Drive it with whatever clock
you like — real time, a paused/scaled/scrubbed one.
No-op if the shader does not declare a uTime uniform (nothing to update),
or in Canvas mode. The engine does NOT call this for you — animation is
opt-in, exactly like re-baking a NoiseTexture2d with update(dt).
elapsed time in seconds
this effect for chaining
// a shader that scrolls a static seamless noise texture over time
const flow = new me.ShaderEffect(renderer, `
uniform float uTime;
vec4 apply(vec4 color, vec2 uv) {
return texture2D(uSampler, uv + vec2(uTime * 0.05, 0.0));
}`);
mySprite.addPostEffect(flow);
// then in your Stage's update(dt):
flow.setTime(me.timer.getTime() / 1000);
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 procedural radial-gradient shader effect: solid color at the center fading linearly to fully transparent at the edge of the host quad. The falloff is naturally elliptical for non-square quads.
It is centred on the renderable it draws, wherever that sits in its texture: a dedicated 1×1 white pixel, a standalone image, a sprite cut from an atlas, or the engine-provided light atlas used by
WebGLRenderer.drawLight.The falloff curve is linear (
f = clamp(1 - d, 0, 1)) to match the Canvas 2DcreateRadialGradienttwo-stop output exactly. Output is premultiplied so the result composes correctly under additive ("lighter") blending across overlapping quads.Color & intensity come from two stacked sources, multiplied together: the
uColor/uIntensityuniforms (set per-effect viasetColor/setIntensity— the natural API for a single-instance shader attached to a renderable) AND the per-vertex tint coming throughaColor(used byWebGLRenderer.drawLightto encode each light's color + intensity in the vertex stream so multiple lights sharing this shader can batch into a single draw call). For typical standalone usage the per-vertex tint is(1,1,1,1)and the uniforms drive the look; for the Light2d batching path the uniforms stay at defaults and the tint carries everything.Example
Example
Example
Example
Example
Example