API reference

Every public class, method, and event in @codexo/exojs. Generated from source.

C

classDisplacementFilter

@codexo/exojs / rendering / stable

A Filter that offsets every fragment's source position by a direction read out of a texture - heat haze, water refraction, glass, shockwaves and dissolve-style warping. The map's red channel drives the horizontal direction and its green channel the vertical, both decoded from `[0, 1]` to `[-1, 1]`, so flat `(0.5, 0.5)` grey is no displacement at all. The result is scaled by scaleX / scaleY in logical units, which keeps the distortion the same size on screen at every pixel ratio and Filter.resolution. ```ts const haze = new DisplacementFilter({ map: noiseTexture, scale: 12 }); water.filters = [haze]; // Scroll the map from the scene's update to animate the distortion. haze.offsetV -= delta * 0.1; ``` A fragment displaced past the edge of the effect domain has nothing to read and comes out transparent rather than smearing the border. The domain grows by the largest displacement on every side, so a subject at rest keeps the room its distortion needs. Runs on a ShaderFilter carrying both a GLSL and a WGSL source, so it works on either backend without the caller choosing one.

6
props
5
methods
0
events
Import
import { DisplacementFilter } from '@codexo/exojs'

A Filter that offsets every fragment's source position by a direction read out of a texture - heat haze, water refraction, glass, shockwaves and dissolve-style warping.

The map's red channel drives the horizontal direction and its green channel the vertical, both decoded from `[0, 1]` to `[-1, 1]`, so flat `(0.5, 0.5)` grey is no displacement at all. The result is scaled by scaleX / scaleY in logical units, which keeps the distortion the same size on screen at every pixel ratio and Filter.resolution.

```ts const haze = new DisplacementFilter({ map: noiseTexture, scale: 12 });

water.filters = [haze];

// Scroll the map from the scene's update to animate the distortion. haze.offsetV -= delta * 0.1; ```

A fragment displaced past the edge of the effect domain has nothing to read and comes out transparent rather than smearing the border. The domain grows by the largest displacement on every side, so a subject at rest keeps the room its distortion needs.

Runs on a ShaderFilter carrying both a GLSL and a WGSL source, so it works on either backend without the caller choosing one.

Constructors1
Methods5
Execute one filter pass: sample from input, write the result to output. Both textures are bounds × resolution texels - NOT the drawable's logical bounding box. Any parameter a subclass expresses in pixels (a blur radius, a displacement amount) is in LOGICAL units by convention and must be multiplied by resolution before it is used as a texel offset; otherwise the effect shrinks by 1/resolution on a HiDPI display. Parameters expressed as a fraction of the target (or as pure colour maths) need no adjustment. The engine always passes resolution. It is optional for the hand-rolled case - a post-processing chain that creates its own RenderTextures and calls apply directly - where the textures are whatever size the caller made them and 1 is the honest answer.
destroy(): void
Release any GPU-side resources held by this filter (uniform buffers, pipelines, intermediate textures). The base drops the attachment list; subclasses with GPU state (BlurFilter, ColorMatrixFilter) override and call super.destroy().
A fragment can be displaced by the full scale in either direction, so the effect reaches that far on every side - the same distance on both axes, because a diagonal displacement uses both at once.
invalidate(): void
Tell every node this filter is attached to that its rendered output is out of date. Call it after mutating anything that changes what the filter draws or how far it reaches - the stock filters do this from their own setters. Without it a cached or retained representation of the owning node keeps replaying the result the filter produced before the change.
setScale(scale: number | readonly [number, number]): this
Set both axes at once. Returns this for chaining.
Properties6
resolution: TargetResolution
Resolution this filter's render targets are rasterized at, in device pixels per logical unit. 'inherit' (the default) matches the surface the result is composited into, so a filtered subtree stays as sharp as its surroundings on a HiDPI display. Lower it for a filter whose output is low-frequency anyway - a heavy blur at 0.5 costs a quarter of the fragments and is hard to tell apart. A filter CHAIN shares one target size, so the whole chain runs at the lowest resolution any of its filters asks for. ts const blur = new BlurFilter({ strength: 4 }); blur.resolution = 0.5; // half-resolution blur, quarter the fill cost
offsetU: number
Horizontal map sampling offset, in the map's own UV units.
offsetV: number
Vertical map sampling offset, in the map's own UV units.
scaleX: number
Maximum horizontal displacement in logical units.
scaleY: number
Maximum vertical displacement in logical units.
Source