Creates a new effect.
The graphics device.
The identifier of the effect, unique among the effects of a camera frame. The names of the chunk, its entry function and its define are derived from it.
Optionaloptions: {The declarations of the effect. All are optional.
OptionalchunkName?: stringThe name the compose chunk can be overridden under, when
it should differ from the derived compose<Id>PS.
OptionaldebugViews?: string[]The names of the debug views the chunk provides. Each
view name requires the chunk to declare a vec3 debug<Name>() function, and is available
while the effect is active.
OptionalentryPoint?: stringThe name of the function the composition calls, when it
should differ from the derived apply<Id>.
Optionalglsl?: stringThe GLSL source of the compose chunk.
Optionalrequires?: string[]The frame resources the effect needs, the FRAMERESOURCE_* constants, see CameraFrameEffect#requires.
Optionalslot?: stringThe compose slot the entry function is called at, one of the COMPOSESLOT_* constants. Omit for an effect that does not take part in the composition, for example one that only owns passes.
Optionalwgsl?: stringThe WGSL source of the compose chunk.
The camera frame the effect is registered with, or null.
The graphics device.
Whether the effect is enabled. An effect can additionally disable itself from its own parameters, see CameraFrameEffect#active.
Gets whether the effect contributes to the frame. Defaults to CameraFrameEffect#enabled. Effects gated on a parameter - a zero intensity, a missing texture - override this.
Gets the scale the effect applies to the exposure of the camera this frame, multiplying the exposure of the scene, or of the physical camera with physical units - for effects adapting the exposure to what the camera sees. Read every frame while the effect takes part, after CameraFrameEffect#frameUpdate; the camera frame applies the product of the scales of the effects taking part, and the camera renders with its own exposure again once none does. Defaults to 1.
// an effect brightening the image by one stop
get cameraExposureScale() {
return 2;
}
Gets the name the compose chunk can be overridden under in ShaderChunks, the same
way as the built-in chunks. Derived from the id as compose<Id>PS unless given.
Gets the names of the debug views the chunk provides.
Gets the define set on the compose shader while the effect is active: the id in upper snake
case, colorEnhance giving COLOR_ENHANCE.
Gets the name of the function the composition calls at the effect's slot. Derived from the
id as apply<Id> unless given. The signature depends on the slot: colour slots take
(vec3 color, vec2 uv) and return the colour, COMPOSESLOT_SCENE takes and returns a
vec4.
Gets the GLSL source of the compose chunk, or null when the effect has none.
Gets the identifier of the effect.
Gets the frame resources the effect needs, the FRAMERESOURCE_* constants - for its passes, or for its compose chunk, such as the scene depth. The camera frame provides them while the effect is active. Requirements which depend on the device are computed when constructing the effect; override this as a getter when they depend on a parameter, and the camera frame provides what it returns from the next CameraFrame#update.
Gets the compose slot the entry function is called at, or null for an effect that does not take part in the composition.
Gets the WGSL source of the compose chunk, or null when the effect has none.
Returns a string which changes whenever the effect's passes need recreating - the parameters which alter the pass graph rather than just its uniforms. Read on each CameraFrame#update while the effect is active: when it differs from the previous update, the camera frame releases the passes with CameraFrameEffect#destroyPasses and creates them again with CameraFrameEffect#createPasses. Parameters the passes pick up in CameraFrameEffect#update do not belong in it. Effects without passes do not implement this.
buildKey() {
// a pass more renders at the high quality
return `${this.highQuality}`;
}
The key.
Creates the passes the effect owns, when it has any. Called by CameraFrame#update when it builds the frame graph, for an active effect registered with the camera frame. Implementing it is what makes an effect own passes. The effect adds each pass to the array of the stage it runs at, in execution order - one effect can run passes at several stages:
createPasses(resources, passes) {
this._pass = new MyPass(this.device, resources.sceneColorHalf);
passes.postResolve.push(this._pass);
}
The effect owns the passes it creates: it releases them in CameraFrameEffect#destroyPasses.
The resources are stable: each texture stays the same object until the passes are destroyed, so it can be handed to the passes once, here. Its size can change, as render targets resize with the canvas, so its dimensions must not be cached. Values which change from frame to frame, the resolved scene color among them, are never resources - they are handed to CameraFrameEffect#frameUpdate instead.
The frame resources the effect requires.
An empty array for each stage of the frame, to add the passes to.
Destroys the effect, removing it from its camera frame if it is still registered and
releasing everything it owns, the passes it created included. Subclasses which create
resources in their constructor release them in an override, calling super.destroy(). The
removal takes effect for the frames rendered after the next CameraFrame#update, which
is due before the next frame renders.
Destroys the passes and any resources CameraFrameEffect#createPasses created.
It is also called when the effect has no passes. Each time the camera frame rebuilds the frame graph, it calls this on every registered effect implementing CameraFrameEffect#createPasses, including inactive effects that never created any. CameraFrameEffect#destroy calls it too, including after the camera frame has already released the passes. So destroy only what exists, and clear the references:
destroyPasses() {
this._pass?.destroy();
this._pass = null;
}
Called every frame while the effect takes part in the frame, while the frame is being
prepared and before any pass renders, with the values of that frame. Most effects do not
need it: their configuration belongs in CameraFrameEffect#update, which runs only
when the camera frame is updated. Values derived from the resolution, which can change
without an update, are computed here from the sizes in the frame, or in the shader from
sceneTextureSize. Anything which changes over time advances here by the time of the frame,
its dt.
The values of this frame. Read them during this call only.
Returns the compose chunk source for a shader language.
SHADERLANGUAGE_GLSL or SHADERLANGUAGE_WGSL.
The source, or null when the effect has no chunk.
Resolves the scene, for an effect whose passes run at the resolve stage - see CameraFrameEffectPasses. Called every frame while the effect's passes take part in the frame, before any pass renders and before CameraFrameEffect#frameUpdate is called on any effect, in the order the effects are registered. The effect hands its passes the scene color the effects before it resolved, and replaces it with the texture they render to this frame, which the effects after it, the half resolution copy of the scene and the composition then read:
resolveScene(scene) {
this._pass.setSourceTexture(scene.texture);
scene.texture = this._pass.outputTexture;
}
An effect resolving the scene to another resolution also sets the width and the height. The default implementation leaves the scene unchanged.
The scene being resolved.
Sets a define on the compose shader. The define persists until changed, so fixed defines can be set once in the constructor and those depending on the parameters from CameraFrameEffect#update. A value of false, null or undefined removes it. Changing a define rebuilds the compose shader.
The define name.
The value.
Sets the value of a uniform the effect's shader chunk reads. Like a material parameter, the value is stored by reference, so an array or a texture can be updated in place. Set the values in CameraFrameEffect#update, or in CameraFrameEffect#frameUpdate for a value which changes every frame.
The name of the uniform, as declared in the chunk.
The value.
Applies the effect's parameters. Called by CameraFrame#update while the effect is active: set the uniform values with CameraFrameEffect#setUniform here, and the defines which depend on the parameters. Everything it sets is what the frames rendered until the next update use.
Base class of an effect registered with a CameraFrame. An effect is constructed with the graphics device, its id and its declarations - the compose slot it applies at and its shader chunk - and exposes its parameters as fields. Declarations are fixed for the life of the effect; anything that depends on a parameter is a getter instead, like CameraFrameEffect#active.
An effect contributes to the composition: you supply its shader chunk (GLSL and WGSL) and write its entry function under a conventional name,
apply<Id>. The camera frame generates the call to that function at the effect's slot, and rebuilds the compose shader when an effect becomes active or inactive, or changes one of its defines. The chunk is only included while the effect is active, so it needs no#ifdefguard of its own - defines are for an effect's own variants, set with CameraFrameEffect#setDefine. The chunk can be overridden by name like the built-in chunks: a chunk set in ShaderChunks undercompose<Id>PSreplaces the effect's own source.<ID>(the id in upper snake case) is defined while the effect is active, should another chunk need to know. Each debug viewnamethe effect lists is backed the same way as the entry function, by adebug<Name>()function in the chunk.All effects registered to a compose slot are called in registration order from within the single compose pass, so contributing to the composition never costs an additional full-screen pass.
An effect can also own passes, for work the composition cannot do in a single sample per pixel, such as a blur at a lower resolution or rendering into the scene. It creates them in CameraFrameEffect#createPasses, from the frame resources it CameraFrameEffect#requires, adding each to the stage of the frame it runs at, and its chunk reads what they render through the uniforms it sets with CameraFrameEffect#setUniform. An effect whose passes resolve the scene, such as an anti-aliasing, replaces the scene color the rest of the frame reads in CameraFrameEffect#resolveScene. An effect owning passes does not need a compose slot.
Every chunk can read what the composition provides: the scene color,
sceneTexture, andsceneTextureSize- the width, height, 1 / width and 1 / height of the scene texture. Use the size for anything which depends on the resolution, such as texel offsets, pixel sizes or the aspect ratio, as it is always current for the camera being drawn. An effect requiring the scene depth, see CameraFrameEffect#requires, can also read it withgetLinearScreenDepth(uv).Like the rest of the camera frame, an effect is configured when CameraFrame#update is called: changes to its parameters, and adding or removing it, take effect at the next update, and every frame rendered after it uses exactly what the update applied.
Lifetime:
Example
Example