-
-
Notifications
You must be signed in to change notification settings - Fork 214
Custom Effects
Effects are lightweight fullscreen passes. They can be combined using the EffectPass.
Just like passes, effects may perform initialization tasks, react to render size changes and execute supporting render operations if needed but they don't have access to an output buffer and are not supposed to render to screen by themselves.
Code Example
uniform vec3 weights;
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
outputColor = vec4(inputColor.rgb * weights, inputColor.a);
}
import { Uniform, Vector3 } from "three";
import { BlendFunction, Effect } from "postprocessing";
// Using rollup-plugin-glsl to import shader files.
import fragmentShader from "./shader.frag";
export class CustomEffect extends Effect {
constructor() {
super("CustomEffect", fragmentShader, {
blendFunction: BlendFunction.Normal,
uniforms: new Map([
["weights", new Uniform(new Vector3())]
])
});
}
}
Every effect must provide a fragment shader that implements at least one of these two functions:
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor);
void mainUv(inout vec2 uv);
If the effect relies on depth, it can choose to implement a slightly different mainImage
function:
void mainImage(const in vec4 inputColor, const in vec2 uv,
const in float depth, out vec4 outputColor);
Effects may also provide a vertex shader that implements the following function:
void mainSupport();
If you need access to the screen uv
coordinates, use the following function signature:
void mainSupport(const in vec2 uv);
Some effects perform special operations inside the fragment shader or require additional resources. There are currently two EffectAttributes available: CONVOLUTION
and DEPTH
. Most effects do not need to specify any attributes.
Attributes can be concatenated using the bitwise OR operator.
class MyEffect extends Effect {
constructor() {
super(name, fragmentShader, {
attributes: EffectAttribute.CONVOLUTION | EffectAttribute.DEPTH
});
}
}
Effects that fetch additional samples from the input buffer inside the fragment shader must specify the CONVOLUTION
attribute. To prevent bad results, it is not allowed to have more than one effect with this attribute per EffectPass
. Convolution effects are also incompatible with effects that implement the mainUv
function. The EffectPass
will warn you when it encounters incompatible effects.
The DEPTH
attribute must be specified by effects that require a depth texture. When the EffectPass
encounters an effect with this attribute, it will request a depth texture from the EffectComposer
. If your fragment shader implements the depth variant of the mainImage
function, depth will be read automatically and the value will be provided to your mainImage
function.
In case you wish to sample depth at another coordinate, use the predefined function float readDepth(const in vec2 uv)
. To calculate the view Z based on depth, you can use the predefined function float getViewZ(const in float depth)
.
All shaders have access to the following uniforms:
uniform vec2 resolution;
uniform vec2 texelSize;
uniform float cameraNear;
uniform float cameraFar;
uniform float aspect;
uniform float time;
The fragment shader has access to the following additional uniforms:
uniform sampler2D inputBuffer;
uniform sampler2D depthBuffer;
The following varyings are reserved:
varying vec2 vUv;
Available vertex attributes:
attribute vec3 position;
Available macros:
- If the camera of the associated
EffectPass
is aPerspectiveCamera
, the macroPERSPECTIVE_CAMERA
will be defined. - If the composer uses
HalfFloatType
frame buffers, the macroFRAMEBUFFER_PRECISION_HIGH
will be defined.
Effects may define custom uniforms, varyings, functions and preprocessor macros as usual, but should not define global variables or constants.
Furthermore, the shader chunks common and packing are included in the fragment shader by default.
Effects can enable a set of shader extensions via the extensions
constructor option. The available WebGLExtensions are DERIVATIVES
, FRAG_DEPTH
, DRAW_BUFFERS
and SHADER_TEXTURE_LOD
.
Code Example
class MyEffect extends Effect {
constructor() {
super(name, fragmentShader, {
extensions: new Set([WebGLExtension.DERIVATIVES])
});
}
}