-
-
Notifications
You must be signed in to change notification settings - Fork 219
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.
Full 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 { Effect } from "postprocessing";
// Using rollup-plugin-string to import text files.
import fragment from "./shader.frag";
export class CustomEffect extends Effect {
constructor() {
super("CustomEffect", fragment, {
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(const inout vec2 uv);
If the effect relies on depth, it must 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();
However, most effect do not need a vertex shader.
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.
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 transform UV coordinates inside the fragment shader.
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
. Inside the fragment shader, depth will only be read once and the value will be provided to your mainImage
function.
Attributes can be concatenated using the bitwise OR operator:
class MyEffect extends Effect {
constructor() {
super(name, fragmentShader, {
attributes: EffectAttribute.CONVOLUTION | EffectAttribute.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;
Effects may define custom uniforms, varyings, functions and preprocessor macros as usual, but should not define global variables or constants.
If the camera of the associated EffectPass
is a PerspectiveCamera
, the macro
PERSPECTIVE_CAMERA
will be defined. Furthermore, the shader chunks
common
and packing
are included in the fragment shader.