Skip to content

Docs: More JSDoc. #30727

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 90 additions & 38 deletions examples/jsm/postprocessing/AfterimagePass.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,103 +10,155 @@ import { Pass, FullScreenQuad } from './Pass.js';
import { CopyShader } from '../shaders/CopyShader.js';
import { AfterimageShader } from '../shaders/AfterimageShader.js';

/**
* Pass for a basic after image effect.
*
* ```js
* const afterimagePass = new AfterimagePass( 0.9 );
* composer.addPass( afterimagePass );
* ```
*
* @augments Pass
*/
class AfterimagePass extends Pass {

/**
* Constructs a new after image pass.
*
* @param {number} [damp=0.96] - The damping intensity. A higher value means a stronger after image effect.
*/
constructor( damp = 0.96 ) {

super();

this.shader = AfterimageShader;

this.uniforms = UniformsUtils.clone( this.shader.uniforms );
/**
* The pass uniforms. Use this object if you want to update the
* `damp` value at runtime.
* ```js
* pass.uniforms.damp.value = 0.9;
* ```
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( AfterimageShader.uniforms );

this.uniforms[ 'damp' ].value = damp;

this.textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );

this.textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );

/**
* The composition material.
*
* @type {ShaderMaterial}
*/
this.compFsMaterial = new ShaderMaterial( {

uniforms: this.uniforms,
vertexShader: this.shader.vertexShader,
fragmentShader: this.shader.fragmentShader
vertexShader: AfterimageShader.vertexShader,
fragmentShader: AfterimageShader.fragmentShader

} );

this.compFsQuad = new FullScreenQuad( this.compFsMaterial );

const copyShader = CopyShader;

/**
* The copy material.
*
* @type {ShaderMaterial}
*/
this.copyFsMaterial = new ShaderMaterial( {
uniforms: UniformsUtils.clone( copyShader.uniforms ),
vertexShader: copyShader.vertexShader,
fragmentShader: copyShader.fragmentShader,
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
vertexShader: CopyShader.vertexShader,
fragmentShader: CopyShader.fragmentShader,
blending: NoBlending,
depthTest: false,
depthWrite: false
} );

this.copyFsQuad = new FullScreenQuad( this.copyFsMaterial );
// internals

this._textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );

this._textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );

this._compFsQuad = new FullScreenQuad( this.compFsMaterial );
this._copyFsQuad = new FullScreenQuad( this.copyFsMaterial );

}

