Your system asks for reduced motion, so VFX-JS draws nothing. Demos on this site show plain HTML.

Type

EffectContext

vfx-js/src/types.ts:820 ↗
import type { EffectContext } from "@vfx-js/core";

Context passed to each Effect lifecycle hook. Fields are updated each frame automatically.

Properties

deltaTime

readonly deltaTime: number

dims

readonly dims: EffectDims

Per-stage layout snapshot — same shape as Effect.outputRect's dims argument. Fresh in update and render; in init it holds placeholder values until the first frame resolves.

enterProgress

readonly enterProgress: number

Enter transition progress, 0 to 1. Plays backward on reversal.

enterTime

readonly enterTime: number

gl

readonly gl: WebGL2RenderingContext

Raw WebGL2 context, for low-level operations (DataTexture upload, extensions, MRT, etc).

Resources allocated here are the caller's responsibility: free in dispose(), rebuild in onContextRestored(cb).

Every draw sets its own framebuffer, viewport, program, VAO, texture bindings and blend state. ctx.draw(), ctx.blit() and ctx.clear() also turn off SCISSOR_TEST, but the rest of the frame (other elements, post effects, the per-frame canvas clear) does not touch scissor.

The rest of the GL state is never set per draw. VFX-JS assumes:

  • SCISSOR_TEST, DEPTH_TEST, CULL_FACE, STENCIL_TEST, POLYGON_OFFSET_FILL, RASTERIZER_DISCARD and SAMPLE_ALPHA_TO_COVERAGE disabled.
  • depthMask(true), colorMask(true, true, true, true), frontFace(CCW) and clearColor(0, 0, 0, 0).
  • No sampler objects, PIXEL_UNPACK_BUFFER or transform feedback bound.
  • UNPACK_ROW_LENGTH, UNPACK_SKIP_* and UNPACK_IMAGE_HEIGHT at 0, and UNPACK_COLORSPACE_CONVERSION_WEBGL at BROWSER_DEFAULT_WEBGL. Texture uploads set UNPACK_FLIP_Y_WEBGL, UNPACK_PREMULTIPLY_ALPHA_WEBGL and UNPACK_ALIGNMENT themselves, so don't rely on their values in raw uploads.

If you change any of this, call EffectContext.resetState when you are done: before the next ctx.draw() / ctx.blit() / ctx.clear(), and before render() returns.

intersection

readonly intersection: number

leaveProgress

readonly leaveProgress: number

Leave transition progress, 0 to 1. Stays 0 until enter finishes.

leaveTime

readonly leaveTime: number

mouse

readonly mouse: readonly [number, number]

Mouse position on the element (element-local, bottom-left origin).

mouseViewport

readonly mouseViewport: readonly [number, number]

Mouse position on the canvas (canvas-local, bottom-left origin).

pixelRatio

readonly pixelRatio: number

quad

readonly quad: EffectQuad

Default fullscreen quad (NDC -1..1), mapped to the target's viewport.

resolution

readonly resolution: readonly [number, number]

Canvas resolution, physical px.

src

readonly src: EffectTexture

Element capture texture (read-only input for the first stage).

target

readonly target: EffectRenderTarget | null

Destination assigned to this stage. null means the canvas.

time

readonly time: number

uniforms

readonly uniforms: Readonly<Record<string, EffectUniformValue>>

User-defined uniforms from VFXProps.uniforms Values are re-evaluated every frame efore update(). Built-in uniforms (time etc) are exposed as top-level ctx fields instead.

vfxProps

readonly vfxProps: EffectVFXProps

blit

blit(
    source: EffectTexture | EffectRenderTarget,
    target?: EffectRenderTarget | null,
    opts?: EffectBlitOpts,
): void

