-
-
Notifications
You must be signed in to change notification settings - Fork 237
Custom Passes
There are two options for creating custom passes. You can either rely on the general-purpose ShaderPass or extend Pass.
The ShaderPass expects an instance of ShaderMaterial as its first argument. The second argument specifies the name of the texture sampler uniform of the shader you provide. This name defaults to tDiffuse and the ShaderPass binds the read buffer to this uniform.
In order to render a simple ShaderMaterial, you have to pass your shader object (uniforms, defines, fragment and vertex shader code) to ShaderMaterial and then pass that material instance to ShaderPass and adjust the name of the input texture if necessary.
import { ShaderMaterial } from "three";
import { ShaderPass } from "postprocessing";
const myShaderMaterial = new ShaderMaterial({
defines: { ... },
uniforms: { ... }
vertexShader: `...`,
fragmentShader: `...`
});
const myShaderPass = new ShaderPass(myShaderMaterial, "myInputSampler");An example that uses the Kaleidoscope Shader from the three.js examples together with the ShaderPass can be found here.
More complex passes often use more than one ShaderMaterial or require additional programming. By extending the Pass class you can decide what happens with your pass during resizing, initialisation and rendering.
There are three points that need to be taken care of when creating a custom pass:
- Override the
rendermethod - Assign a
ShaderMaterialto thequadthat fills the screen - Set
needsSwaptotrueif your pass renders to thewriteBuffer
All of these tasks are intertwined. By overriding the render method you define where your result is rendered to. You can assign different materials to the screen quad for multiple independent render operations or you can assign only one material in the constructor. You're also free to create custom render targets in your pass and you don't have to worry about destroying them thanks to the already implemented dispose method that every pass inherits from Pass.
As stated in the docs, the render method gains access to a readBuffer as well as a writeBuffer. Reading from and writing to the same render target should be avoided. Therefore, two seperate yet identical buffers are used. The EffectComposer does not know into which buffer your pass renders its results. This means that your pass needs to explicitly tell the composer whether the readBuffer should be swapped with the writeBuffer after it is done rendering so that the next pass can find your results in the readBuffer.
Note that Passes don't have to use the buffers that are provided in the render method. Writing self-contained render-to-texture passes is also a feasible option.
For reference, take a look at the existing passes.