/**
* Performs the after image pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {

this.uniforms[ 'tOld' ].value = this.textureOld.texture;
this.uniforms[ 'tOld' ].value = this._textureOld.texture;
this.uniforms[ 'tNew' ].value = readBuffer.texture;

renderer.setRenderTarget( this.textureComp );
this.compFsQuad.render( renderer );
renderer.setRenderTarget( this._textureComp );
this._compFsQuad.render( renderer );

this.copyFsQuad.material.uniforms.tDiffuse.value = this.textureComp.texture;
this._copyFsQuad.material.uniforms.tDiffuse.value = this._textureComp.texture;

if ( this.renderToScreen ) {

renderer.setRenderTarget( null );
this.copyFsQuad.render( renderer );
this._copyFsQuad.render( renderer );

} else {

renderer.setRenderTarget( writeBuffer );

if ( this.clear ) renderer.clear();

this.copyFsQuad.render( renderer );
this._copyFsQuad.render( renderer );

}

// Swap buffers.
const temp = this.textureOld;
this.textureOld = this.textureComp;
this.textureComp = temp;
const temp = this._textureOld;
this._textureOld = this._textureComp;
this._textureComp = temp;
// Now textureOld contains the latest image, ready for the next frame.

}

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {

this.textureComp.setSize( width, height );
this.textureOld.setSize( width, height );
this._textureComp.setSize( width, height );
this._textureOld.setSize( width, height );

}

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

this.textureComp.dispose();
this.textureOld.dispose();
this._textureComp.dispose();
this._textureOld.dispose();

this.compFsMaterial.dispose();
this.copyFsMaterial.dispose();

this.compFsQuad.dispose();
this.copyFsQuad.dispose();
this._compFsQuad.dispose();
this._copyFsQuad.dispose();

}

Expand Down
112 changes: 89 additions & 23 deletions examples/jsm/postprocessing/BloomPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,47 @@ import {
import { Pass, FullScreenQuad } from './Pass.js';
import { ConvolutionShader } from '../shaders/ConvolutionShader.js';

/**
* A pass for a basic Bloom effect.
*
* {@link UnrealBloomPass} produces a more advanced Bloom but is also
* more expensive.
*
* ```js
* const effectBloom = new BloomPass( 0.75 );
* composer.addPass( effectBloom );
* ```
*
* @augments Pass
*/
class BloomPass extends Pass {

/**
* Constructs a new Bloom pass.
*
* @param {number} [strength=1] - The Bloom strength.
* @param {number} [kernelSize=25] - The kernel size.
* @param {number} [sigma=4] - The sigma.
*/
constructor( strength = 1, kernelSize = 25, sigma = 4 ) {

super();

// render targets

this.renderTargetX = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this.renderTargetX.texture.name = 'BloomPass.x';
this.renderTargetY = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this.renderTargetY.texture.name = 'BloomPass.y';

// combine material

/**
* The combine pass uniforms.
*
* @type {Object}
*/
this.combineUniforms = UniformsUtils.clone( CombineShader.uniforms );

this.combineUniforms[ 'strength' ].value = strength;

/**
* The combine pass material.
*
* @type {ShaderMaterial}
*/
this.materialCombine = new ShaderMaterial( {

name: CombineShader.name,
Expand All @@ -43,11 +65,21 @@ class BloomPass extends Pass {

const convolutionShader = ConvolutionShader;

/**
* The convolution pass uniforms.
*
* @type {Object}
*/
this.convolutionUniforms = UniformsUtils.clone( convolutionShader.uniforms );

this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX;
this.convolutionUniforms[ 'cKernel' ].value = ConvolutionShader.buildKernel( sigma );

/**
* The convolution pass material.
*
* @type {ShaderMaterial}
*/
this.materialConvolution = new ShaderMaterial( {

name: convolutionShader.name,
Expand All @@ -61,67 +93,101 @@ class BloomPass extends Pass {

} );

/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;

this.fsQuad = new FullScreenQuad( null );
// internals

this._renderTargetX = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this._renderTargetX.texture.name = 'BloomPass.x';
this._renderTargetY = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this._renderTargetY.texture.name = 'BloomPass.y';

this._fsQuad = new FullScreenQuad( null );

}

/**
* Performs the Bloom pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {

if ( maskActive ) renderer.state.buffers.stencil.setTest( false );

// Render quad with blurred scene into texture (convolution pass 1)

this.fsQuad.material = this.materialConvolution;
this._fsQuad.material = this.materialConvolution;

this.convolutionUniforms[ 'tDiffuse' ].value = readBuffer.texture;
this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX;

renderer.setRenderTarget( this.renderTargetX );
renderer.setRenderTarget( this._renderTargetX );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );


// Render quad with blurred scene into texture (convolution pass 2)

this.convolutionUniforms[ 'tDiffuse' ].value = this.renderTargetX.texture;
this.convolutionUniforms[ 'tDiffuse' ].value = this._renderTargetX.texture;
this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurY;

renderer.setRenderTarget( this.renderTargetY );
renderer.setRenderTarget( this._renderTargetY );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

// Render original scene with superimposed blur to texture

this.fsQuad.material = this.materialCombine;
this._fsQuad.material = this.materialCombine;

this.combineUniforms[ 'tDiffuse' ].value = this.renderTargetY.texture;
this.combineUniforms[ 'tDiffuse' ].value = this._renderTargetY.texture;

if ( maskActive ) renderer.state.buffers.stencil.setTest( true );

renderer.setRenderTarget( readBuffer );
if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

}

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {

this.renderTargetX.setSize( width, height );
this.renderTargetY.setSize( width, height );
this._renderTargetX.setSize( width, height );
this._renderTargetY.setSize( width, height );

}

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

this.renderTargetX.dispose();
this.renderTargetY.dispose();
this._renderTargetX.dispose();
this._renderTargetY.dispose();

this.materialCombine.dispose();
this.materialConvolution.dispose();

this.fsQuad.dispose();
this._fsQuad.dispose();

}

Expand Down
Loading
Loading