Copy a texture / render target into target (the stage's assigned output, or the canvas, when target is omitted / null).

Samples through the uvSrc varying, so the captured content maps into the destination buffer exactly like the framework's built-in passthrough. Use it instead of hand-written texture(src, uvSrc) copy passes (capture, downsample, source passthrough).

Only valid during Effect.render(); other calls are ignored.

clear

clear(target?: EffectRenderTarget | null): void

Zero a render target with a fast GPU clear, instead of a full-screen draw. Use it to reset accumulation / trail buffers each frame.

Omit target (or pass null) to clear the stage's assigned output. Clears both sides of a ping-pong (persistent: true) RT.

Only valid during Effect.render(); other calls are ignored.

createRenderTarget

createRenderTarget(opts?: EffectRenderTargetOpts): EffectRenderTarget

Allocate a render target.

draw

draw(opts: EffectDrawOpts): void

Run a draw call. Only valid during Effect.render(); other calls are ignored.

onContextRestored

onContextRestored(cb: () => void): () => void

Subscribe to webglcontextrestored to rebuild resources allocated via raw ctx.gl. High-level API resources (createRenderTarget, wrapTexture, EffectGeometry) are restored automatically.

Returns an unsubscribe function; auto-unsubscribed on dispose.

releaseGeometry

releaseGeometry(geometry: EffectGeometry): void

Free the GPU buffers compiled for a geometry.

Call before dropping or replacing an EffectGeometry (e.g. on a density change); otherwise its buffers live until the effect chain is disposed.

resetState

resetState(): void

Put the GL state back to the baseline VFX-JS's pipeline assumes, whatever raw ctx.gl calls changed. It only writes state; it never queries it.

Resets:

  • Draw and read framebuffer to the canvas, drawBuffers([BACK]), and the viewport to the whole canvas.
  • DEPTH_TEST, CULL_FACE, STENCIL_TEST, SCISSOR_TEST, BLEND, POLYGON_OFFSET_FILL, RASTERIZER_DISCARD, SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_COVERAGE disabled.
  • depthMask(true), depthFunc(LESS), colorMask(true × 4), stencilMask(~0), frontFace(CCW), cullFace(BACK), clearColor(0, 0, 0, 0).
  • Program, VAO and the ARRAY_BUFFER, PIXEL_PACK_BUFFER, PIXEL_UNPACK_BUFFER, UNIFORM_BUFFER, COPY_READ_BUFFER, COPY_WRITE_BUFFER bindings unbound. Transform feedback unbound.
  • Sampler objects unbound on every texture unit, and the active texture unit set to TEXTURE0.
  • Pixel store parameters set to the WebGL defaults.

Call it after raw ctx.gl work in render(): before the next ctx.draw() / ctx.blit() / ctx.clear(), and before render() returns. Calling it in init() or update() is allowed but rarely needed, since nothing is drawn there. It does nothing while the WebGL context is lost, or after the effect is disposed.

If you use transform feedback, call gl.endTransformFeedback() first. While transform feedback is active, unbinding it and the program is an INVALID_OPERATION.

Example

render(ctx) {
    const gl = ctx.gl;
    gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);
    gl.enable(gl.DEPTH_TEST);
    // ... custom drawing ...
    ctx.resetState();
    ctx.blit(this.result);
}

wrapTexture

wrapTexture(source: EffectTextureSource, opts?: {
    autoUpdate?: boolean;
    filter?: EffectTextureFilter;
    size?: readonly [number, number];
    wrap?: EffectTextureWrap | readonly [EffectTextureWrap, EffectTextureWrap];
}): EffectTexture

Wrap an externally-produced texture for use as a uniform.

Each call allocates a new GPU texture (no caching), so call this once in init() and reuse the result across frames.

  • DOM sources: dimensions are read automatically, and the texture is restored after WebGL context loss.
  • WebGLTexture: you must pass opts.size, and you must re-wrap the texture yourself from onContextRestored(cb).

autoUpdate defaults to true for HTMLVideoElement, HTMLCanvasElement, and OffscreenCanvas, and false for everything else. With autoUpdate: false, call texture.update() after the source changes.