feat: initialize project with core dependencies and game entry point
This commit is contained in:
185
node_modules/three/examples/jsm/postprocessing/AfterimagePass.js
generated
vendored
Normal file
185
node_modules/three/examples/jsm/postprocessing/AfterimagePass.js
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
import {
|
||||
HalfFloatType,
|
||||
NearestFilter,
|
||||
NoBlending,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
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
|
||||
* @three_import import { AfterimagePass } from 'three/addons/postprocessing/AfterimagePass.js';
|
||||
*/
|
||||
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();
|
||||
|
||||
/**
|
||||
* 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.damp = damp;
|
||||
|
||||
/**
|
||||
* The composition material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.compFsMaterial = new ShaderMaterial( {
|
||||
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: AfterimageShader.vertexShader,
|
||||
fragmentShader: AfterimageShader.fragmentShader
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* The copy material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.copyFsMaterial = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
blending: NoBlending,
|
||||
depthTest: false,
|
||||
depthWrite: false
|
||||
} );
|
||||
|
||||
// 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 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The damping intensity, from 0.0 to 1.0. A higher value means a stronger after image effect.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
get damp() {
|
||||
|
||||
return this.uniforms[ 'damp' ].value;
|
||||
|
||||
}
|
||||
|
||||
set damp( value ) {
|
||||
|
||||
this.uniforms[ 'damp' ].value = value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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[ 'tNew' ].value = readBuffer.texture;
|
||||
|
||||
renderer.setRenderTarget( this._textureComp );
|
||||
this._compFsQuad.render( renderer );
|
||||
|
||||
this._copyFsQuad.material.uniforms.tDiffuse.value = this._textureComp.texture;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._copyFsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
|
||||
if ( this.clear ) renderer.clear();
|
||||
|
||||
this._copyFsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
// Swap buffers.
|
||||
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 height to set.
|
||||
*/
|
||||
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.compFsMaterial.dispose();
|
||||
this.copyFsMaterial.dispose();
|
||||
|
||||
this._compFsQuad.dispose();
|
||||
this._copyFsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { AfterimagePass };
|
||||
274
node_modules/three/examples/jsm/postprocessing/BloomPass.js
generated
vendored
Normal file
274
node_modules/three/examples/jsm/postprocessing/BloomPass.js
generated
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
import {
|
||||
AdditiveBlending,
|
||||
HalfFloatType,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
Vector2,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
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
|
||||
* @three_import import { BloomPass } from 'three/addons/postprocessing/BloomPass.js';
|
||||
*/
|
||||
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();
|
||||
|
||||
// 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,
|
||||
uniforms: this.combineUniforms,
|
||||
vertexShader: CombineShader.vertexShader,
|
||||
fragmentShader: CombineShader.fragmentShader,
|
||||
blending: AdditiveBlending,
|
||||
transparent: true
|
||||
|
||||
} );
|
||||
|
||||
// convolution material
|
||||
|
||||
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 = buildKernel( sigma );
|
||||
|
||||
/**
|
||||
* The convolution pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.materialConvolution = new ShaderMaterial( {
|
||||
|
||||
name: convolutionShader.name,
|
||||
uniforms: this.convolutionUniforms,
|
||||
vertexShader: convolutionShader.vertexShader,
|
||||
fragmentShader: convolutionShader.fragmentShader,
|
||||
defines: {
|
||||
'KERNEL_SIZE_FLOAT': kernelSize.toFixed( 1 ),
|
||||
'KERNEL_SIZE_INT': kernelSize.toFixed( 0 )
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
// 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.convolutionUniforms[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX;
|
||||
|
||||
renderer.setRenderTarget( this._renderTargetX );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
|
||||
// Render quad with blurred scene into texture (convolution pass 2)
|
||||
|
||||
this.convolutionUniforms[ 'tDiffuse' ].value = this._renderTargetX.texture;
|
||||
this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurY;
|
||||
|
||||
renderer.setRenderTarget( this._renderTargetY );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// Render original scene with superimposed blur to texture
|
||||
|
||||
this._fsQuad.material = this.materialCombine;
|
||||
|
||||
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 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
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.materialCombine.dispose();
|
||||
this.materialConvolution.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const CombineShader = {
|
||||
|
||||
name: 'CombineShader',
|
||||
|
||||
uniforms: {
|
||||
|
||||
'tDiffuse': { value: null },
|
||||
'strength': { value: 1.0 }
|
||||
|
||||
},
|
||||
|
||||
vertexShader: /* glsl */`
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}`,
|
||||
|
||||
fragmentShader: /* glsl */`
|
||||
|
||||
uniform float strength;
|
||||
|
||||
uniform sampler2D tDiffuse;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 texel = texture2D( tDiffuse, vUv );
|
||||
gl_FragColor = strength * texel;
|
||||
|
||||
}`
|
||||
|
||||
};
|
||||
|
||||
BloomPass.blurX = new Vector2( 0.001953125, 0.0 );
|
||||
BloomPass.blurY = new Vector2( 0.0, 0.001953125 );
|
||||
|
||||
|
||||
function gauss( x, sigma ) {
|
||||
|
||||
return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) );
|
||||
|
||||
}
|
||||
|
||||
function buildKernel( sigma ) {
|
||||
|
||||
// We loop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway.
|
||||
|
||||
const kMaxKernelSize = 25;
|
||||
let kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1;
|
||||
|
||||
if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize;
|
||||
|
||||
const halfWidth = ( kernelSize - 1 ) * 0.5;
|
||||
|
||||
const values = new Array( kernelSize );
|
||||
let sum = 0.0;
|
||||
for ( let i = 0; i < kernelSize; ++ i ) {
|
||||
|
||||
values[ i ] = gauss( i - halfWidth, sigma );
|
||||
sum += values[ i ];
|
||||
|
||||
}
|
||||
|
||||
// normalize the kernel
|
||||
|
||||
for ( let i = 0; i < kernelSize; ++ i ) values[ i ] /= sum;
|
||||
|
||||
return values;
|
||||
|
||||
}
|
||||
|
||||
export { BloomPass };
|
||||
218
node_modules/three/examples/jsm/postprocessing/BokehPass.js
generated
vendored
Normal file
218
node_modules/three/examples/jsm/postprocessing/BokehPass.js
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
import {
|
||||
Color,
|
||||
HalfFloatType,
|
||||
MeshDepthMaterial,
|
||||
NearestFilter,
|
||||
NoBlending,
|
||||
RGBADepthPacking,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { BokehShader } from '../shaders/BokehShader.js';
|
||||
|
||||
/**
|
||||
* Pass for creating depth of field (DOF) effect.
|
||||
*
|
||||
* ```js
|
||||
* const bokehPass = new BokehPass( scene, camera, {
|
||||
* focus: 500
|
||||
* aperture: 5,
|
||||
* maxblur: 0.01
|
||||
* } );
|
||||
* composer.addPass( bokehPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { BokehPass } from 'three/addons/postprocessing/BokehPass.js';
|
||||
*/
|
||||
class BokehPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new Bokeh pass.
|
||||
*
|
||||
* @param {Scene} scene - The scene to render the DOF for.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {BokehPass~Options} params - The pass options.
|
||||
*/
|
||||
constructor( scene, camera, params ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scene to render the DOF for.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
const focus = ( params.focus !== undefined ) ? params.focus : 1.0;
|
||||
const aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025;
|
||||
const maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0;
|
||||
|
||||
// render targets
|
||||
|
||||
this._renderTargetDepth = new WebGLRenderTarget( 1, 1, { // will be resized later
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter,
|
||||
type: HalfFloatType
|
||||
} );
|
||||
|
||||
this._renderTargetDepth.texture.name = 'BokehPass.depth';
|
||||
|
||||
// depth material
|
||||
|
||||
this._materialDepth = new MeshDepthMaterial();
|
||||
this._materialDepth.depthPacking = RGBADepthPacking;
|
||||
this._materialDepth.blending = NoBlending;
|
||||
|
||||
// bokeh material
|
||||
|
||||
const bokehUniforms = UniformsUtils.clone( BokehShader.uniforms );
|
||||
|
||||
bokehUniforms[ 'tDepth' ].value = this._renderTargetDepth.texture;
|
||||
|
||||
bokehUniforms[ 'focus' ].value = focus;
|
||||
bokehUniforms[ 'aspect' ].value = camera.aspect;
|
||||
bokehUniforms[ 'aperture' ].value = aperture;
|
||||
bokehUniforms[ 'maxblur' ].value = maxblur;
|
||||
bokehUniforms[ 'nearClip' ].value = camera.near;
|
||||
bokehUniforms[ 'farClip' ].value = camera.far;
|
||||
|
||||
/**
|
||||
* The pass bokeh material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.materialBokeh = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, BokehShader.defines ),
|
||||
uniforms: bokehUniforms,
|
||||
vertexShader: BokehShader.vertexShader,
|
||||
fragmentShader: BokehShader.fragmentShader
|
||||
} );
|
||||
|
||||
/**
|
||||
* The pass uniforms. Use this object if you want to update the
|
||||
* `focus`, `aperture` or `maxblur` values at runtime.
|
||||
*
|
||||
* ```js
|
||||
* pass.uniforms.focus.value = focus;
|
||||
* pass.uniforms.aperture.value = aperture;
|
||||
* pass.uniforms.maxblur.value = maxblur;
|
||||
* ```
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = bokehUniforms;
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.materialBokeh );
|
||||
|
||||
this._oldClearColor = new Color();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the Bokeh 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*/ ) {
|
||||
|
||||
// Render depth into texture
|
||||
|
||||
this.scene.overrideMaterial = this._materialDepth;
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
const oldClearAlpha = renderer.getClearAlpha();
|
||||
const oldAutoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
renderer.setClearColor( 0xffffff );
|
||||
renderer.setClearAlpha( 1.0 );
|
||||
renderer.setRenderTarget( this._renderTargetDepth );
|
||||
renderer.clear();
|
||||
renderer.render( this.scene, this.camera );
|
||||
|
||||
// Render bokeh composite
|
||||
|
||||
this.uniforms[ 'tColor' ].value = readBuffer.texture;
|
||||
this.uniforms[ 'nearClip' ].value = this.camera.near;
|
||||
this.uniforms[ 'farClip' ].value = this.camera.far;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
this.scene.overrideMaterial = null;
|
||||
renderer.setClearColor( this._oldClearColor );
|
||||
renderer.setClearAlpha( oldClearAlpha );
|
||||
renderer.autoClear = oldAutoClear;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.materialBokeh.uniforms[ 'aspect' ].value = width / height;
|
||||
|
||||
this._renderTargetDepth.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._renderTargetDepth.dispose();
|
||||
|
||||
this._materialDepth.dispose();
|
||||
this.materialBokeh.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor options of `BokehPass`.
|
||||
*
|
||||
* @typedef {Object} BokehPass~Options
|
||||
* @property {number} [focus=1] - Defines the effect's focus which is the distance along the camera's look direction in world units.
|
||||
* @property {number} [aperture=0.025] - Defines the effect's aperture.
|
||||
* @property {number} [maxblur=1] - Defines the effect's maximum blur.
|
||||
**/
|
||||
|
||||
export { BokehPass };
|
||||
97
node_modules/three/examples/jsm/postprocessing/ClearPass.js
generated
vendored
Normal file
97
node_modules/three/examples/jsm/postprocessing/ClearPass.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import {
|
||||
Color
|
||||
} from 'three';
|
||||
import { Pass } from './Pass.js';
|
||||
|
||||
/**
|
||||
* This class can be used to force a clear operation for the current read or
|
||||
* default framebuffer (when rendering to screen).
|
||||
*
|
||||
* ```js
|
||||
* const clearPass = new ClearPass();
|
||||
* composer.addPass( clearPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { ClearPass } from 'three/addons/postprocessing/ClearPass.js';
|
||||
*/
|
||||
class ClearPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new clear pass.
|
||||
*
|
||||
* @param {(number|Color|string)} [clearColor=0x000000] - The clear color.
|
||||
* @param {number} [clearAlpha=0] - The clear alpha.
|
||||
*/
|
||||
constructor( clearColor = 0x000000, clearAlpha = 0 ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
/**
|
||||
* The clear color.
|
||||
*
|
||||
* @type {(number|Color|string)}
|
||||
* @default 0x000000
|
||||
*/
|
||||
this.clearColor = clearColor;
|
||||
|
||||
/**
|
||||
* The clear alpha.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.clearAlpha = clearAlpha;
|
||||
|
||||
// internals
|
||||
|
||||
this._oldClearColor = new Color();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the clear operation. This affects the current read or the default framebuffer.
|
||||
*
|
||||
* @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 */ ) {
|
||||
|
||||
let oldClearAlpha;
|
||||
|
||||
if ( this.clearColor ) {
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
oldClearAlpha = renderer.getClearAlpha();
|
||||
|
||||
renderer.setClearColor( this.clearColor, this.clearAlpha );
|
||||
|
||||
}
|
||||
|
||||
renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
|
||||
renderer.clear();
|
||||
|
||||
if ( this.clearColor ) {
|
||||
|
||||
renderer.setClearColor( this._oldClearColor, oldClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { ClearPass };
|
||||
146
node_modules/three/examples/jsm/postprocessing/CubeTexturePass.js
generated
vendored
Normal file
146
node_modules/three/examples/jsm/postprocessing/CubeTexturePass.js
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
import {
|
||||
BackSide,
|
||||
BoxGeometry,
|
||||
Mesh,
|
||||
PerspectiveCamera,
|
||||
Scene,
|
||||
ShaderLib,
|
||||
ShaderMaterial,
|
||||
UniformsUtils
|
||||
} from 'three';
|
||||
import { Pass } from './Pass.js';
|
||||
|
||||
/**
|
||||
* This pass can be used to render a cube texture over the entire screen.
|
||||
*
|
||||
* ```js
|
||||
* const cubeMap = new THREE.CubeTextureLoader().load( urls );
|
||||
*
|
||||
* const cubeTexturePass = new CubeTexturePass( camera, cubemap );
|
||||
* composer.addPass( cubeTexturePass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { CubeTexturePass } from 'three/addons/postprocessing/CubeTexturePass.js';
|
||||
*/
|
||||
class CubeTexturePass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new cube texture pass.
|
||||
*
|
||||
* @param {PerspectiveCamera} camera - The camera.
|
||||
* @param {CubeTexture} tCube - The cube texture to render.
|
||||
* @param {number} [opacity=1] - The opacity.
|
||||
*/
|
||||
constructor( camera, tCube, opacity = 1 ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {PerspectiveCamera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* The cube texture to render.
|
||||
*
|
||||
* @type {CubeTexture}
|
||||
*/
|
||||
this.tCube = tCube;
|
||||
|
||||
/**
|
||||
* The opacity.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.opacity = opacity;
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
// internals
|
||||
|
||||
const cubeShader = ShaderLib[ 'cube' ];
|
||||
|
||||
this._cubeMesh = new Mesh(
|
||||
new BoxGeometry( 10, 10, 10 ),
|
||||
new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( cubeShader.uniforms ),
|
||||
vertexShader: cubeShader.vertexShader,
|
||||
fragmentShader: cubeShader.fragmentShader,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
side: BackSide
|
||||
} )
|
||||
);
|
||||
|
||||
Object.defineProperty( this._cubeMesh.material, 'envMap', {
|
||||
|
||||
get: function () {
|
||||
|
||||
return this.uniforms.tCube.value;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
this._cubeScene = new Scene();
|
||||
this._cubeCamera = new PerspectiveCamera();
|
||||
this._cubeScene.add( this._cubeMesh );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the cube texture 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*/ ) {
|
||||
|
||||
const oldAutoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
this._cubeCamera.projectionMatrix.copy( this.camera.projectionMatrix );
|
||||
this._cubeCamera.quaternion.setFromRotationMatrix( this.camera.matrixWorld );
|
||||
|
||||
this._cubeMesh.material.uniforms.tCube.value = this.tCube;
|
||||
this._cubeMesh.material.uniforms.tFlip.value = ( this.tCube.isCubeTexture && this.tCube.isRenderTargetTexture === false ) ? - 1 : 1;
|
||||
this._cubeMesh.material.uniforms.opacity.value = this.opacity;
|
||||
this._cubeMesh.material.transparent = ( this.opacity < 1.0 );
|
||||
|
||||
renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
renderer.render( this._cubeScene, this._cubeCamera );
|
||||
|
||||
renderer.autoClear = oldAutoClear;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this._cubeMesh.geometry.dispose();
|
||||
this._cubeMesh.material.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { CubeTexturePass };
|
||||
114
node_modules/three/examples/jsm/postprocessing/DotScreenPass.js
generated
vendored
Normal file
114
node_modules/three/examples/jsm/postprocessing/DotScreenPass.js
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
import {
|
||||
ShaderMaterial,
|
||||
UniformsUtils
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { DotScreenShader } from '../shaders/DotScreenShader.js';
|
||||
|
||||
/**
|
||||
* Pass for creating a dot-screen effect.
|
||||
*
|
||||
* ```js
|
||||
* const pass = new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 );
|
||||
* composer.addPass( pass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { DotScreenPass } from 'three/addons/postprocessing/DotScreenPass.js';
|
||||
*/
|
||||
class DotScreenPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new dot screen pass.
|
||||
*
|
||||
* @param {Vector2} center - The center point.
|
||||
* @param {number} angle - The rotation of the effect in radians.
|
||||
* @param {number} scale - The scale of the effect. A higher value means smaller dots.
|
||||
*/
|
||||
constructor( center, angle, scale ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The pass uniforms. Use this object if you want to update the
|
||||
* `center`, `angle` or `scale` values at runtime.
|
||||
* ```js
|
||||
* pass.uniforms.center.value.copy( center );
|
||||
* pass.uniforms.angle.value = 0;
|
||||
* pass.uniforms.scale.value = 0.5;
|
||||
* ```
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = UniformsUtils.clone( DotScreenShader.uniforms );
|
||||
|
||||
if ( center !== undefined ) this.uniforms[ 'center' ].value.copy( center );
|
||||
if ( angle !== undefined ) this.uniforms[ 'angle' ].value = angle;
|
||||
if ( scale !== undefined ) this.uniforms[ 'scale' ].value = scale;
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.material = new ShaderMaterial( {
|
||||
|
||||
name: DotScreenShader.name,
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: DotScreenShader.vertexShader,
|
||||
fragmentShader: DotScreenShader.fragmentShader
|
||||
|
||||
} );
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the dot screen 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[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
this.uniforms[ 'tSize' ].value.set( readBuffer.width, readBuffer.height );
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.material.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { DotScreenPass };
|
||||
363
node_modules/three/examples/jsm/postprocessing/EffectComposer.js
generated
vendored
Normal file
363
node_modules/three/examples/jsm/postprocessing/EffectComposer.js
generated
vendored
Normal file
@@ -0,0 +1,363 @@
|
||||
import {
|
||||
Clock,
|
||||
HalfFloatType,
|
||||
NoBlending,
|
||||
Vector2,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
import { ShaderPass } from './ShaderPass.js';
|
||||
import { ClearMaskPass, MaskPass } from './MaskPass.js';
|
||||
|
||||
/**
|
||||
* Used to implement post-processing effects in three.js.
|
||||
* The class manages a chain of post-processing passes to produce the final visual result.
|
||||
* Post-processing passes are executed in order of their addition/insertion.
|
||||
* The last pass is automatically rendered to screen.
|
||||
*
|
||||
* This module can only be used with {@link WebGLRenderer}.
|
||||
*
|
||||
* ```js
|
||||
* const composer = new EffectComposer( renderer );
|
||||
*
|
||||
* // adding some passes
|
||||
* const renderPass = new RenderPass( scene, camera );
|
||||
* composer.addPass( renderPass );
|
||||
*
|
||||
* const glitchPass = new GlitchPass();
|
||||
* composer.addPass( glitchPass );
|
||||
*
|
||||
* const outputPass = new OutputPass()
|
||||
* composer.addPass( outputPass );
|
||||
*
|
||||
* function animate() {
|
||||
*
|
||||
* composer.render(); // instead of renderer.render()
|
||||
*
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @three_import import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
|
||||
*/
|
||||
class EffectComposer {
|
||||
|
||||
/**
|
||||
* Constructs a new effect composer.
|
||||
*
|
||||
* @param {WebGLRenderer} renderer - The renderer.
|
||||
* @param {WebGLRenderTarget} [renderTarget] - This render target and a clone will
|
||||
* be used as the internal read and write buffers. If not given, the composer creates
|
||||
* the buffers automatically.
|
||||
*/
|
||||
constructor( renderer, renderTarget ) {
|
||||
|
||||
/**
|
||||
* The renderer.
|
||||
*
|
||||
* @type {WebGLRenderer}
|
||||
*/
|
||||
this.renderer = renderer;
|
||||
|
||||
this._pixelRatio = renderer.getPixelRatio();
|
||||
|
||||
if ( renderTarget === undefined ) {
|
||||
|
||||
const size = renderer.getSize( new Vector2() );
|
||||
this._width = size.width;
|
||||
this._height = size.height;
|
||||
|
||||
renderTarget = new WebGLRenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType } );
|
||||
renderTarget.texture.name = 'EffectComposer.rt1';
|
||||
|
||||
} else {
|
||||
|
||||
this._width = renderTarget.width;
|
||||
this._height = renderTarget.height;
|
||||
|
||||
}
|
||||
|
||||
this.renderTarget1 = renderTarget;
|
||||
this.renderTarget2 = renderTarget.clone();
|
||||
this.renderTarget2.texture.name = 'EffectComposer.rt2';
|
||||
|
||||
/**
|
||||
* A reference to the internal write buffer. Passes usually write
|
||||
* their result into this buffer.
|
||||
*
|
||||
* @type {WebGLRenderTarget}
|
||||
*/
|
||||
this.writeBuffer = this.renderTarget1;
|
||||
|
||||
/**
|
||||
* A reference to the internal read buffer. Passes usually read
|
||||
* the previous render result from this buffer.
|
||||
*
|
||||
* @type {WebGLRenderTarget}
|
||||
*/
|
||||
this.readBuffer = this.renderTarget2;
|
||||
|
||||
/**
|
||||
* Whether the final pass is rendered to the screen (default framebuffer) or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.renderToScreen = true;
|
||||
|
||||
/**
|
||||
* An array representing the (ordered) chain of post-processing passes.
|
||||
*
|
||||
* @type {Array<Pass>}
|
||||
*/
|
||||
this.passes = [];
|
||||
|
||||
/**
|
||||
* A copy pass used for internal swap operations.
|
||||
*
|
||||
* @private
|
||||
* @type {ShaderPass}
|
||||
*/
|
||||
this.copyPass = new ShaderPass( CopyShader );
|
||||
this.copyPass.material.blending = NoBlending;
|
||||
|
||||
/**
|
||||
* The internal clock for managing time data.
|
||||
*
|
||||
* @private
|
||||
* @type {Clock}
|
||||
*/
|
||||
this.clock = new Clock();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the internal read/write buffers.
|
||||
*/
|
||||
swapBuffers() {
|
||||
|
||||
const tmp = this.readBuffer;
|
||||
this.readBuffer = this.writeBuffer;
|
||||
this.writeBuffer = tmp;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given pass to the pass chain.
|
||||
*
|
||||
* @param {Pass} pass - The pass to add.
|
||||
*/
|
||||
addPass( pass ) {
|
||||
|
||||
this.passes.push( pass );
|
||||
pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given pass at a given index.
|
||||
*
|
||||
* @param {Pass} pass - The pass to insert.
|
||||
* @param {number} index - The index into the pass chain.
|
||||
*/
|
||||
insertPass( pass, index ) {
|
||||
|
||||
this.passes.splice( index, 0, pass );
|
||||
pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given pass from the pass chain.
|
||||
*
|
||||
* @param {Pass} pass - The pass to remove.
|
||||
*/
|
||||
removePass( pass ) {
|
||||
|
||||
const index = this.passes.indexOf( pass );
|
||||
|
||||
if ( index !== - 1 ) {
|
||||
|
||||
this.passes.splice( index, 1 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the pass for the given index is the last enabled pass in the pass chain.
|
||||
*
|
||||
* @param {number} passIndex - The pass index.
|
||||
* @return {boolean} Whether the pass for the given index is the last pass in the pass chain.
|
||||
*/
|
||||
isLastEnabledPass( passIndex ) {
|
||||
|
||||
for ( let i = passIndex + 1; i < this.passes.length; i ++ ) {
|
||||
|
||||
if ( this.passes[ i ].enabled ) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all enabled post-processing passes in order to produce the final frame.
|
||||
*
|
||||
* @param {number} deltaTime - The delta time in seconds. If not given, the composer computes
|
||||
* its own time delta value.
|
||||
*/
|
||||
render( deltaTime ) {
|
||||
|
||||
// deltaTime value is in seconds
|
||||
|
||||
if ( deltaTime === undefined ) {
|
||||
|
||||
deltaTime = this.clock.getDelta();
|
||||
|
||||
}
|
||||
|
||||
const currentRenderTarget = this.renderer.getRenderTarget();
|
||||
|
||||
let maskActive = false;
|
||||
|
||||
for ( let i = 0, il = this.passes.length; i < il; i ++ ) {
|
||||
|
||||
const pass = this.passes[ i ];
|
||||
|
||||
if ( pass.enabled === false ) continue;
|
||||
|
||||
pass.renderToScreen = ( this.renderToScreen && this.isLastEnabledPass( i ) );
|
||||
pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive );
|
||||
|
||||
if ( pass.needsSwap ) {
|
||||
|
||||
if ( maskActive ) {
|
||||
|
||||
const context = this.renderer.getContext();
|
||||
const stencil = this.renderer.state.buffers.stencil;
|
||||
|
||||
//context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
|
||||
stencil.setFunc( context.NOTEQUAL, 1, 0xffffffff );
|
||||
|
||||
this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime );
|
||||
|
||||
//context.stencilFunc( context.EQUAL, 1, 0xffffffff );
|
||||
stencil.setFunc( context.EQUAL, 1, 0xffffffff );
|
||||
|
||||
}
|
||||
|
||||
this.swapBuffers();
|
||||
|
||||
}
|
||||
|
||||
if ( MaskPass !== undefined ) {
|
||||
|
||||
if ( pass instanceof MaskPass ) {
|
||||
|
||||
maskActive = true;
|
||||
|
||||
} else if ( pass instanceof ClearMaskPass ) {
|
||||
|
||||
maskActive = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.renderer.setRenderTarget( currentRenderTarget );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the internal state of the EffectComposer.
|
||||
*
|
||||
* @param {WebGLRenderTarget} [renderTarget] - This render target has the same purpose like
|
||||
* the one from the constructor. If set, it is used to setup the read and write buffers.
|
||||
*/
|
||||
reset( renderTarget ) {
|
||||
|
||||
if ( renderTarget === undefined ) {
|
||||
|
||||
const size = this.renderer.getSize( new Vector2() );
|
||||
this._pixelRatio = this.renderer.getPixelRatio();
|
||||
this._width = size.width;
|
||||
this._height = size.height;
|
||||
|
||||
renderTarget = this.renderTarget1.clone();
|
||||
renderTarget.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );
|
||||
|
||||
}
|
||||
|
||||
this.renderTarget1.dispose();
|
||||
this.renderTarget2.dispose();
|
||||
this.renderTarget1 = renderTarget;
|
||||
this.renderTarget2 = renderTarget.clone();
|
||||
|
||||
this.writeBuffer = this.renderTarget1;
|
||||
this.readBuffer = this.renderTarget2;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the internal read and write buffers as well as all passes. Similar to {@link WebGLRenderer#setSize},
|
||||
* this method honors the current pixel ration.
|
||||
*
|
||||
* @param {number} width - The width in logical pixels.
|
||||
* @param {number} height - The height in logical pixels.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
const effectiveWidth = this._width * this._pixelRatio;
|
||||
const effectiveHeight = this._height * this._pixelRatio;
|
||||
|
||||
this.renderTarget1.setSize( effectiveWidth, effectiveHeight );
|
||||
this.renderTarget2.setSize( effectiveWidth, effectiveHeight );
|
||||
|
||||
for ( let i = 0; i < this.passes.length; i ++ ) {
|
||||
|
||||
this.passes[ i ].setSize( effectiveWidth, effectiveHeight );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets device pixel ratio. This is usually used for HiDPI device to prevent blurring output.
|
||||
* Setting the pixel ratio will automatically resize the composer.
|
||||
*
|
||||
* @param {number} pixelRatio - The pixel ratio to set.
|
||||
*/
|
||||
setPixelRatio( pixelRatio ) {
|
||||
|
||||
this._pixelRatio = pixelRatio;
|
||||
|
||||
this.setSize( this._width, this._height );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the composer is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.renderTarget1.dispose();
|
||||
this.renderTarget2.dispose();
|
||||
|
||||
this.copyPass.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { EffectComposer };
|
||||
40
node_modules/three/examples/jsm/postprocessing/FXAAPass.js
generated
vendored
Normal file
40
node_modules/three/examples/jsm/postprocessing/FXAAPass.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { FXAAShader } from '../shaders/FXAAShader.js';
|
||||
import { ShaderPass } from './ShaderPass.js';
|
||||
|
||||
/**
|
||||
* A pass for applying FXAA.
|
||||
*
|
||||
* ```js
|
||||
* const fxaaPass = new FXAAPass();
|
||||
* composer.addPass( fxaaPass );
|
||||
* ```
|
||||
*
|
||||
* @augments ShaderPass
|
||||
* @three_import import { FXAAPass } from 'three/addons/postprocessing/FXAAPass.js';
|
||||
*/
|
||||
class FXAAPass extends ShaderPass {
|
||||
|
||||
/**
|
||||
* Constructs a new FXAA pass.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
super( FXAAShader );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.material.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { FXAAPass };
|
||||
113
node_modules/three/examples/jsm/postprocessing/FilmPass.js
generated
vendored
Normal file
113
node_modules/three/examples/jsm/postprocessing/FilmPass.js
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
import {
|
||||
ShaderMaterial,
|
||||
UniformsUtils
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { FilmShader } from '../shaders/FilmShader.js';
|
||||
|
||||
/**
|
||||
* This pass can be used to create a film grain effect.
|
||||
*
|
||||
* ```js
|
||||
* const filmPass = new FilmPass();
|
||||
* composer.addPass( filmPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { FilmPass } from 'three/addons/postprocessing/FilmPass.js';
|
||||
*/
|
||||
class FilmPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new film pass.
|
||||
*
|
||||
* @param {number} [intensity=0.5] - The grain intensity in the range `[0,1]` (0 = no effect, 1 = full effect).
|
||||
* @param {boolean} [grayscale=false] - Whether to apply a grayscale effect or not.
|
||||
*/
|
||||
constructor( intensity = 0.5, grayscale = false ) {
|
||||
|
||||
super();
|
||||
|
||||
const shader = FilmShader;
|
||||
|
||||
/**
|
||||
* The pass uniforms. Use this object if you want to update the
|
||||
* `intensity` or `grayscale` values at runtime.
|
||||
* ```js
|
||||
* pass.uniforms.intensity.value = 1;
|
||||
* pass.uniforms.grayscale.value = true;
|
||||
* ```
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = UniformsUtils.clone( shader.uniforms );
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.material = new ShaderMaterial( {
|
||||
|
||||
name: shader.name,
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader
|
||||
|
||||
} );
|
||||
|
||||
this.uniforms.intensity.value = intensity;
|
||||
this.uniforms.grayscale.value = grayscale;
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the film 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[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
this.uniforms[ 'time' ].value += deltaTime;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.material.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { FilmPass };
|
||||
727
node_modules/three/examples/jsm/postprocessing/GTAOPass.js
generated
vendored
Normal file
727
node_modules/three/examples/jsm/postprocessing/GTAOPass.js
generated
vendored
Normal file
@@ -0,0 +1,727 @@
|
||||
import {
|
||||
AddEquation,
|
||||
Color,
|
||||
CustomBlending,
|
||||
DataTexture,
|
||||
DepthTexture,
|
||||
DepthStencilFormat,
|
||||
DstAlphaFactor,
|
||||
DstColorFactor,
|
||||
HalfFloatType,
|
||||
MeshNormalMaterial,
|
||||
NearestFilter,
|
||||
NoBlending,
|
||||
RepeatWrapping,
|
||||
RGBAFormat,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
UnsignedByteType,
|
||||
UnsignedInt248Type,
|
||||
WebGLRenderTarget,
|
||||
ZeroFactor
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { generateMagicSquareNoise, GTAOShader, GTAODepthShader, GTAOBlendShader } from '../shaders/GTAOShader.js';
|
||||
import { generatePdSamplePointInitializer, PoissonDenoiseShader } from '../shaders/PoissonDenoiseShader.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
import { SimplexNoise } from '../math/SimplexNoise.js';
|
||||
|
||||
/**
|
||||
* A pass for an GTAO effect.
|
||||
*
|
||||
* `GTAOPass` provides better quality than {@link SSAOPass} but is also more expensive.
|
||||
*
|
||||
* ```js
|
||||
* const gtaoPass = new GTAOPass( scene, camera, width, height );
|
||||
* gtaoPass.output = GTAOPass.OUTPUT.Denoise;
|
||||
* composer.addPass( gtaoPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { GTAOPass } from 'three/addons/postprocessing/GTAOPass.js';
|
||||
*/
|
||||
class GTAOPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new GTAO pass.
|
||||
*
|
||||
* @param {Scene} scene - The scene to compute the AO for.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {number} [width=512] - The width of the effect.
|
||||
* @param {number} [height=512] - The height of the effect.
|
||||
* @param {Object} [parameters] - The pass parameters.
|
||||
* @param {Object} [aoParameters] - The AO parameters.
|
||||
* @param {Object} [pdParameters] - The denoise parameters.
|
||||
*/
|
||||
constructor( scene, camera, width = 512, height = 512, parameters, aoParameters, pdParameters ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The width of the effect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 512
|
||||
*/
|
||||
this.width = width;
|
||||
|
||||
/**
|
||||
* The height of the effect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 512
|
||||
*/
|
||||
this.height = height;
|
||||
|
||||
/**
|
||||
* Overwritten to perform a clear operation by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.clear = true;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* The scene to render the AO for.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The output configuration.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.output = 0;
|
||||
this._renderGBuffer = true;
|
||||
this._visibilityCache = [];
|
||||
|
||||
/**
|
||||
* The AO blend intensity.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.blendIntensity = 1.;
|
||||
|
||||
/**
|
||||
* The number of Poisson Denoise rings.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 2
|
||||
*/
|
||||
this.pdRings = 2.;
|
||||
|
||||
/**
|
||||
* The Poisson Denoise radius exponent.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 2
|
||||
*/
|
||||
this.pdRadiusExponent = 2.;
|
||||
|
||||
/**
|
||||
* The Poisson Denoise sample count.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 16
|
||||
*/
|
||||
this.pdSamples = 16;
|
||||
|
||||
this.gtaoNoiseTexture = generateMagicSquareNoise();
|
||||
this.pdNoiseTexture = this._generateNoise();
|
||||
|
||||
this.gtaoRenderTarget = new WebGLRenderTarget( this.width, this.height, { type: HalfFloatType } );
|
||||
this.pdRenderTarget = this.gtaoRenderTarget.clone();
|
||||
|
||||
this.gtaoMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, GTAOShader.defines ),
|
||||
uniforms: UniformsUtils.clone( GTAOShader.uniforms ),
|
||||
vertexShader: GTAOShader.vertexShader,
|
||||
fragmentShader: GTAOShader.fragmentShader,
|
||||
blending: NoBlending,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
} );
|
||||
this.gtaoMaterial.defines.PERSPECTIVE_CAMERA = this.camera.isPerspectiveCamera ? 1 : 0;
|
||||
this.gtaoMaterial.uniforms.tNoise.value = this.gtaoNoiseTexture;
|
||||
this.gtaoMaterial.uniforms.resolution.value.set( this.width, this.height );
|
||||
this.gtaoMaterial.uniforms.cameraNear.value = this.camera.near;
|
||||
this.gtaoMaterial.uniforms.cameraFar.value = this.camera.far;
|
||||
|
||||
this.normalMaterial = new MeshNormalMaterial();
|
||||
this.normalMaterial.blending = NoBlending;
|
||||
|
||||
this.pdMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, PoissonDenoiseShader.defines ),
|
||||
uniforms: UniformsUtils.clone( PoissonDenoiseShader.uniforms ),
|
||||
vertexShader: PoissonDenoiseShader.vertexShader,
|
||||
fragmentShader: PoissonDenoiseShader.fragmentShader,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
} );
|
||||
this.pdMaterial.uniforms.tDiffuse.value = this.gtaoRenderTarget.texture;
|
||||
this.pdMaterial.uniforms.tNoise.value = this.pdNoiseTexture;
|
||||
this.pdMaterial.uniforms.resolution.value.set( this.width, this.height );
|
||||
this.pdMaterial.uniforms.lumaPhi.value = 10;
|
||||
this.pdMaterial.uniforms.depthPhi.value = 2;
|
||||
this.pdMaterial.uniforms.normalPhi.value = 3;
|
||||
this.pdMaterial.uniforms.radius.value = 8;
|
||||
|
||||
this.depthRenderMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, GTAODepthShader.defines ),
|
||||
uniforms: UniformsUtils.clone( GTAODepthShader.uniforms ),
|
||||
vertexShader: GTAODepthShader.vertexShader,
|
||||
fragmentShader: GTAODepthShader.fragmentShader,
|
||||
blending: NoBlending
|
||||
} );
|
||||
this.depthRenderMaterial.uniforms.cameraNear.value = this.camera.near;
|
||||
this.depthRenderMaterial.uniforms.cameraFar.value = this.camera.far;
|
||||
|
||||
this.copyMaterial = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
transparent: true,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
blendSrc: DstColorFactor,
|
||||
blendDst: ZeroFactor,
|
||||
blendEquation: AddEquation,
|
||||
blendSrcAlpha: DstAlphaFactor,
|
||||
blendDstAlpha: ZeroFactor,
|
||||
blendEquationAlpha: AddEquation
|
||||
} );
|
||||
|
||||
this.blendMaterial = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( GTAOBlendShader.uniforms ),
|
||||
vertexShader: GTAOBlendShader.vertexShader,
|
||||
fragmentShader: GTAOBlendShader.fragmentShader,
|
||||
transparent: true,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
blending: CustomBlending,
|
||||
blendSrc: DstColorFactor,
|
||||
blendDst: ZeroFactor,
|
||||
blendEquation: AddEquation,
|
||||
blendSrcAlpha: DstAlphaFactor,
|
||||
blendDstAlpha: ZeroFactor,
|
||||
blendEquationAlpha: AddEquation
|
||||
} );
|
||||
|
||||
this._fsQuad = new FullScreenQuad( null );
|
||||
|
||||
this._originalClearColor = new Color();
|
||||
|
||||
this.setGBuffer( parameters ? parameters.depthTexture : undefined, parameters ? parameters.normalTexture : undefined );
|
||||
|
||||
if ( aoParameters !== undefined ) {
|
||||
|
||||
this.updateGtaoMaterial( aoParameters );
|
||||
|
||||
}
|
||||
|
||||
if ( pdParameters !== undefined ) {
|
||||
|
||||
this.updatePdMaterial( pdParameters );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.gtaoRenderTarget.setSize( width, height );
|
||||
this.normalRenderTarget.setSize( width, height );
|
||||
this.pdRenderTarget.setSize( width, height );
|
||||
|
||||
this.gtaoMaterial.uniforms.resolution.value.set( width, height );
|
||||
this.gtaoMaterial.uniforms.cameraProjectionMatrix.value.copy( this.camera.projectionMatrix );
|
||||
this.gtaoMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
|
||||
|
||||
this.pdMaterial.uniforms.resolution.value.set( width, height );
|
||||
this.pdMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.gtaoNoiseTexture.dispose();
|
||||
this.pdNoiseTexture.dispose();
|
||||
this.normalRenderTarget.dispose();
|
||||
this.gtaoRenderTarget.dispose();
|
||||
this.pdRenderTarget.dispose();
|
||||
this.normalMaterial.dispose();
|
||||
this.pdMaterial.dispose();
|
||||
this.copyMaterial.dispose();
|
||||
this.depthRenderMaterial.dispose();
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A texture holding the computed AO.
|
||||
*
|
||||
* @type {Texture}
|
||||
* @readonly
|
||||
*/
|
||||
get gtaoMap() {
|
||||
|
||||
return this.pdRenderTarget.texture;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the GBuffer of this pass. If no arguments are passed,
|
||||
* the pass creates an internal render target for holding depth
|
||||
* and normal data.
|
||||
*
|
||||
* @param {DepthTexture} [depthTexture] - The depth texture.
|
||||
* @param {DepthTexture} [normalTexture] - The normal texture.
|
||||
*/
|
||||
setGBuffer( depthTexture, normalTexture ) {
|
||||
|
||||
if ( depthTexture !== undefined ) {
|
||||
|
||||
this.depthTexture = depthTexture;
|
||||
this.normalTexture = normalTexture;
|
||||
this._renderGBuffer = false;
|
||||
|
||||
} else {
|
||||
|
||||
this.depthTexture = new DepthTexture();
|
||||
this.depthTexture.format = DepthStencilFormat;
|
||||
this.depthTexture.type = UnsignedInt248Type;
|
||||
this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter,
|
||||
type: HalfFloatType,
|
||||
depthTexture: this.depthTexture
|
||||
} );
|
||||
this.normalTexture = this.normalRenderTarget.texture;
|
||||
this._renderGBuffer = true;
|
||||
|
||||
}
|
||||
|
||||
const normalVectorType = ( this.normalTexture ) ? 1 : 0;
|
||||
const depthValueSource = ( this.depthTexture === this.normalTexture ) ? 'w' : 'x';
|
||||
|
||||
this.gtaoMaterial.defines.NORMAL_VECTOR_TYPE = normalVectorType;
|
||||
this.gtaoMaterial.defines.DEPTH_SWIZZLING = depthValueSource;
|
||||
this.gtaoMaterial.uniforms.tNormal.value = this.normalTexture;
|
||||
this.gtaoMaterial.uniforms.tDepth.value = this.depthTexture;
|
||||
|
||||
this.pdMaterial.defines.NORMAL_VECTOR_TYPE = normalVectorType;
|
||||
this.pdMaterial.defines.DEPTH_SWIZZLING = depthValueSource;
|
||||
this.pdMaterial.uniforms.tNormal.value = this.normalTexture;
|
||||
this.pdMaterial.uniforms.tDepth.value = this.depthTexture;
|
||||
|
||||
this.depthRenderMaterial.uniforms.tDepth.value = this.normalRenderTarget.depthTexture;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the clip box of the GTAO shader with the given AABB.
|
||||
*
|
||||
* @param {?Box3} box - The AABB enclosing the scene that should receive AO. When passing
|
||||
* `null`, to clip box is used.
|
||||
*/
|
||||
setSceneClipBox( box ) {
|
||||
|
||||
if ( box ) {
|
||||
|
||||
this.gtaoMaterial.needsUpdate = this.gtaoMaterial.defines.SCENE_CLIP_BOX !== 1;
|
||||
this.gtaoMaterial.defines.SCENE_CLIP_BOX = 1;
|
||||
this.gtaoMaterial.uniforms.sceneBoxMin.value.copy( box.min );
|
||||
this.gtaoMaterial.uniforms.sceneBoxMax.value.copy( box.max );
|
||||
|
||||
} else {
|
||||
|
||||
this.gtaoMaterial.needsUpdate = this.gtaoMaterial.defines.SCENE_CLIP_BOX === 0;
|
||||
this.gtaoMaterial.defines.SCENE_CLIP_BOX = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the GTAO material from the given parameter object.
|
||||
*
|
||||
* @param {Object} parameters - The GTAO material parameters.
|
||||
*/
|
||||
updateGtaoMaterial( parameters ) {
|
||||
|
||||
if ( parameters.radius !== undefined ) {
|
||||
|
||||
this.gtaoMaterial.uniforms.radius.value = parameters.radius;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.distanceExponent !== undefined ) {
|
||||
|
||||
this.gtaoMaterial.uniforms.distanceExponent.value = parameters.distanceExponent;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.thickness !== undefined ) {
|
||||
|
||||
this.gtaoMaterial.uniforms.thickness.value = parameters.thickness;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.distanceFallOff !== undefined ) {
|
||||
|
||||
this.gtaoMaterial.uniforms.distanceFallOff.value = parameters.distanceFallOff;
|
||||
this.gtaoMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.scale !== undefined ) {
|
||||
|
||||
this.gtaoMaterial.uniforms.scale.value = parameters.scale;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.samples !== undefined && parameters.samples !== this.gtaoMaterial.defines.SAMPLES ) {
|
||||
|
||||
this.gtaoMaterial.defines.SAMPLES = parameters.samples;
|
||||
this.gtaoMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.screenSpaceRadius !== undefined && ( parameters.screenSpaceRadius ? 1 : 0 ) !== this.gtaoMaterial.defines.SCREEN_SPACE_RADIUS ) {
|
||||
|
||||
this.gtaoMaterial.defines.SCREEN_SPACE_RADIUS = parameters.screenSpaceRadius ? 1 : 0;
|
||||
this.gtaoMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Denoise material from the given parameter object.
|
||||
*
|
||||
* @param {Object} parameters - The denoise parameters.
|
||||
*/
|
||||
updatePdMaterial( parameters ) {
|
||||
|
||||
let updateShader = false;
|
||||
|
||||
if ( parameters.lumaPhi !== undefined ) {
|
||||
|
||||
this.pdMaterial.uniforms.lumaPhi.value = parameters.lumaPhi;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.depthPhi !== undefined ) {
|
||||
|
||||
this.pdMaterial.uniforms.depthPhi.value = parameters.depthPhi;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.normalPhi !== undefined ) {
|
||||
|
||||
this.pdMaterial.uniforms.normalPhi.value = parameters.normalPhi;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.radius !== undefined && parameters.radius !== this.radius ) {
|
||||
|
||||
this.pdMaterial.uniforms.radius.value = parameters.radius;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.radiusExponent !== undefined && parameters.radiusExponent !== this.pdRadiusExponent ) {
|
||||
|
||||
this.pdRadiusExponent = parameters.radiusExponent;
|
||||
updateShader = true;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.rings !== undefined && parameters.rings !== this.pdRings ) {
|
||||
|
||||
this.pdRings = parameters.rings;
|
||||
updateShader = true;
|
||||
|
||||
}
|
||||
|
||||
if ( parameters.samples !== undefined && parameters.samples !== this.pdSamples ) {
|
||||
|
||||
this.pdSamples = parameters.samples;
|
||||
updateShader = true;
|
||||
|
||||
}
|
||||
|
||||
if ( updateShader ) {
|
||||
|
||||
this.pdMaterial.defines.SAMPLES = this.pdSamples;
|
||||
this.pdMaterial.defines.SAMPLE_VECTORS = generatePdSamplePointInitializer( this.pdSamples, this.pdRings, this.pdRadiusExponent );
|
||||
this.pdMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the GTAO 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 */ ) {
|
||||
|
||||
// render normals and depth (honor only meshes, points and lines do not contribute to AO)
|
||||
|
||||
if ( this._renderGBuffer ) {
|
||||
|
||||
this._overrideVisibility();
|
||||
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
|
||||
this._restoreVisibility();
|
||||
|
||||
}
|
||||
|
||||
// render AO
|
||||
|
||||
this.gtaoMaterial.uniforms.cameraNear.value = this.camera.near;
|
||||
this.gtaoMaterial.uniforms.cameraFar.value = this.camera.far;
|
||||
this.gtaoMaterial.uniforms.cameraProjectionMatrix.value.copy( this.camera.projectionMatrix );
|
||||
this.gtaoMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
|
||||
this.gtaoMaterial.uniforms.cameraWorldMatrix.value.copy( this.camera.matrixWorld );
|
||||
this._renderPass( renderer, this.gtaoMaterial, this.gtaoRenderTarget, 0xffffff, 1.0 );
|
||||
|
||||
// render poisson denoise
|
||||
|
||||
this.pdMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
|
||||
this._renderPass( renderer, this.pdMaterial, this.pdRenderTarget, 0xffffff, 1.0 );
|
||||
|
||||
// output result to screen
|
||||
|
||||
switch ( this.output ) {
|
||||
|
||||
case GTAOPass.OUTPUT.Off:
|
||||
break;
|
||||
|
||||
case GTAOPass.OUTPUT.Diffuse:
|
||||
|
||||
this.copyMaterial.uniforms.tDiffuse.value = readBuffer.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case GTAOPass.OUTPUT.AO:
|
||||
|
||||
this.copyMaterial.uniforms.tDiffuse.value = this.gtaoRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case GTAOPass.OUTPUT.Denoise:
|
||||
|
||||
this.copyMaterial.uniforms.tDiffuse.value = this.pdRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case GTAOPass.OUTPUT.Depth:
|
||||
|
||||
this.depthRenderMaterial.uniforms.cameraNear.value = this.camera.near;
|
||||
this.depthRenderMaterial.uniforms.cameraFar.value = this.camera.far;
|
||||
this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case GTAOPass.OUTPUT.Normal:
|
||||
|
||||
this.copyMaterial.uniforms.tDiffuse.value = this.normalRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case GTAOPass.OUTPUT.Default:
|
||||
|
||||
this.copyMaterial.uniforms.tDiffuse.value = readBuffer.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
this.blendMaterial.uniforms.intensity.value = this.blendIntensity;
|
||||
this.blendMaterial.uniforms.tDiffuse.value = this.pdRenderTarget.texture;
|
||||
this._renderPass( renderer, this.blendMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn( 'THREE.GTAOPass: Unknown output type.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
// save original state
|
||||
renderer.getClearColor( this._originalClearColor );
|
||||
const originalClearAlpha = renderer.getClearAlpha();
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
|
||||
// setup pass state
|
||||
renderer.autoClear = false;
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this._fsQuad.material = passMaterial;
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this._originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
renderer.getClearColor( this._originalClearColor );
|
||||
const originalClearAlpha = renderer.getClearAlpha();
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.autoClear = false;
|
||||
|
||||
clearColor = overrideMaterial.clearColor || clearColor;
|
||||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
|
||||
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this.scene.overrideMaterial = overrideMaterial;
|
||||
renderer.render( this.scene, this.camera );
|
||||
this.scene.overrideMaterial = null;
|
||||
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this._originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
_overrideVisibility() {
|
||||
|
||||
const scene = this.scene;
|
||||
const cache = this._visibilityCache;
|
||||
|
||||
scene.traverse( function ( object ) {
|
||||
|
||||
if ( ( object.isPoints || object.isLine || object.isLine2 ) && object.visible ) {
|
||||
|
||||
object.visible = false;
|
||||
cache.push( object );
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_restoreVisibility() {
|
||||
|
||||
const cache = this._visibilityCache;
|
||||
|
||||
for ( let i = 0; i < cache.length; i ++ ) {
|
||||
|
||||
cache[ i ].visible = true;
|
||||
|
||||
}
|
||||
|
||||
cache.length = 0;
|
||||
|
||||
}
|
||||
|
||||
_generateNoise( size = 64 ) {
|
||||
|
||||
const simplex = new SimplexNoise();
|
||||
|
||||
const arraySize = size * size * 4;
|
||||
const data = new Uint8Array( arraySize );
|
||||
|
||||
for ( let i = 0; i < size; i ++ ) {
|
||||
|
||||
for ( let j = 0; j < size; j ++ ) {
|
||||
|
||||
const x = i;
|
||||
const y = j;
|
||||
|
||||
data[ ( i * size + j ) * 4 ] = ( simplex.noise( x, y ) * 0.5 + 0.5 ) * 255;
|
||||
data[ ( i * size + j ) * 4 + 1 ] = ( simplex.noise( x + size, y ) * 0.5 + 0.5 ) * 255;
|
||||
data[ ( i * size + j ) * 4 + 2 ] = ( simplex.noise( x, y + size ) * 0.5 + 0.5 ) * 255;
|
||||
data[ ( i * size + j ) * 4 + 3 ] = ( simplex.noise( x + size, y + size ) * 0.5 + 0.5 ) * 255;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const noiseTexture = new DataTexture( data, size, size, RGBAFormat, UnsignedByteType );
|
||||
noiseTexture.wrapS = RepeatWrapping;
|
||||
noiseTexture.wrapT = RepeatWrapping;
|
||||
noiseTexture.needsUpdate = true;
|
||||
|
||||
return noiseTexture;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GTAOPass.OUTPUT = {
|
||||
'Off': - 1,
|
||||
'Default': 0,
|
||||
'Diffuse': 1,
|
||||
'Depth': 2,
|
||||
'Normal': 3,
|
||||
'AO': 4,
|
||||
'Denoise': 5,
|
||||
};
|
||||
|
||||
export { GTAOPass };
|
||||
177
node_modules/three/examples/jsm/postprocessing/GlitchPass.js
generated
vendored
Normal file
177
node_modules/three/examples/jsm/postprocessing/GlitchPass.js
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
import {
|
||||
DataTexture,
|
||||
FloatType,
|
||||
MathUtils,
|
||||
RedFormat,
|
||||
ShaderMaterial,
|
||||
UniformsUtils
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { DigitalGlitch } from '../shaders/DigitalGlitch.js';
|
||||
|
||||
/**
|
||||
* Pass for creating a glitch effect.
|
||||
*
|
||||
* ```js
|
||||
* const glitchPass = new GlitchPass();
|
||||
* composer.addPass( glitchPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { GlitchPass } from 'three/addons/postprocessing/GlitchPass.js';
|
||||
*/
|
||||
class GlitchPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new glitch pass.
|
||||
*
|
||||
* @param {number} [dt_size=64] - The size of the displacement texture
|
||||
* for digital glitch squares.
|
||||
*/
|
||||
constructor( dt_size = 64 ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The pass uniforms.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = UniformsUtils.clone( DigitalGlitch.uniforms );
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.material = new ShaderMaterial( {
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: DigitalGlitch.vertexShader,
|
||||
fragmentShader: DigitalGlitch.fragmentShader
|
||||
} );
|
||||
|
||||
/**
|
||||
* Whether to noticeably increase the effect intensity or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.goWild = false;
|
||||
|
||||
// internals
|
||||
|
||||
this._heightMap = this._generateHeightmap( dt_size );
|
||||
this.uniforms[ 'tDisp' ].value = this._heightMap;
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
this._curF = 0;
|
||||
this._randX = 0;
|
||||
|
||||
this._generateTrigger();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the glitch 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[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
this.uniforms[ 'seed' ].value = Math.random(); // default seeding
|
||||
this.uniforms[ 'byp' ].value = 0;
|
||||
|
||||
if ( this._curF % this._randX == 0 || this.goWild == true ) {
|
||||
|
||||
this.uniforms[ 'amount' ].value = Math.random() / 30;
|
||||
this.uniforms[ 'angle' ].value = MathUtils.randFloat( - Math.PI, Math.PI );
|
||||
this.uniforms[ 'seed_x' ].value = MathUtils.randFloat( - 1, 1 );
|
||||
this.uniforms[ 'seed_y' ].value = MathUtils.randFloat( - 1, 1 );
|
||||
this.uniforms[ 'distortion_x' ].value = MathUtils.randFloat( 0, 1 );
|
||||
this.uniforms[ 'distortion_y' ].value = MathUtils.randFloat( 0, 1 );
|
||||
this._curF = 0;
|
||||
this._generateTrigger();
|
||||
|
||||
} else if ( this._curF % this._randX < this._randX / 5 ) {
|
||||
|
||||
this.uniforms[ 'amount' ].value = Math.random() / 90;
|
||||
this.uniforms[ 'angle' ].value = MathUtils.randFloat( - Math.PI, Math.PI );
|
||||
this.uniforms[ 'distortion_x' ].value = MathUtils.randFloat( 0, 1 );
|
||||
this.uniforms[ 'distortion_y' ].value = MathUtils.randFloat( 0, 1 );
|
||||
this.uniforms[ 'seed_x' ].value = MathUtils.randFloat( - 0.3, 0.3 );
|
||||
this.uniforms[ 'seed_y' ].value = MathUtils.randFloat( - 0.3, 0.3 );
|
||||
|
||||
} else if ( this.goWild == false ) {
|
||||
|
||||
this.uniforms[ 'byp' ].value = 1;
|
||||
|
||||
}
|
||||
|
||||
this._curF ++;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.material.dispose();
|
||||
|
||||
this._heightMap.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_generateTrigger() {
|
||||
|
||||
this._randX = MathUtils.randInt( 120, 240 );
|
||||
|
||||
}
|
||||
|
||||
_generateHeightmap( dt_size ) {
|
||||
|
||||
const data_arr = new Float32Array( dt_size * dt_size );
|
||||
const length = dt_size * dt_size;
|
||||
|
||||
for ( let i = 0; i < length; i ++ ) {
|
||||
|
||||
const val = MathUtils.randFloat( 0, 1 );
|
||||
data_arr[ i ] = val;
|
||||
|
||||
}
|
||||
|
||||
const texture = new DataTexture( data_arr, dt_size, dt_size, RedFormat, FloatType );
|
||||
texture.needsUpdate = true;
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { GlitchPass };
|
||||
134
node_modules/three/examples/jsm/postprocessing/HalftonePass.js
generated
vendored
Normal file
134
node_modules/three/examples/jsm/postprocessing/HalftonePass.js
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
import {
|
||||
ShaderMaterial,
|
||||
UniformsUtils
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { HalftoneShader } from '../shaders/HalftoneShader.js';
|
||||
|
||||
/**
|
||||
* Pass for creating a RGB halftone effect.
|
||||
*
|
||||
* ```js
|
||||
* const params = {
|
||||
* shape: 1,
|
||||
* radius: 4,
|
||||
* rotateR: Math.PI / 12,
|
||||
* rotateB: Math.PI / 12 * 2,
|
||||
* rotateG: Math.PI / 12 * 3,
|
||||
* scatter: 0,
|
||||
* blending: 1,
|
||||
* blendingMode: 1,
|
||||
* greyscale: false,
|
||||
* disable: false
|
||||
* };
|
||||
* const halftonePass = new HalftonePass( params );
|
||||
* composer.addPass( halftonePass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { HalftonePass } from 'three/addons/postprocessing/HalftonePass.js';
|
||||
*/
|
||||
class HalftonePass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new halftone pass.
|
||||
*
|
||||
* @param {Object} params - The halftone shader parameter.
|
||||
*/
|
||||
constructor( params ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The pass uniforms.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = UniformsUtils.clone( HalftoneShader.uniforms );
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.material = new ShaderMaterial( {
|
||||
uniforms: this.uniforms,
|
||||
fragmentShader: HalftoneShader.fragmentShader,
|
||||
vertexShader: HalftoneShader.vertexShader
|
||||
} );
|
||||
|
||||
|
||||
for ( const key in params ) {
|
||||
|
||||
if ( params.hasOwnProperty( key ) && this.uniforms.hasOwnProperty( key ) ) {
|
||||
|
||||
this.uniforms[ key ].value = params[ key ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the halftone 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.material.uniforms[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.uniforms.width.value = width;
|
||||
this.uniforms.height.value = 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.material.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { HalftonePass };
|
||||
138
node_modules/three/examples/jsm/postprocessing/LUTPass.js
generated
vendored
Normal file
138
node_modules/three/examples/jsm/postprocessing/LUTPass.js
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
import { ShaderPass } from './ShaderPass.js';
|
||||
|
||||
const LUTShader = {
|
||||
|
||||
name: 'LUTShader',
|
||||
|
||||
uniforms: {
|
||||
|
||||
lut: { value: null },
|
||||
lutSize: { value: 0 },
|
||||
|
||||
tDiffuse: { value: null },
|
||||
intensity: { value: 1.0 },
|
||||
},
|
||||
|
||||
vertexShader: /* glsl */`
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}
|
||||
|
||||
`,
|
||||
|
||||
fragmentShader: /* glsl */`
|
||||
|
||||
uniform float lutSize;
|
||||
uniform sampler3D lut;
|
||||
|
||||
varying vec2 vUv;
|
||||
uniform float intensity;
|
||||
uniform sampler2D tDiffuse;
|
||||
void main() {
|
||||
|
||||
vec4 val = texture2D( tDiffuse, vUv );
|
||||
vec4 lutVal;
|
||||
|
||||
// pull the sample in by half a pixel so the sample begins
|
||||
// at the center of the edge pixels.
|
||||
float pixelWidth = 1.0 / lutSize;
|
||||
float halfPixelWidth = 0.5 / lutSize;
|
||||
vec3 uvw = vec3( halfPixelWidth ) + val.rgb * ( 1.0 - pixelWidth );
|
||||
|
||||
|
||||
lutVal = vec4( texture( lut, uvw ).rgb, val.a );
|
||||
|
||||
gl_FragColor = vec4( mix( val, lutVal, intensity ) );
|
||||
|
||||
}
|
||||
|
||||
`,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Pass for color grading via lookup tables.
|
||||
*
|
||||
* ```js
|
||||
* const lutPass = new LUTPass( { lut: lut.texture3D } );
|
||||
* composer.addPass( lutPass );
|
||||
* ```
|
||||
*
|
||||
* @augments ShaderPass
|
||||
* @three_import import { LUTPass } from 'three/addons/postprocessing/LUTPass.js';
|
||||
*/
|
||||
class LUTPass extends ShaderPass {
|
||||
|
||||
/**
|
||||
* Constructs a LUT pass.
|
||||
*
|
||||
* @param {{lut:Data3DTexture,intensity:number}} [options={}] - The pass options.
|
||||
*/
|
||||
constructor( options = {} ) {
|
||||
|
||||
super( LUTShader );
|
||||
|
||||
/**
|
||||
* The LUT as a 3D texture.
|
||||
*
|
||||
* @type {?Data3DTexture}
|
||||
* @default null
|
||||
*/
|
||||
this.lut = options.lut || null;
|
||||
|
||||
/**
|
||||
* The intensity.
|
||||
*
|
||||
* @type {?number}
|
||||
* @default 1
|
||||
*/
|
||||
this.intensity = 'intensity' in options ? options.intensity : 1;
|
||||
|
||||
}
|
||||
|
||||
set lut( v ) {
|
||||
|
||||
const material = this.material;
|
||||
|
||||
if ( v !== this.lut ) {
|
||||
|
||||
material.uniforms.lut.value = null;
|
||||
|
||||
if ( v ) {
|
||||
|
||||
material.uniforms.lutSize.value = v.image.width;
|
||||
material.uniforms.lut.value = v;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
get lut() {
|
||||
|
||||
return this.material.uniforms.lut.value;
|
||||
|
||||
}
|
||||
|
||||
set intensity( v ) {
|
||||
|
||||
this.material.uniforms.intensity.value = v;
|
||||
|
||||
}
|
||||
|
||||
get intensity() {
|
||||
|
||||
return this.material.uniforms.intensity.value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { LUTPass };
|
||||
195
node_modules/three/examples/jsm/postprocessing/MaskPass.js
generated
vendored
Normal file
195
node_modules/three/examples/jsm/postprocessing/MaskPass.js
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
import { Pass } from './Pass.js';
|
||||
|
||||
/**
|
||||
* This pass can be used to define a mask during post processing.
|
||||
* Meaning only areas of subsequent post processing are affected
|
||||
* which lie in the masking area of this pass. Internally, the masking
|
||||
* is implemented with the stencil buffer.
|
||||
*
|
||||
* ```js
|
||||
* const maskPass = new MaskPass( scene, camera );
|
||||
* composer.addPass( maskPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { MaskPass } from 'three/addons/postprocessing/MaskPass.js';
|
||||
*/
|
||||
class MaskPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new mask pass.
|
||||
*
|
||||
* @param {Scene} scene - The 3D objects in this scene will define the mask.
|
||||
* @param {Camera} camera - The camera.
|
||||
*/
|
||||
constructor( scene, camera ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scene that defines the mask.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* Overwritten to perform a clear operation by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.clear = true;
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
/**
|
||||
* Whether to inverse the mask or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.inverse = false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a mask pass with the configured scene and camera.
|
||||
*
|
||||
* @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 */ ) {
|
||||
|
||||
const context = renderer.getContext();
|
||||
const state = renderer.state;
|
||||
|
||||
// don't update color or depth
|
||||
|
||||
state.buffers.color.setMask( false );
|
||||
state.buffers.depth.setMask( false );
|
||||
|
||||
// lock buffers
|
||||
|
||||
state.buffers.color.setLocked( true );
|
||||
state.buffers.depth.setLocked( true );
|
||||
|
||||
// set up stencil
|
||||
|
||||
let writeValue, clearValue;
|
||||
|
||||
if ( this.inverse ) {
|
||||
|
||||
writeValue = 0;
|
||||
clearValue = 1;
|
||||
|
||||
} else {
|
||||
|
||||
writeValue = 1;
|
||||
clearValue = 0;
|
||||
|
||||
}
|
||||
|
||||
state.buffers.stencil.setTest( true );
|
||||
state.buffers.stencil.setOp( context.REPLACE, context.REPLACE, context.REPLACE );
|
||||
state.buffers.stencil.setFunc( context.ALWAYS, writeValue, 0xffffffff );
|
||||
state.buffers.stencil.setClear( clearValue );
|
||||
state.buffers.stencil.setLocked( true );
|
||||
|
||||
// draw into the stencil buffer
|
||||
|
||||
renderer.setRenderTarget( readBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
renderer.render( this.scene, this.camera );
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
renderer.render( this.scene, this.camera );
|
||||
|
||||
// unlock color and depth buffer and make them writable for subsequent rendering/clearing
|
||||
|
||||
state.buffers.color.setLocked( false );
|
||||
state.buffers.depth.setLocked( false );
|
||||
|
||||
state.buffers.color.setMask( true );
|
||||
state.buffers.depth.setMask( true );
|
||||
|
||||
// only render where stencil is set to 1
|
||||
|
||||
state.buffers.stencil.setLocked( false );
|
||||
state.buffers.stencil.setFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1
|
||||
state.buffers.stencil.setOp( context.KEEP, context.KEEP, context.KEEP );
|
||||
state.buffers.stencil.setLocked( true );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This pass can be used to clear a mask previously defined with {@link MaskPass}.
|
||||
*
|
||||
* ```js
|
||||
* const clearPass = new ClearMaskPass();
|
||||
* composer.addPass( clearPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
*/
|
||||
class ClearMaskPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new clear mask pass.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the clear of the currently defined mask.
|
||||
*
|
||||
* @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 */ ) {
|
||||
|
||||
renderer.state.buffers.stencil.setLocked( false );
|
||||
renderer.state.buffers.stencil.setTest( false );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { MaskPass, ClearMaskPass };
|
||||
776
node_modules/three/examples/jsm/postprocessing/OutlinePass.js
generated
vendored
Normal file
776
node_modules/three/examples/jsm/postprocessing/OutlinePass.js
generated
vendored
Normal file
@@ -0,0 +1,776 @@
|
||||
import {
|
||||
AdditiveBlending,
|
||||
Color,
|
||||
DoubleSide,
|
||||
HalfFloatType,
|
||||
Matrix4,
|
||||
MeshDepthMaterial,
|
||||
NoBlending,
|
||||
RGBADepthPacking,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
Vector2,
|
||||
Vector3,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
|
||||
/**
|
||||
* A pass for rendering outlines around selected objects.
|
||||
*
|
||||
* ```js
|
||||
* const resolution = new THREE.Vector2( window.innerWidth, window.innerHeight );
|
||||
* const outlinePass = new OutlinePass( resolution, scene, camera );
|
||||
* composer.addPass( outlinePass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { OutlinePass } from 'three/addons/postprocessing/OutlinePass.js';
|
||||
*/
|
||||
class OutlinePass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new outline pass.
|
||||
*
|
||||
* @param {Vector2} [resolution] - The effect's resolution.
|
||||
* @param {Scene} scene - The scene to render.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {Array<Object3D>} [selectedObjects] - The selected 3D objects that should receive an outline.
|
||||
*
|
||||
*/
|
||||
constructor( resolution, scene, camera, selectedObjects ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scene to render.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.renderScene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.renderCamera = camera;
|
||||
|
||||
/**
|
||||
* The selected 3D objects that should receive an outline.
|
||||
*
|
||||
* @type {Array<Object3D>}
|
||||
*/
|
||||
this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
|
||||
|
||||
/**
|
||||
* The visible edge color.
|
||||
*
|
||||
* @type {Color}
|
||||
* @default (1,1,1)
|
||||
*/
|
||||
this.visibleEdgeColor = new Color( 1, 1, 1 );
|
||||
|
||||
/**
|
||||
* The hidden edge color.
|
||||
*
|
||||
* @type {Color}
|
||||
* @default (0.1,0.04,0.02)
|
||||
*/
|
||||
this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 );
|
||||
|
||||
/**
|
||||
* Can be used for an animated glow/pulse effect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.edgeGlow = 0.0;
|
||||
|
||||
/**
|
||||
* Whether to use a pattern texture for to highlight selected
|
||||
* 3D objects or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.usePatternTexture = false;
|
||||
|
||||
/**
|
||||
* Can be used to highlight selected 3D objects. Requires to set
|
||||
* {@link OutlinePass#usePatternTexture} to `true`.
|
||||
*
|
||||
* @type {?Texture}
|
||||
* @default null
|
||||
*/
|
||||
this.patternTexture = null;
|
||||
|
||||
/**
|
||||
* The edge thickness.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.edgeThickness = 1.0;
|
||||
|
||||
/**
|
||||
* The edge strength.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 3
|
||||
*/
|
||||
this.edgeStrength = 3.0;
|
||||
|
||||
/**
|
||||
* The downsample ratio. The effect can be rendered in a much
|
||||
* lower resolution than the beauty pass.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 2
|
||||
*/
|
||||
this.downSampleRatio = 2;
|
||||
|
||||
/**
|
||||
* The pulse period.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.pulsePeriod = 0;
|
||||
|
||||
this._visibilityCache = new Map();
|
||||
this._selectionCache = new Set();
|
||||
|
||||
/**
|
||||
* The effect's resolution.
|
||||
*
|
||||
* @type {Vector2}
|
||||
* @default (256,256)
|
||||
*/
|
||||
this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 );
|
||||
|
||||
const resx = Math.round( this.resolution.x / this.downSampleRatio );
|
||||
const resy = Math.round( this.resolution.y / this.downSampleRatio );
|
||||
|
||||
this.renderTargetMaskBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y );
|
||||
this.renderTargetMaskBuffer.texture.name = 'OutlinePass.mask';
|
||||
this.renderTargetMaskBuffer.texture.generateMipmaps = false;
|
||||
|
||||
this.depthMaterial = new MeshDepthMaterial();
|
||||
this.depthMaterial.side = DoubleSide;
|
||||
this.depthMaterial.depthPacking = RGBADepthPacking;
|
||||
this.depthMaterial.blending = NoBlending;
|
||||
|
||||
this.prepareMaskMaterial = this._getPrepareMaskMaterial();
|
||||
this.prepareMaskMaterial.side = DoubleSide;
|
||||
this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
|
||||
|
||||
this.renderTargetDepthBuffer = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { type: HalfFloatType } );
|
||||
this.renderTargetDepthBuffer.texture.name = 'OutlinePass.depth';
|
||||
this.renderTargetDepthBuffer.texture.generateMipmaps = false;
|
||||
|
||||
this.renderTargetMaskDownSampleBuffer = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
|
||||
this.renderTargetMaskDownSampleBuffer.texture.name = 'OutlinePass.depthDownSample';
|
||||
this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false;
|
||||
|
||||
this.renderTargetBlurBuffer1 = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
|
||||
this.renderTargetBlurBuffer1.texture.name = 'OutlinePass.blur1';
|
||||
this.renderTargetBlurBuffer1.texture.generateMipmaps = false;
|
||||
this.renderTargetBlurBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), { type: HalfFloatType } );
|
||||
this.renderTargetBlurBuffer2.texture.name = 'OutlinePass.blur2';
|
||||
this.renderTargetBlurBuffer2.texture.generateMipmaps = false;
|
||||
|
||||
this.edgeDetectionMaterial = this._getEdgeDetectionMaterial();
|
||||
this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
|
||||
this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1';
|
||||
this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
|
||||
this.renderTargetEdgeBuffer2 = new WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), { type: HalfFloatType } );
|
||||
this.renderTargetEdgeBuffer2.texture.name = 'OutlinePass.edge2';
|
||||
this.renderTargetEdgeBuffer2.texture.generateMipmaps = false;
|
||||
|
||||
const MAX_EDGE_THICKNESS = 4;
|
||||
const MAX_EDGE_GLOW = 4;
|
||||
|
||||
this.separableBlurMaterial1 = this._getSeparableBlurMaterial( MAX_EDGE_THICKNESS );
|
||||
this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy );
|
||||
this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1;
|
||||
this.separableBlurMaterial2 = this._getSeparableBlurMaterial( MAX_EDGE_GLOW );
|
||||
this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) );
|
||||
this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW;
|
||||
|
||||
// Overlay material
|
||||
this.overlayMaterial = this._getOverlayMaterial();
|
||||
|
||||
// copy material
|
||||
|
||||
const copyShader = CopyShader;
|
||||
|
||||
this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );
|
||||
|
||||
this.materialCopy = new ShaderMaterial( {
|
||||
uniforms: this.copyUniforms,
|
||||
vertexShader: copyShader.vertexShader,
|
||||
fragmentShader: copyShader.fragmentShader,
|
||||
blending: NoBlending,
|
||||
depthTest: false,
|
||||
depthWrite: false
|
||||
} );
|
||||
|
||||
this.enabled = true;
|
||||
this.needsSwap = false;
|
||||
|
||||
this._oldClearColor = new Color();
|
||||
this.oldClearAlpha = 1;
|
||||
|
||||
this._fsQuad = new FullScreenQuad( null );
|
||||
|
||||
this.tempPulseColor1 = new Color();
|
||||
this.tempPulseColor2 = new Color();
|
||||
this.textureMatrix = new Matrix4();
|
||||
|
||||
function replaceDepthToViewZ( string, camera ) {
|
||||
|
||||
const type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic';
|
||||
|
||||
return string.replace( /DEPTH_TO_VIEW_Z/g, type + 'DepthToViewZ' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.renderTargetMaskBuffer.dispose();
|
||||
this.renderTargetDepthBuffer.dispose();
|
||||
this.renderTargetMaskDownSampleBuffer.dispose();
|
||||
this.renderTargetBlurBuffer1.dispose();
|
||||
this.renderTargetBlurBuffer2.dispose();
|
||||
this.renderTargetEdgeBuffer1.dispose();
|
||||
this.renderTargetEdgeBuffer2.dispose();
|
||||
|
||||
this.depthMaterial.dispose();
|
||||
this.prepareMaskMaterial.dispose();
|
||||
this.edgeDetectionMaterial.dispose();
|
||||
this.separableBlurMaterial1.dispose();
|
||||
this.separableBlurMaterial2.dispose();
|
||||
this.overlayMaterial.dispose();
|
||||
this.materialCopy.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.renderTargetMaskBuffer.setSize( width, height );
|
||||
this.renderTargetDepthBuffer.setSize( width, height );
|
||||
|
||||
let resx = Math.round( width / this.downSampleRatio );
|
||||
let resy = Math.round( height / this.downSampleRatio );
|
||||
this.renderTargetMaskDownSampleBuffer.setSize( resx, resy );
|
||||
this.renderTargetBlurBuffer1.setSize( resx, resy );
|
||||
this.renderTargetEdgeBuffer1.setSize( resx, resy );
|
||||
this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy );
|
||||
|
||||
resx = Math.round( resx / 2 );
|
||||
resy = Math.round( resy / 2 );
|
||||
|
||||
this.renderTargetBlurBuffer2.setSize( resx, resy );
|
||||
this.renderTargetEdgeBuffer2.setSize( resx, resy );
|
||||
|
||||
this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( resx, resy );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the Outline 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 ( this.selectedObjects.length > 0 ) {
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
this.oldClearAlpha = renderer.getClearAlpha();
|
||||
const oldAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.autoClear = false;
|
||||
|
||||
if ( maskActive ) renderer.state.buffers.stencil.setTest( false );
|
||||
|
||||
renderer.setClearColor( 0xffffff, 1 );
|
||||
|
||||
this._updateSelectionCache();
|
||||
|
||||
// Make selected objects invisible
|
||||
this._changeVisibilityOfSelectedObjects( false );
|
||||
|
||||
const currentBackground = this.renderScene.background;
|
||||
const currentOverrideMaterial = this.renderScene.overrideMaterial;
|
||||
this.renderScene.background = null;
|
||||
|
||||
// 1. Draw Non Selected objects in the depth buffer
|
||||
this.renderScene.overrideMaterial = this.depthMaterial;
|
||||
renderer.setRenderTarget( this.renderTargetDepthBuffer );
|
||||
renderer.clear();
|
||||
renderer.render( this.renderScene, this.renderCamera );
|
||||
|
||||
// Make selected objects visible
|
||||
this._changeVisibilityOfSelectedObjects( true );
|
||||
this._visibilityCache.clear();
|
||||
|
||||
// Update Texture Matrix for Depth compare
|
||||
this._updateTextureMatrix();
|
||||
|
||||
// Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
|
||||
this._changeVisibilityOfNonSelectedObjects( false );
|
||||
this.renderScene.overrideMaterial = this.prepareMaskMaterial;
|
||||
this.prepareMaskMaterial.uniforms[ 'cameraNearFar' ].value.set( this.renderCamera.near, this.renderCamera.far );
|
||||
this.prepareMaskMaterial.uniforms[ 'depthTexture' ].value = this.renderTargetDepthBuffer.texture;
|
||||
this.prepareMaskMaterial.uniforms[ 'textureMatrix' ].value = this.textureMatrix;
|
||||
renderer.setRenderTarget( this.renderTargetMaskBuffer );
|
||||
renderer.clear();
|
||||
renderer.render( this.renderScene, this.renderCamera );
|
||||
this._changeVisibilityOfNonSelectedObjects( true );
|
||||
this._visibilityCache.clear();
|
||||
this._selectionCache.clear();
|
||||
|
||||
this.renderScene.background = currentBackground;
|
||||
this.renderScene.overrideMaterial = currentOverrideMaterial;
|
||||
|
||||
// 2. Downsample to Half resolution
|
||||
this._fsQuad.material = this.materialCopy;
|
||||
this.copyUniforms[ 'tDiffuse' ].value = this.renderTargetMaskBuffer.texture;
|
||||
renderer.setRenderTarget( this.renderTargetMaskDownSampleBuffer );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
this.tempPulseColor1.copy( this.visibleEdgeColor );
|
||||
this.tempPulseColor2.copy( this.hiddenEdgeColor );
|
||||
|
||||
if ( this.pulsePeriod > 0 ) {
|
||||
|
||||
const scalar = ( 1 + 0.25 ) / 2 + Math.cos( performance.now() * 0.01 / this.pulsePeriod ) * ( 1.0 - 0.25 ) / 2;
|
||||
this.tempPulseColor1.multiplyScalar( scalar );
|
||||
this.tempPulseColor2.multiplyScalar( scalar );
|
||||
|
||||
}
|
||||
|
||||
// 3. Apply Edge Detection Pass
|
||||
this._fsQuad.material = this.edgeDetectionMaterial;
|
||||
this.edgeDetectionMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskDownSampleBuffer.texture;
|
||||
this.edgeDetectionMaterial.uniforms[ 'texSize' ].value.set( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );
|
||||
this.edgeDetectionMaterial.uniforms[ 'visibleEdgeColor' ].value = this.tempPulseColor1;
|
||||
this.edgeDetectionMaterial.uniforms[ 'hiddenEdgeColor' ].value = this.tempPulseColor2;
|
||||
renderer.setRenderTarget( this.renderTargetEdgeBuffer1 );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// 4. Apply Blur on Half res
|
||||
this._fsQuad.material = this.separableBlurMaterial1;
|
||||
this.separableBlurMaterial1.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture;
|
||||
this.separableBlurMaterial1.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionX;
|
||||
this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = this.edgeThickness;
|
||||
renderer.setRenderTarget( this.renderTargetBlurBuffer1 );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
this.separableBlurMaterial1.uniforms[ 'colorTexture' ].value = this.renderTargetBlurBuffer1.texture;
|
||||
this.separableBlurMaterial1.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionY;
|
||||
renderer.setRenderTarget( this.renderTargetEdgeBuffer1 );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// Apply Blur on quarter res
|
||||
this._fsQuad.material = this.separableBlurMaterial2;
|
||||
this.separableBlurMaterial2.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture;
|
||||
this.separableBlurMaterial2.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionX;
|
||||
renderer.setRenderTarget( this.renderTargetBlurBuffer2 );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
this.separableBlurMaterial2.uniforms[ 'colorTexture' ].value = this.renderTargetBlurBuffer2.texture;
|
||||
this.separableBlurMaterial2.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionY;
|
||||
renderer.setRenderTarget( this.renderTargetEdgeBuffer2 );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// Blend it additively over the input texture
|
||||
this._fsQuad.material = this.overlayMaterial;
|
||||
this.overlayMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskBuffer.texture;
|
||||
this.overlayMaterial.uniforms[ 'edgeTexture1' ].value = this.renderTargetEdgeBuffer1.texture;
|
||||
this.overlayMaterial.uniforms[ 'edgeTexture2' ].value = this.renderTargetEdgeBuffer2.texture;
|
||||
this.overlayMaterial.uniforms[ 'patternTexture' ].value = this.patternTexture;
|
||||
this.overlayMaterial.uniforms[ 'edgeStrength' ].value = this.edgeStrength;
|
||||
this.overlayMaterial.uniforms[ 'edgeGlow' ].value = this.edgeGlow;
|
||||
this.overlayMaterial.uniforms[ 'usePatternTexture' ].value = this.usePatternTexture;
|
||||
|
||||
|
||||
if ( maskActive ) renderer.state.buffers.stencil.setTest( true );
|
||||
|
||||
renderer.setRenderTarget( readBuffer );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
renderer.setClearColor( this._oldClearColor, this.oldClearAlpha );
|
||||
renderer.autoClear = oldAutoClear;
|
||||
|
||||
}
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
this._fsQuad.material = this.materialCopy;
|
||||
this.copyUniforms[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_updateSelectionCache() {
|
||||
|
||||
const cache = this._selectionCache;
|
||||
|
||||
function gatherSelectedMeshesCallBack( object ) {
|
||||
|
||||
if ( object.isMesh ) cache.add( object );
|
||||
|
||||
}
|
||||
|
||||
cache.clear();
|
||||
|
||||
for ( let i = 0; i < this.selectedObjects.length; i ++ ) {
|
||||
|
||||
const selectedObject = this.selectedObjects[ i ];
|
||||
selectedObject.traverse( gatherSelectedMeshesCallBack );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_changeVisibilityOfSelectedObjects( bVisible ) {
|
||||
|
||||
const cache = this._visibilityCache;
|
||||
|
||||
for ( const mesh of this._selectionCache ) {
|
||||
|
||||
if ( bVisible === true ) {
|
||||
|
||||
mesh.visible = cache.get( mesh );
|
||||
|
||||
} else {
|
||||
|
||||
cache.set( mesh, mesh.visible );
|
||||
mesh.visible = bVisible;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_changeVisibilityOfNonSelectedObjects( bVisible ) {
|
||||
|
||||
const visibilityCache = this._visibilityCache;
|
||||
const selectionCache = this._selectionCache;
|
||||
|
||||
function VisibilityChangeCallBack( object ) {
|
||||
|
||||
if ( object.isPoints || object.isLine || object.isLine2 ) {
|
||||
|
||||
// the visibility of points and lines is always set to false in order to
|
||||
// not affect the outline computation
|
||||
|
||||
if ( bVisible === true ) {
|
||||
|
||||
object.visible = visibilityCache.get( object ); // restore
|
||||
|
||||
} else {
|
||||
|
||||
visibilityCache.set( object, object.visible );
|
||||
object.visible = bVisible;
|
||||
|
||||
}
|
||||
|
||||
} else if ( object.isMesh || object.isSprite ) {
|
||||
|
||||
// only meshes and sprites are supported by OutlinePass
|
||||
|
||||
if ( ! selectionCache.has( object ) ) {
|
||||
|
||||
const visibility = object.visible;
|
||||
|
||||
if ( bVisible === false || visibilityCache.get( object ) === true ) {
|
||||
|
||||
object.visible = bVisible;
|
||||
|
||||
}
|
||||
|
||||
visibilityCache.set( object, visibility );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.renderScene.traverse( VisibilityChangeCallBack );
|
||||
|
||||
}
|
||||
|
||||
_updateTextureMatrix() {
|
||||
|
||||
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
|
||||
0.0, 0.5, 0.0, 0.5,
|
||||
0.0, 0.0, 0.5, 0.5,
|
||||
0.0, 0.0, 0.0, 1.0 );
|
||||
this.textureMatrix.multiply( this.renderCamera.projectionMatrix );
|
||||
this.textureMatrix.multiply( this.renderCamera.matrixWorldInverse );
|
||||
|
||||
}
|
||||
|
||||
_getPrepareMaskMaterial() {
|
||||
|
||||
return new ShaderMaterial( {
|
||||
|
||||
uniforms: {
|
||||
'depthTexture': { value: null },
|
||||
'cameraNearFar': { value: new Vector2( 0.5, 0.5 ) },
|
||||
'textureMatrix': { value: null }
|
||||
},
|
||||
|
||||
vertexShader:
|
||||
`#include <batching_pars_vertex>
|
||||
#include <morphtarget_pars_vertex>
|
||||
#include <skinning_pars_vertex>
|
||||
|
||||
varying vec4 projTexCoord;
|
||||
varying vec4 vPosition;
|
||||
uniform mat4 textureMatrix;
|
||||
|
||||
void main() {
|
||||
|
||||
#include <batching_vertex>
|
||||
#include <skinbase_vertex>
|
||||
#include <begin_vertex>
|
||||
#include <morphtarget_vertex>
|
||||
#include <skinning_vertex>
|
||||
#include <project_vertex>
|
||||
|
||||
vPosition = mvPosition;
|
||||
|
||||
vec4 worldPosition = vec4( transformed, 1.0 );
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
|
||||
worldPosition = instanceMatrix * worldPosition;
|
||||
|
||||
#endif
|
||||
|
||||
worldPosition = modelMatrix * worldPosition;
|
||||
|
||||
projTexCoord = textureMatrix * worldPosition;
|
||||
|
||||
}`,
|
||||
|
||||
fragmentShader:
|
||||
`#include <packing>
|
||||
varying vec4 vPosition;
|
||||
varying vec4 projTexCoord;
|
||||
uniform sampler2D depthTexture;
|
||||
uniform vec2 cameraNearFar;
|
||||
|
||||
void main() {
|
||||
|
||||
float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));
|
||||
float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );
|
||||
float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;
|
||||
gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);
|
||||
|
||||
}`
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_getEdgeDetectionMaterial() {
|
||||
|
||||
return new ShaderMaterial( {
|
||||
|
||||
uniforms: {
|
||||
'maskTexture': { value: null },
|
||||
'texSize': { value: new Vector2( 0.5, 0.5 ) },
|
||||
'visibleEdgeColor': { value: new Vector3( 1.0, 1.0, 1.0 ) },
|
||||
'hiddenEdgeColor': { value: new Vector3( 1.0, 1.0, 1.0 ) },
|
||||
},
|
||||
|
||||
vertexShader:
|
||||
`varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
}`,
|
||||
|
||||
fragmentShader:
|
||||
`varying vec2 vUv;
|
||||
|
||||
uniform sampler2D maskTexture;
|
||||
uniform vec2 texSize;
|
||||
uniform vec3 visibleEdgeColor;
|
||||
uniform vec3 hiddenEdgeColor;
|
||||
|
||||
void main() {
|
||||
vec2 invSize = 1.0 / texSize;
|
||||
vec4 uvOffset = vec4(1.0, 0.0, 0.0, 1.0) * vec4(invSize, invSize);
|
||||
vec4 c1 = texture2D( maskTexture, vUv + uvOffset.xy);
|
||||
vec4 c2 = texture2D( maskTexture, vUv - uvOffset.xy);
|
||||
vec4 c3 = texture2D( maskTexture, vUv + uvOffset.yw);
|
||||
vec4 c4 = texture2D( maskTexture, vUv - uvOffset.yw);
|
||||
float diff1 = (c1.r - c2.r)*0.5;
|
||||
float diff2 = (c3.r - c4.r)*0.5;
|
||||
float d = length( vec2(diff1, diff2) );
|
||||
float a1 = min(c1.g, c2.g);
|
||||
float a2 = min(c3.g, c4.g);
|
||||
float visibilityFactor = min(a1, a2);
|
||||
vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;
|
||||
gl_FragColor = vec4(edgeColor, 1.0) * vec4(d);
|
||||
}`
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_getSeparableBlurMaterial( maxRadius ) {
|
||||
|
||||
return new ShaderMaterial( {
|
||||
|
||||
defines: {
|
||||
'MAX_RADIUS': maxRadius,
|
||||
},
|
||||
|
||||
uniforms: {
|
||||
'colorTexture': { value: null },
|
||||
'texSize': { value: new Vector2( 0.5, 0.5 ) },
|
||||
'direction': { value: new Vector2( 0.5, 0.5 ) },
|
||||
'kernelRadius': { value: 1.0 }
|
||||
},
|
||||
|
||||
vertexShader:
|
||||
`varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
}`,
|
||||
|
||||
fragmentShader:
|
||||
`#include <common>
|
||||
varying vec2 vUv;
|
||||
uniform sampler2D colorTexture;
|
||||
uniform vec2 texSize;
|
||||
uniform vec2 direction;
|
||||
uniform float kernelRadius;
|
||||
|
||||
float gaussianPdf(in float x, in float sigma) {
|
||||
return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 invSize = 1.0 / texSize;
|
||||
float sigma = kernelRadius/2.0;
|
||||
float weightSum = gaussianPdf(0.0, sigma);
|
||||
vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;
|
||||
vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);
|
||||
vec2 uvOffset = delta;
|
||||
for( int i = 1; i <= MAX_RADIUS; i ++ ) {
|
||||
float x = kernelRadius * float(i) / float(MAX_RADIUS);
|
||||
float w = gaussianPdf(x, sigma);
|
||||
vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);
|
||||
vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);
|
||||
diffuseSum += ((sample1 + sample2) * w);
|
||||
weightSum += (2.0 * w);
|
||||
uvOffset += delta;
|
||||
}
|
||||
gl_FragColor = diffuseSum/weightSum;
|
||||
}`
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_getOverlayMaterial() {
|
||||
|
||||
return new ShaderMaterial( {
|
||||
|
||||
uniforms: {
|
||||
'maskTexture': { value: null },
|
||||
'edgeTexture1': { value: null },
|
||||
'edgeTexture2': { value: null },
|
||||
'patternTexture': { value: null },
|
||||
'edgeStrength': { value: 1.0 },
|
||||
'edgeGlow': { value: 1.0 },
|
||||
'usePatternTexture': { value: 0.0 }
|
||||
},
|
||||
|
||||
vertexShader:
|
||||
`varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
}`,
|
||||
|
||||
fragmentShader:
|
||||
`varying vec2 vUv;
|
||||
|
||||
uniform sampler2D maskTexture;
|
||||
uniform sampler2D edgeTexture1;
|
||||
uniform sampler2D edgeTexture2;
|
||||
uniform sampler2D patternTexture;
|
||||
uniform float edgeStrength;
|
||||
uniform float edgeGlow;
|
||||
uniform bool usePatternTexture;
|
||||
|
||||
void main() {
|
||||
vec4 edgeValue1 = texture2D(edgeTexture1, vUv);
|
||||
vec4 edgeValue2 = texture2D(edgeTexture2, vUv);
|
||||
vec4 maskColor = texture2D(maskTexture, vUv);
|
||||
vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);
|
||||
float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;
|
||||
vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;
|
||||
vec4 finalColor = edgeStrength * maskColor.r * edgeValue;
|
||||
if(usePatternTexture)
|
||||
finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);
|
||||
gl_FragColor = finalColor;
|
||||
}`,
|
||||
blending: AdditiveBlending,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
transparent: true
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OutlinePass.BlurDirectionX = new Vector2( 1.0, 0.0 );
|
||||
OutlinePass.BlurDirectionY = new Vector2( 0.0, 1.0 );
|
||||
|
||||
export { OutlinePass };
|
||||
148
node_modules/three/examples/jsm/postprocessing/OutputPass.js
generated
vendored
Normal file
148
node_modules/three/examples/jsm/postprocessing/OutputPass.js
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
import {
|
||||
ColorManagement,
|
||||
RawShaderMaterial,
|
||||
UniformsUtils,
|
||||
LinearToneMapping,
|
||||
ReinhardToneMapping,
|
||||
CineonToneMapping,
|
||||
AgXToneMapping,
|
||||
ACESFilmicToneMapping,
|
||||
NeutralToneMapping,
|
||||
CustomToneMapping,
|
||||
SRGBTransfer
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { OutputShader } from '../shaders/OutputShader.js';
|
||||
|
||||
/**
|
||||
* This pass is responsible for including tone mapping and color space conversion
|
||||
* into your pass chain. In most cases, this pass should be included at the end
|
||||
* of each pass chain. If a pass requires sRGB input (e.g. like FXAA), the pass
|
||||
* must follow `OutputPass` in the pass chain.
|
||||
*
|
||||
* The tone mapping and color space settings are extracted from the renderer.
|
||||
*
|
||||
* ```js
|
||||
* const outputPass = new OutputPass();
|
||||
* composer.addPass( outputPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
|
||||
*/
|
||||
class OutputPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new output pass.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* This flag indicates that this is an output pass.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isOutputPass = true;
|
||||
|
||||
/**
|
||||
* The pass uniforms.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = UniformsUtils.clone( OutputShader.uniforms );
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {RawShaderMaterial}
|
||||
*/
|
||||
this.material = new RawShaderMaterial( {
|
||||
name: OutputShader.name,
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: OutputShader.vertexShader,
|
||||
fragmentShader: OutputShader.fragmentShader
|
||||
} );
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
this._outputColorSpace = null;
|
||||
this._toneMapping = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the output 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[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
this.uniforms[ 'toneMappingExposure' ].value = renderer.toneMappingExposure;
|
||||
|
||||
// rebuild defines if required
|
||||
|
||||
if ( this._outputColorSpace !== renderer.outputColorSpace || this._toneMapping !== renderer.toneMapping ) {
|
||||
|
||||
this._outputColorSpace = renderer.outputColorSpace;
|
||||
this._toneMapping = renderer.toneMapping;
|
||||
|
||||
this.material.defines = {};
|
||||
|
||||
if ( ColorManagement.getTransfer( this._outputColorSpace ) === SRGBTransfer ) this.material.defines.SRGB_TRANSFER = '';
|
||||
|
||||
if ( this._toneMapping === LinearToneMapping ) this.material.defines.LINEAR_TONE_MAPPING = '';
|
||||
else if ( this._toneMapping === ReinhardToneMapping ) this.material.defines.REINHARD_TONE_MAPPING = '';
|
||||
else if ( this._toneMapping === CineonToneMapping ) this.material.defines.CINEON_TONE_MAPPING = '';
|
||||
else if ( this._toneMapping === ACESFilmicToneMapping ) this.material.defines.ACES_FILMIC_TONE_MAPPING = '';
|
||||
else if ( this._toneMapping === AgXToneMapping ) this.material.defines.AGX_TONE_MAPPING = '';
|
||||
else if ( this._toneMapping === NeutralToneMapping ) this.material.defines.NEUTRAL_TONE_MAPPING = '';
|
||||
else if ( this._toneMapping === CustomToneMapping ) this.material.defines.CUSTOM_TONE_MAPPING = '';
|
||||
|
||||
this.material.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if ( this.renderToScreen === true ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.material.dispose();
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { OutputPass };
|
||||
191
node_modules/three/examples/jsm/postprocessing/Pass.js
generated
vendored
Normal file
191
node_modules/three/examples/jsm/postprocessing/Pass.js
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
import {
|
||||
BufferGeometry,
|
||||
Float32BufferAttribute,
|
||||
OrthographicCamera,
|
||||
Mesh
|
||||
} from 'three';
|
||||
|
||||
/**
|
||||
* Abstract base class for all post processing passes.
|
||||
*
|
||||
* This module is only relevant for post processing with {@link WebGLRenderer}.
|
||||
*
|
||||
* @abstract
|
||||
* @three_import import { Pass } from 'three/addons/postprocessing/Pass.js';
|
||||
*/
|
||||
class Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new pass.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isPass = true;
|
||||
|
||||
/**
|
||||
* If set to `true`, the pass is processed by the composer.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.enabled = true;
|
||||
|
||||
/**
|
||||
* If set to `true`, the pass indicates to swap read and write buffer after rendering.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.needsSwap = true;
|
||||
|
||||
/**
|
||||
* If set to `true`, the pass clears its buffer before rendering
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.clear = false;
|
||||
|
||||
/**
|
||||
* If set to `true`, the result of the pass is rendered to screen. The last pass in the composers
|
||||
* pass chain gets automatically rendered to screen, no matter how this property is configured.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.renderToScreen = false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @abstract
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( /* width, height */ ) {}
|
||||
|
||||
/**
|
||||
* This method holds the render logic of a pass. It must be implemented in all derived classes.
|
||||
*
|
||||
* @abstract
|
||||
* @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 */ ) {
|
||||
|
||||
console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
dispose() {}
|
||||
|
||||
}
|
||||
|
||||
// Helper for passes that need to fill the viewport with a single quad.
|
||||
|
||||
const _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
|
||||
|
||||
// https://github.com/mrdoob/three.js/pull/21358
|
||||
|
||||
class FullscreenTriangleGeometry extends BufferGeometry {
|
||||
|
||||
constructor() {
|
||||
|
||||
super();
|
||||
|
||||
this.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) );
|
||||
this.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 2, 0, 0, 2, 0 ], 2 ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const _geometry = new FullscreenTriangleGeometry();
|
||||
|
||||
|
||||
/**
|
||||
* This module is a helper for passes which need to render a full
|
||||
* screen effect which is quite common in context of post processing.
|
||||
*
|
||||
* The intended usage is to reuse a single full screen quad for rendering
|
||||
* subsequent passes by just reassigning the `material` reference.
|
||||
*
|
||||
* This module can only be used with {@link WebGLRenderer}.
|
||||
*
|
||||
* @augments Mesh
|
||||
* @three_import import { FullScreenQuad } from 'three/addons/postprocessing/Pass.js';
|
||||
*/
|
||||
class FullScreenQuad {
|
||||
|
||||
/**
|
||||
* Constructs a new full screen quad.
|
||||
*
|
||||
* @param {?Material} material - The material to render te full screen quad with.
|
||||
*/
|
||||
constructor( material ) {
|
||||
|
||||
this._mesh = new Mesh( _geometry, material );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the instance is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this._mesh.geometry.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the full screen quad.
|
||||
*
|
||||
* @param {WebGLRenderer} renderer - The renderer.
|
||||
*/
|
||||
render( renderer ) {
|
||||
|
||||
renderer.render( this._mesh, _camera );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The quad's material.
|
||||
*
|
||||
* @type {?Material}
|
||||
*/
|
||||
get material() {
|
||||
|
||||
return this._mesh.material;
|
||||
|
||||
}
|
||||
|
||||
set material( value ) {
|
||||
|
||||
this._mesh.material = value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Pass, FullScreenQuad };
|
||||
193
node_modules/three/examples/jsm/postprocessing/RenderPass.js
generated
vendored
Normal file
193
node_modules/three/examples/jsm/postprocessing/RenderPass.js
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
import {
|
||||
Color
|
||||
} from 'three';
|
||||
import { Pass } from './Pass.js';
|
||||
|
||||
/**
|
||||
* This class represents a render pass. It takes a camera and a scene and produces
|
||||
* a beauty pass for subsequent post processing effects.
|
||||
*
|
||||
* ```js
|
||||
* const renderPass = new RenderPass( scene, camera );
|
||||
* composer.addPass( renderPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
|
||||
*/
|
||||
class RenderPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new render pass.
|
||||
*
|
||||
* @param {Scene} scene - The scene to render.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {?Material} [overrideMaterial=null] - The override material. If set, this material is used
|
||||
* for all objects in the scene.
|
||||
* @param {?(number|Color|string)} [clearColor=null] - The clear color of the render pass.
|
||||
* @param {?number} [clearAlpha=null] - The clear alpha of the render pass.
|
||||
*/
|
||||
constructor( scene, camera, overrideMaterial = null, clearColor = null, clearAlpha = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scene to render.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* The override material. If set, this material is used
|
||||
* for all objects in the scene.
|
||||
*
|
||||
* @type {?Material}
|
||||
* @default null
|
||||
*/
|
||||
this.overrideMaterial = overrideMaterial;
|
||||
|
||||
/**
|
||||
* The clear color of the render pass.
|
||||
*
|
||||
* @type {?(number|Color|string)}
|
||||
* @default null
|
||||
*/
|
||||
this.clearColor = clearColor;
|
||||
|
||||
/**
|
||||
* The clear alpha of the render pass.
|
||||
*
|
||||
* @type {?number}
|
||||
* @default null
|
||||
*/
|
||||
this.clearAlpha = clearAlpha;
|
||||
|
||||
/**
|
||||
* Overwritten to perform a clear operation by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.clear = true;
|
||||
|
||||
/**
|
||||
* If set to `true`, only the depth can be cleared when `clear` is to `false`.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.clearDepth = false;
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
/**
|
||||
* This flag indicates that this pass renders the scene itself.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isRenderPass = true;
|
||||
|
||||
this._oldClearColor = new Color();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a beauty pass with the configured scene and camera.
|
||||
*
|
||||
* @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 */ ) {
|
||||
|
||||
const oldAutoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
let oldClearAlpha, oldOverrideMaterial;
|
||||
|
||||
if ( this.overrideMaterial !== null ) {
|
||||
|
||||
oldOverrideMaterial = this.scene.overrideMaterial;
|
||||
|
||||
this.scene.overrideMaterial = this.overrideMaterial;
|
||||
|
||||
}
|
||||
|
||||
if ( this.clearColor !== null ) {
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
renderer.setClearColor( this.clearColor, renderer.getClearAlpha() );
|
||||
|
||||
}
|
||||
|
||||
if ( this.clearAlpha !== null ) {
|
||||
|
||||
oldClearAlpha = renderer.getClearAlpha();
|
||||
renderer.setClearAlpha( this.clearAlpha );
|
||||
|
||||
}
|
||||
|
||||
if ( this.clearDepth == true ) {
|
||||
|
||||
renderer.clearDepth();
|
||||
|
||||
}
|
||||
|
||||
renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
|
||||
|
||||
if ( this.clear === true ) {
|
||||
|
||||
// TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
|
||||
renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
|
||||
|
||||
}
|
||||
|
||||
renderer.render( this.scene, this.camera );
|
||||
|
||||
// restore
|
||||
|
||||
if ( this.clearColor !== null ) {
|
||||
|
||||
renderer.setClearColor( this._oldClearColor );
|
||||
|
||||
}
|
||||
|
||||
if ( this.clearAlpha !== null ) {
|
||||
|
||||
renderer.setClearAlpha( oldClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
if ( this.overrideMaterial !== null ) {
|
||||
|
||||
this.scene.overrideMaterial = oldOverrideMaterial;
|
||||
|
||||
}
|
||||
|
||||
renderer.autoClear = oldAutoClear;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { RenderPass };
|
||||
314
node_modules/three/examples/jsm/postprocessing/RenderPixelatedPass.js
generated
vendored
Normal file
314
node_modules/three/examples/jsm/postprocessing/RenderPixelatedPass.js
generated
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
import {
|
||||
WebGLRenderTarget,
|
||||
MeshNormalMaterial,
|
||||
ShaderMaterial,
|
||||
Vector2,
|
||||
Vector4,
|
||||
DepthTexture,
|
||||
NearestFilter,
|
||||
HalfFloatType
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
|
||||
/**
|
||||
* A special type of render pass that produces a pixelated beauty pass.
|
||||
*
|
||||
* ```js
|
||||
* const renderPixelatedPass = new RenderPixelatedPass( 6, scene, camera );
|
||||
* composer.addPass( renderPixelatedPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { RenderPixelatedPass } from 'three/addons/postprocessing/RenderPixelatedPass.js';
|
||||
*/
|
||||
class RenderPixelatedPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new render pixelated pass.
|
||||
*
|
||||
* @param {number} pixelSize - The effect's pixel size.
|
||||
* @param {Scene} scene - The scene to render.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {{normalEdgeStrength:number,depthEdgeStrength:number}} options - The pass options.
|
||||
*/
|
||||
constructor( pixelSize, scene, camera, options = {} ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The effect's pixel size.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
this.pixelSize = pixelSize;
|
||||
|
||||
/**
|
||||
* The scene to render.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* The normal edge strength.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.3
|
||||
*/
|
||||
this.normalEdgeStrength = options.normalEdgeStrength || 0.3;
|
||||
|
||||
/**
|
||||
* The normal edge strength.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.4
|
||||
*/
|
||||
this.depthEdgeStrength = options.depthEdgeStrength || 0.4;
|
||||
|
||||
/**
|
||||
* The pixelated material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.pixelatedMaterial = this._createPixelatedMaterial();
|
||||
|
||||
// internals
|
||||
|
||||
this._resolution = new Vector2();
|
||||
this._renderResolution = new Vector2();
|
||||
|
||||
this._normalMaterial = new MeshNormalMaterial();
|
||||
|
||||
this._beautyRenderTarget = new WebGLRenderTarget();
|
||||
this._beautyRenderTarget.texture.minFilter = NearestFilter;
|
||||
this._beautyRenderTarget.texture.magFilter = NearestFilter;
|
||||
this._beautyRenderTarget.texture.type = HalfFloatType;
|
||||
this._beautyRenderTarget.depthTexture = new DepthTexture();
|
||||
|
||||
this._normalRenderTarget = new WebGLRenderTarget();
|
||||
this._normalRenderTarget.texture.minFilter = NearestFilter;
|
||||
this._normalRenderTarget.texture.magFilter = NearestFilter;
|
||||
this._normalRenderTarget.texture.type = HalfFloatType;
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.pixelatedMaterial );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this._beautyRenderTarget.dispose();
|
||||
this._normalRenderTarget.dispose();
|
||||
|
||||
this.pixelatedMaterial.dispose();
|
||||
this._normalMaterial.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this._resolution.set( width, height );
|
||||
this._renderResolution.set( ( width / this.pixelSize ) | 0, ( height / this.pixelSize ) | 0 );
|
||||
const { x, y } = this._renderResolution;
|
||||
this._beautyRenderTarget.setSize( x, y );
|
||||
this._normalRenderTarget.setSize( x, y );
|
||||
this._fsQuad.material.uniforms.resolution.value.set( x, y, 1 / x, 1 / y );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the effect's pixel size.
|
||||
*
|
||||
* @param {number} pixelSize - The pixel size to set.
|
||||
*/
|
||||
setPixelSize( pixelSize ) {
|
||||
|
||||
this.pixelSize = pixelSize;
|
||||
this.setSize( this._resolution.x, this._resolution.y );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the pixelation 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 */ ) {
|
||||
|
||||
const uniforms = this._fsQuad.material.uniforms;
|
||||
uniforms.normalEdgeStrength.value = this.normalEdgeStrength;
|
||||
uniforms.depthEdgeStrength.value = this.depthEdgeStrength;
|
||||
|
||||
renderer.setRenderTarget( this._beautyRenderTarget );
|
||||
renderer.render( this.scene, this.camera );
|
||||
|
||||
const overrideMaterial_old = this.scene.overrideMaterial;
|
||||
renderer.setRenderTarget( this._normalRenderTarget );
|
||||
this.scene.overrideMaterial = this._normalMaterial;
|
||||
renderer.render( this.scene, this.camera );
|
||||
this.scene.overrideMaterial = overrideMaterial_old;
|
||||
|
||||
uniforms.tDiffuse.value = this._beautyRenderTarget.texture;
|
||||
uniforms.tDepth.value = this._beautyRenderTarget.depthTexture;
|
||||
uniforms.tNormal.value = this._normalRenderTarget.texture;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
|
||||
if ( this.clear ) renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_createPixelatedMaterial() {
|
||||
|
||||
return new ShaderMaterial( {
|
||||
uniforms: {
|
||||
tDiffuse: { value: null },
|
||||
tDepth: { value: null },
|
||||
tNormal: { value: null },
|
||||
resolution: { value: new Vector4() },
|
||||
normalEdgeStrength: { value: 0 },
|
||||
depthEdgeStrength: { value: 0 }
|
||||
},
|
||||
vertexShader: /* glsl */`
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}
|
||||
`,
|
||||
fragmentShader: /* glsl */`
|
||||
uniform sampler2D tDiffuse;
|
||||
uniform sampler2D tDepth;
|
||||
uniform sampler2D tNormal;
|
||||
uniform vec4 resolution;
|
||||
uniform float normalEdgeStrength;
|
||||
uniform float depthEdgeStrength;
|
||||
varying vec2 vUv;
|
||||
|
||||
float getDepth(int x, int y) {
|
||||
|
||||
return texture2D( tDepth, vUv + vec2(x, y) * resolution.zw ).r;
|
||||
|
||||
}
|
||||
|
||||
vec3 getNormal(int x, int y) {
|
||||
|
||||
return texture2D( tNormal, vUv + vec2(x, y) * resolution.zw ).rgb * 2.0 - 1.0;
|
||||
|
||||
}
|
||||
|
||||
float depthEdgeIndicator(float depth, vec3 normal) {
|
||||
|
||||
float diff = 0.0;
|
||||
diff += clamp(getDepth(1, 0) - depth, 0.0, 1.0);
|
||||
diff += clamp(getDepth(-1, 0) - depth, 0.0, 1.0);
|
||||
diff += clamp(getDepth(0, 1) - depth, 0.0, 1.0);
|
||||
diff += clamp(getDepth(0, -1) - depth, 0.0, 1.0);
|
||||
return floor(smoothstep(0.01, 0.02, diff) * 2.) / 2.;
|
||||
|
||||
}
|
||||
|
||||
float neighborNormalEdgeIndicator(int x, int y, float depth, vec3 normal) {
|
||||
|
||||
float depthDiff = getDepth(x, y) - depth;
|
||||
vec3 neighborNormal = getNormal(x, y);
|
||||
|
||||
// Edge pixels should yield to faces who's normals are closer to the bias normal.
|
||||
vec3 normalEdgeBias = vec3(1., 1., 1.); // This should probably be a parameter.
|
||||
float normalDiff = dot(normal - neighborNormal, normalEdgeBias);
|
||||
float normalIndicator = clamp(smoothstep(-.01, .01, normalDiff), 0.0, 1.0);
|
||||
|
||||
// Only the shallower pixel should detect the normal edge.
|
||||
float depthIndicator = clamp(sign(depthDiff * .25 + .0025), 0.0, 1.0);
|
||||
|
||||
return (1.0 - dot(normal, neighborNormal)) * depthIndicator * normalIndicator;
|
||||
|
||||
}
|
||||
|
||||
float normalEdgeIndicator(float depth, vec3 normal) {
|
||||
|
||||
float indicator = 0.0;
|
||||
|
||||
indicator += neighborNormalEdgeIndicator(0, -1, depth, normal);
|
||||
indicator += neighborNormalEdgeIndicator(0, 1, depth, normal);
|
||||
indicator += neighborNormalEdgeIndicator(-1, 0, depth, normal);
|
||||
indicator += neighborNormalEdgeIndicator(1, 0, depth, normal);
|
||||
|
||||
return step(0.1, indicator);
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 texel = texture2D( tDiffuse, vUv );
|
||||
|
||||
float depth = 0.0;
|
||||
vec3 normal = vec3(0.0);
|
||||
|
||||
if (depthEdgeStrength > 0.0 || normalEdgeStrength > 0.0) {
|
||||
|
||||
depth = getDepth(0, 0);
|
||||
normal = getNormal(0, 0);
|
||||
|
||||
}
|
||||
|
||||
float dei = 0.0;
|
||||
if (depthEdgeStrength > 0.0)
|
||||
dei = depthEdgeIndicator(depth, normal);
|
||||
|
||||
float nei = 0.0;
|
||||
if (normalEdgeStrength > 0.0)
|
||||
nei = normalEdgeIndicator(depth, normal);
|
||||
|
||||
float Strength = dei > 0.0 ? (1.0 - depthEdgeStrength * dei) : (1.0 + normalEdgeStrength * nei);
|
||||
|
||||
gl_FragColor = texel * Strength;
|
||||
|
||||
}
|
||||
`
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { RenderPixelatedPass };
|
||||
267
node_modules/three/examples/jsm/postprocessing/RenderTransitionPass.js
generated
vendored
Normal file
267
node_modules/three/examples/jsm/postprocessing/RenderTransitionPass.js
generated
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
import {
|
||||
HalfFloatType,
|
||||
ShaderMaterial,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { FullScreenQuad, Pass } from './Pass.js';
|
||||
|
||||
/**
|
||||
* A special type of render pass for implementing transition effects.
|
||||
* When active, the pass will transition from scene A to scene B.
|
||||
*
|
||||
* ```js
|
||||
* const renderTransitionPass = new RenderTransitionPass( fxSceneA.scene, fxSceneA.camera, fxSceneB.scene, fxSceneB.camera );
|
||||
* renderTransitionPass.setTexture( textures[ 0 ] );
|
||||
* composer.addPass( renderTransitionPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { RenderTransitionPass } from 'three/addons/postprocessing/RenderTransitionPass.js';
|
||||
*/
|
||||
class RenderTransitionPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a render transition pass.
|
||||
*
|
||||
* @param {Scene} sceneA - The first scene.
|
||||
* @param {Camera} cameraA - The camera of the first scene.
|
||||
* @param {Scene} sceneB - The second scene.
|
||||
* @param {Camera} cameraB - The camera of the second scene.
|
||||
*/
|
||||
constructor( sceneA, cameraA, sceneB, cameraB ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The first scene.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.sceneA = sceneA;
|
||||
|
||||
|
||||
/**
|
||||
* The camera of the first scene.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.cameraA = cameraA;
|
||||
|
||||
/**
|
||||
* The second scene.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.sceneB = sceneB;
|
||||
|
||||
/**
|
||||
* The camera of the second scene.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.cameraB = cameraB;
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.material = this._createMaterial();
|
||||
|
||||
// internals
|
||||
|
||||
this._renderTargetA = new WebGLRenderTarget();
|
||||
this._renderTargetA.texture.type = HalfFloatType;
|
||||
this._renderTargetB = new WebGLRenderTarget();
|
||||
this._renderTargetB.texture.type = HalfFloatType;
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transition factor. Must be in the range `[0,1]`.
|
||||
* This value determines to what degree both scenes are mixed.
|
||||
*
|
||||
* @param {boolean|number} value - The transition factor.
|
||||
*/
|
||||
setTransition( value ) {
|
||||
|
||||
this.material.uniforms.mixRatio.value = value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the usage of a texture for the effect.
|
||||
*
|
||||
* @param {boolean} value - Whether to use a texture for the transition effect or not.
|
||||
*/
|
||||
useTexture( value ) {
|
||||
|
||||
this.material.uniforms.useTexture.value = value ? 1 : 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the effect texture.
|
||||
*
|
||||
* @param {Texture} value - The effect texture.
|
||||
*/
|
||||
setTexture( value ) {
|
||||
|
||||
this.material.uniforms.tMixTexture.value = value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the texture threshold. This value defined how strong the texture effects
|
||||
* the transition. Must be in the range `[0,1]` (0 means full effect, 1 means no effect).
|
||||
*
|
||||
* @param {boolean|number} value - The threshold value.
|
||||
*/
|
||||
setTextureThreshold( value ) {
|
||||
|
||||
this.material.uniforms.threshold.value = value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this._renderTargetA.setSize( width, height );
|
||||
this._renderTargetB.setSize( width, height );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the transition 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 */ ) {
|
||||
|
||||
renderer.setRenderTarget( this._renderTargetA );
|
||||
renderer.render( this.sceneA, this.cameraA );
|
||||
renderer.setRenderTarget( this._renderTargetB );
|
||||
renderer.render( this.sceneB, this.cameraB );
|
||||
|
||||
const uniforms = this._fsQuad.material.uniforms;
|
||||
uniforms.tDiffuse1.value = this._renderTargetA.texture;
|
||||
uniforms.tDiffuse2.value = this._renderTargetB.texture;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
renderer.clear();
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.material.dispose();
|
||||
|
||||
this._renderTargetA.dispose();
|
||||
this._renderTargetB.dispose();
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_createMaterial() {
|
||||
|
||||
return new ShaderMaterial( {
|
||||
uniforms: {
|
||||
tDiffuse1: {
|
||||
value: null
|
||||
},
|
||||
tDiffuse2: {
|
||||
value: null
|
||||
},
|
||||
mixRatio: {
|
||||
value: 0.0
|
||||
},
|
||||
threshold: {
|
||||
value: 0.1
|
||||
},
|
||||
useTexture: {
|
||||
value: 1
|
||||
},
|
||||
tMixTexture: {
|
||||
value: null
|
||||
}
|
||||
},
|
||||
vertexShader: /* glsl */`
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = vec2( uv.x, uv.y );
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}
|
||||
`,
|
||||
fragmentShader: /* glsl */`
|
||||
uniform float mixRatio;
|
||||
|
||||
uniform sampler2D tDiffuse1;
|
||||
uniform sampler2D tDiffuse2;
|
||||
uniform sampler2D tMixTexture;
|
||||
|
||||
uniform int useTexture;
|
||||
uniform float threshold;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 texel1 = texture2D( tDiffuse1, vUv );
|
||||
vec4 texel2 = texture2D( tDiffuse2, vUv );
|
||||
|
||||
if (useTexture == 1) {
|
||||
|
||||
vec4 transitionTexel = texture2D( tMixTexture, vUv );
|
||||
float r = mixRatio * ( 1.0 + threshold * 2.0 ) - threshold;
|
||||
float mixf = clamp( ( transitionTexel.r - r ) * ( 1.0 / threshold ), 0.0, 1.0 );
|
||||
|
||||
gl_FragColor = mix( texel1, texel2, mixf );
|
||||
|
||||
} else {
|
||||
|
||||
gl_FragColor = mix( texel2, texel1, mixRatio );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
`
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { RenderTransitionPass };
|
||||
407
node_modules/three/examples/jsm/postprocessing/SAOPass.js
generated
vendored
Normal file
407
node_modules/three/examples/jsm/postprocessing/SAOPass.js
generated
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
import {
|
||||
AddEquation,
|
||||
Color,
|
||||
CustomBlending,
|
||||
DepthTexture,
|
||||
DstAlphaFactor,
|
||||
DstColorFactor,
|
||||
HalfFloatType,
|
||||
MeshNormalMaterial,
|
||||
NearestFilter,
|
||||
NoBlending,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
DepthStencilFormat,
|
||||
UnsignedInt248Type,
|
||||
Vector2,
|
||||
WebGLRenderTarget,
|
||||
ZeroFactor
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { SAOShader } from '../shaders/SAOShader.js';
|
||||
import { BlurShaderUtils, DepthLimitedBlurShader } from '../shaders/DepthLimitedBlurShader.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
|
||||
/**
|
||||
* A SAO implementation inspired from @bhouston previous SAO work.
|
||||
*
|
||||
* `SAOPass` provides better quality than {@link SSAOPass} but is also more expensive.
|
||||
*
|
||||
* ```js
|
||||
* const saoPass = new SAOPass( scene, camera );
|
||||
* composer.addPass( saoPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { SAOPass } from 'three/addons/postprocessing/SAOPass.js';
|
||||
*/
|
||||
class SAOPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new SAO pass.
|
||||
*
|
||||
* @param {Scene} scene - The scene to compute the AO for.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {Vector2} [resolution] - The effect's resolution.
|
||||
*/
|
||||
constructor( scene, camera, resolution = new Vector2( 256, 256 ) ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scene to render the AO for.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* Overwritten to perform a clear operation by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.clear = true;
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
this._originalClearColor = new Color();
|
||||
this._oldClearColor = new Color();
|
||||
this._oldClearAlpha = 1;
|
||||
|
||||
/**
|
||||
* The SAO parameter.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.params = {
|
||||
output: 0,
|
||||
saoBias: 0.5,
|
||||
saoIntensity: 0.18,
|
||||
saoScale: 1,
|
||||
saoKernelRadius: 100,
|
||||
saoMinResolution: 0,
|
||||
saoBlur: true,
|
||||
saoBlurRadius: 8,
|
||||
saoBlurStdDev: 4,
|
||||
saoBlurDepthCutoff: 0.01
|
||||
};
|
||||
|
||||
/**
|
||||
* The effect's resolution.
|
||||
*
|
||||
* @type {Vector2}
|
||||
* @default (256,256)
|
||||
*/
|
||||
this.resolution = new Vector2( resolution.x, resolution.y );
|
||||
|
||||
this.saoRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, { type: HalfFloatType } );
|
||||
this.blurIntermediateRenderTarget = this.saoRenderTarget.clone();
|
||||
|
||||
const depthTexture = new DepthTexture();
|
||||
depthTexture.format = DepthStencilFormat;
|
||||
depthTexture.type = UnsignedInt248Type;
|
||||
|
||||
this.normalRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter,
|
||||
type: HalfFloatType,
|
||||
depthTexture: depthTexture
|
||||
} );
|
||||
|
||||
this.normalMaterial = new MeshNormalMaterial();
|
||||
this.normalMaterial.blending = NoBlending;
|
||||
|
||||
this.saoMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SAOShader.defines ),
|
||||
fragmentShader: SAOShader.fragmentShader,
|
||||
vertexShader: SAOShader.vertexShader,
|
||||
uniforms: UniformsUtils.clone( SAOShader.uniforms )
|
||||
} );
|
||||
this.saoMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
|
||||
this.saoMaterial.uniforms[ 'tDepth' ].value = depthTexture;
|
||||
this.saoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
|
||||
this.saoMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
|
||||
this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
|
||||
this.saoMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.camera.projectionMatrix;
|
||||
this.saoMaterial.blending = NoBlending;
|
||||
|
||||
this.vBlurMaterial = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ),
|
||||
defines: Object.assign( {}, DepthLimitedBlurShader.defines ),
|
||||
vertexShader: DepthLimitedBlurShader.vertexShader,
|
||||
fragmentShader: DepthLimitedBlurShader.fragmentShader
|
||||
} );
|
||||
this.vBlurMaterial.defines[ 'DEPTH_PACKING' ] = 0;
|
||||
this.vBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
|
||||
this.vBlurMaterial.uniforms[ 'tDiffuse' ].value = this.saoRenderTarget.texture;
|
||||
this.vBlurMaterial.uniforms[ 'tDepth' ].value = depthTexture;
|
||||
this.vBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
|
||||
this.vBlurMaterial.blending = NoBlending;
|
||||
|
||||
this.hBlurMaterial = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ),
|
||||
defines: Object.assign( {}, DepthLimitedBlurShader.defines ),
|
||||
vertexShader: DepthLimitedBlurShader.vertexShader,
|
||||
fragmentShader: DepthLimitedBlurShader.fragmentShader
|
||||
} );
|
||||
this.hBlurMaterial.defines[ 'DEPTH_PACKING' ] = 0;
|
||||
this.hBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
|
||||
this.hBlurMaterial.uniforms[ 'tDiffuse' ].value = this.blurIntermediateRenderTarget.texture;
|
||||
this.hBlurMaterial.uniforms[ 'tDepth' ].value = depthTexture;
|
||||
this.hBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
|
||||
this.hBlurMaterial.blending = NoBlending;
|
||||
|
||||
this.materialCopy = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
blending: NoBlending
|
||||
} );
|
||||
this.materialCopy.transparent = true;
|
||||
this.materialCopy.depthTest = false;
|
||||
this.materialCopy.depthWrite = false;
|
||||
this.materialCopy.blending = CustomBlending;
|
||||
this.materialCopy.blendSrc = DstColorFactor;
|
||||
this.materialCopy.blendDst = ZeroFactor;
|
||||
this.materialCopy.blendEquation = AddEquation;
|
||||
this.materialCopy.blendSrcAlpha = DstAlphaFactor;
|
||||
this.materialCopy.blendDstAlpha = ZeroFactor;
|
||||
this.materialCopy.blendEquationAlpha = AddEquation;
|
||||
|
||||
this.fsQuad = new FullScreenQuad( null );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the SAO 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*/ ) {
|
||||
|
||||
// Rendering readBuffer first when rendering to screen
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
this.materialCopy.blending = NoBlending;
|
||||
this.materialCopy.uniforms[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
this.materialCopy.needsUpdate = true;
|
||||
this._renderPass( renderer, this.materialCopy, null );
|
||||
|
||||
}
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
this._oldClearAlpha = renderer.getClearAlpha();
|
||||
const oldAutoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
this.saoMaterial.uniforms[ 'bias' ].value = this.params.saoBias;
|
||||
this.saoMaterial.uniforms[ 'intensity' ].value = this.params.saoIntensity;
|
||||
this.saoMaterial.uniforms[ 'scale' ].value = this.params.saoScale;
|
||||
this.saoMaterial.uniforms[ 'kernelRadius' ].value = this.params.saoKernelRadius;
|
||||
this.saoMaterial.uniforms[ 'minResolution' ].value = this.params.saoMinResolution;
|
||||
this.saoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
|
||||
this.saoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
|
||||
// this.saoMaterial.uniforms['randomSeed'].value = Math.random();
|
||||
|
||||
const depthCutoff = this.params.saoBlurDepthCutoff * ( this.camera.far - this.camera.near );
|
||||
this.vBlurMaterial.uniforms[ 'depthCutoff' ].value = depthCutoff;
|
||||
this.hBlurMaterial.uniforms[ 'depthCutoff' ].value = depthCutoff;
|
||||
|
||||
this.vBlurMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
|
||||
this.vBlurMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
|
||||
this.hBlurMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
|
||||
this.hBlurMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
|
||||
|
||||
this.params.saoBlurRadius = Math.floor( this.params.saoBlurRadius );
|
||||
if ( ( this.prevStdDev !== this.params.saoBlurStdDev ) || ( this.prevNumSamples !== this.params.saoBlurRadius ) ) {
|
||||
|
||||
BlurShaderUtils.configure( this.vBlurMaterial, this.params.saoBlurRadius, this.params.saoBlurStdDev, new Vector2( 0, 1 ) );
|
||||
BlurShaderUtils.configure( this.hBlurMaterial, this.params.saoBlurRadius, this.params.saoBlurStdDev, new Vector2( 1, 0 ) );
|
||||
this.prevStdDev = this.params.saoBlurStdDev;
|
||||
this.prevNumSamples = this.params.saoBlurRadius;
|
||||
|
||||
}
|
||||
|
||||
// render normal and depth
|
||||
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
|
||||
|
||||
// Rendering SAO texture
|
||||
this._renderPass( renderer, this.saoMaterial, this.saoRenderTarget, 0xffffff, 1.0 );
|
||||
|
||||
// Blurring SAO texture
|
||||
if ( this.params.saoBlur ) {
|
||||
|
||||
this._renderPass( renderer, this.vBlurMaterial, this.blurIntermediateRenderTarget, 0xffffff, 1.0 );
|
||||
this._renderPass( renderer, this.hBlurMaterial, this.saoRenderTarget, 0xffffff, 1.0 );
|
||||
|
||||
}
|
||||
|
||||
const outputMaterial = this.materialCopy;
|
||||
|
||||
// Setting up SAO rendering
|
||||
if ( this.params.output === SAOPass.OUTPUT.Normal ) {
|
||||
|
||||
this.materialCopy.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
|
||||
this.materialCopy.needsUpdate = true;
|
||||
|
||||
} else {
|
||||
|
||||
this.materialCopy.uniforms[ 'tDiffuse' ].value = this.saoRenderTarget.texture;
|
||||
this.materialCopy.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
// Blending depends on output
|
||||
if ( this.params.output === SAOPass.OUTPUT.Default ) {
|
||||
|
||||
outputMaterial.blending = CustomBlending;
|
||||
|
||||
} else {
|
||||
|
||||
outputMaterial.blending = NoBlending;
|
||||
|
||||
}
|
||||
|
||||
// Rendering SAOPass result on top of previous pass
|
||||
this._renderPass( renderer, outputMaterial, this.renderToScreen ? null : readBuffer );
|
||||
|
||||
renderer.setClearColor( this._oldClearColor, this._oldClearAlpha );
|
||||
renderer.autoClear = oldAutoClear;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.saoRenderTarget.setSize( width, height );
|
||||
this.blurIntermediateRenderTarget.setSize( width, height );
|
||||
this.normalRenderTarget.setSize( width, height );
|
||||
|
||||
this.saoMaterial.uniforms[ 'size' ].value.set( width, height );
|
||||
this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
|
||||
this.saoMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.camera.projectionMatrix;
|
||||
this.saoMaterial.needsUpdate = true;
|
||||
|
||||
this.vBlurMaterial.uniforms[ 'size' ].value.set( width, height );
|
||||
this.vBlurMaterial.needsUpdate = true;
|
||||
|
||||
this.hBlurMaterial.uniforms[ 'size' ].value.set( width, height );
|
||||
this.hBlurMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.saoRenderTarget.dispose();
|
||||
this.blurIntermediateRenderTarget.dispose();
|
||||
this.normalRenderTarget.dispose();
|
||||
|
||||
this.normalMaterial.dispose();
|
||||
this.saoMaterial.dispose();
|
||||
this.vBlurMaterial.dispose();
|
||||
this.hBlurMaterial.dispose();
|
||||
this.materialCopy.dispose();
|
||||
|
||||
this.fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
// internal
|
||||
|
||||
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
// save original state
|
||||
renderer.getClearColor( this._originalClearColor );
|
||||
const originalClearAlpha = renderer.getClearAlpha();
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
|
||||
// setup pass state
|
||||
renderer.autoClear = false;
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this.fsQuad.material = passMaterial;
|
||||
this.fsQuad.render( renderer );
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this._originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
renderer.getClearColor( this._originalClearColor );
|
||||
const originalClearAlpha = renderer.getClearAlpha();
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.autoClear = false;
|
||||
|
||||
clearColor = overrideMaterial.clearColor || clearColor;
|
||||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this.scene.overrideMaterial = overrideMaterial;
|
||||
renderer.render( this.scene, this.camera );
|
||||
this.scene.overrideMaterial = null;
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this._originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SAOPass.OUTPUT = {
|
||||
'Default': 0,
|
||||
'SAO': 1,
|
||||
'Normal': 2
|
||||
};
|
||||
|
||||
export { SAOPass };
|
||||
230
node_modules/three/examples/jsm/postprocessing/SMAAPass.js
generated
vendored
Normal file
230
node_modules/three/examples/jsm/postprocessing/SMAAPass.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
313
node_modules/three/examples/jsm/postprocessing/SSAARenderPass.js
generated
vendored
Normal file
313
node_modules/three/examples/jsm/postprocessing/SSAARenderPass.js
generated
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
import {
|
||||
AdditiveBlending,
|
||||
Color,
|
||||
HalfFloatType,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
|
||||
/**
|
||||
* Supersample Anti-Aliasing Render Pass.
|
||||
*
|
||||
* This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.
|
||||
*
|
||||
* ```js
|
||||
* const ssaaRenderPass = new SSAARenderPass( scene, camera );
|
||||
* ssaaRenderPass.sampleLevel = 3;
|
||||
* composer.addPass( ssaaRenderPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { SSAARenderPass } from 'three/addons/postprocessing/SSAARenderPass.js';
|
||||
*/
|
||||
class SSAARenderPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new SSAA render pass.
|
||||
*
|
||||
* @param {Scene} scene - The scene to render.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {?(number|Color|string)} [clearColor=0x000000] - The clear color of the render pass.
|
||||
* @param {?number} [clearAlpha=0] - The clear alpha of the render pass.
|
||||
*/
|
||||
constructor( scene, camera, clearColor = 0x000000, clearAlpha = 0 ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scene to render.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* The sample level. Specified as n, where the number of
|
||||
* samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 4
|
||||
*/
|
||||
this.sampleLevel = 4;
|
||||
|
||||
/**
|
||||
* Whether the pass should be unbiased or not. This property has the most
|
||||
* visible effect when rendering to a RGBA8 buffer because it mitigates
|
||||
* rounding errors. By default RGBA16F is used.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.unbiased = true;
|
||||
|
||||
/**
|
||||
* Whether to use a stencil buffer or not. This property can't
|
||||
* be changed after the first render.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.stencilBuffer = false;
|
||||
|
||||
/**
|
||||
* The clear color of the render pass.
|
||||
*
|
||||
* @type {?(number|Color|string)}
|
||||
* @default 0x000000
|
||||
*/
|
||||
this.clearColor = clearColor;
|
||||
|
||||
/**
|
||||
* The clear alpha of the render pass.
|
||||
*
|
||||
* @type {?number}
|
||||
* @default 0
|
||||
*/
|
||||
this.clearAlpha = clearAlpha;
|
||||
|
||||
// internals
|
||||
|
||||
this._sampleRenderTarget = null;
|
||||
|
||||
this._oldClearColor = new Color();
|
||||
|
||||
this._copyUniforms = UniformsUtils.clone( CopyShader.uniforms );
|
||||
|
||||
this._copyMaterial = new ShaderMaterial( {
|
||||
uniforms: this._copyUniforms,
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
transparent: true,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
premultipliedAlpha: true,
|
||||
blending: AdditiveBlending
|
||||
} );
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this._copyMaterial );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
if ( this._sampleRenderTarget ) {
|
||||
|
||||
this._sampleRenderTarget.dispose();
|
||||
this._sampleRenderTarget = null;
|
||||
|
||||
}
|
||||
|
||||
this._copyMaterial.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
if ( this._sampleRenderTarget ) this._sampleRenderTarget.setSize( width, height );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the SSAA render 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 ( ! this._sampleRenderTarget ) {
|
||||
|
||||
this._sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType, stencilBuffer: this.stencilBuffer } );
|
||||
this._sampleRenderTarget.texture.name = 'SSAARenderPass.sample';
|
||||
|
||||
}
|
||||
|
||||
const jitterOffsets = _JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ];
|
||||
|
||||
const autoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
const oldClearAlpha = renderer.getClearAlpha();
|
||||
|
||||
const baseSampleWeight = 1.0 / jitterOffsets.length;
|
||||
const roundingRange = 1 / 32;
|
||||
this._copyUniforms[ 'tDiffuse' ].value = this._sampleRenderTarget.texture;
|
||||
|
||||
const viewOffset = {
|
||||
|
||||
fullWidth: readBuffer.width,
|
||||
fullHeight: readBuffer.height,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
width: readBuffer.width,
|
||||
height: readBuffer.height
|
||||
|
||||
};
|
||||
|
||||
const originalViewOffset = Object.assign( {}, this.camera.view );
|
||||
|
||||
if ( originalViewOffset.enabled ) Object.assign( viewOffset, originalViewOffset );
|
||||
|
||||
// render the scene multiple times, each slightly jitter offset from the last and accumulate the results.
|
||||
for ( let i = 0; i < jitterOffsets.length; i ++ ) {
|
||||
|
||||
const jitterOffset = jitterOffsets[ i ];
|
||||
|
||||
if ( this.camera.setViewOffset ) {
|
||||
|
||||
this.camera.setViewOffset(
|
||||
|
||||
viewOffset.fullWidth, viewOffset.fullHeight,
|
||||
|
||||
viewOffset.offsetX + jitterOffset[ 0 ] * 0.0625, viewOffset.offsetY + jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16
|
||||
|
||||
viewOffset.width, viewOffset.height
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
let sampleWeight = baseSampleWeight;
|
||||
|
||||
if ( this.unbiased ) {
|
||||
|
||||
// the theory is that equal weights for each sample lead to an accumulation of rounding errors.
|
||||
// The following equation varies the sampleWeight per sample so that it is uniformly distributed
|
||||
// across a range of values whose rounding errors cancel each other out.
|
||||
|
||||
const uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length );
|
||||
sampleWeight += roundingRange * uniformCenteredDistribution;
|
||||
|
||||
}
|
||||
|
||||
this._copyUniforms[ 'opacity' ].value = sampleWeight;
|
||||
renderer.setClearColor( this.clearColor, this.clearAlpha );
|
||||
renderer.setRenderTarget( this._sampleRenderTarget );
|
||||
renderer.clear();
|
||||
renderer.render( this.scene, this.camera );
|
||||
|
||||
renderer.setRenderTarget( this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
if ( i === 0 ) {
|
||||
|
||||
renderer.setClearColor( 0x000000, 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
if ( this.camera.setViewOffset && originalViewOffset.enabled ) {
|
||||
|
||||
this.camera.setViewOffset(
|
||||
|
||||
originalViewOffset.fullWidth, originalViewOffset.fullHeight,
|
||||
|
||||
originalViewOffset.offsetX, originalViewOffset.offsetY,
|
||||
|
||||
originalViewOffset.width, originalViewOffset.height
|
||||
|
||||
);
|
||||
|
||||
} else if ( this.camera.clearViewOffset ) {
|
||||
|
||||
this.camera.clearViewOffset();
|
||||
|
||||
}
|
||||
|
||||
renderer.autoClear = autoClear;
|
||||
renderer.setClearColor( this._oldClearColor, oldClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// These jitter vectors are specified in integers because it is easier.
|
||||
// I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5)
|
||||
// before being used, thus these integers need to be scaled by 1/16.
|
||||
//
|
||||
// Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
|
||||
const _JitterVectors = [
|
||||
[
|
||||
[ 0, 0 ]
|
||||
],
|
||||
[
|
||||
[ 4, 4 ], [ - 4, - 4 ]
|
||||
],
|
||||
[
|
||||
[ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]
|
||||
],
|
||||
[
|
||||
[ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ],
|
||||
[ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]
|
||||
],
|
||||
[
|
||||
[ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ],
|
||||
[ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ],
|
||||
[ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ],
|
||||
[ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]
|
||||
],
|
||||
[
|
||||
[ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ],
|
||||
[ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ],
|
||||
[ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ],
|
||||
[ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ],
|
||||
[ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ],
|
||||
[ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ],
|
||||
[ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ],
|
||||
[ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]
|
||||
]
|
||||
];
|
||||
|
||||
export { SSAARenderPass };
|
||||
527
node_modules/three/examples/jsm/postprocessing/SSAOPass.js
generated
vendored
Normal file
527
node_modules/three/examples/jsm/postprocessing/SSAOPass.js
generated
vendored
Normal file
@@ -0,0 +1,527 @@
|
||||
import {
|
||||
AddEquation,
|
||||
Color,
|
||||
CustomBlending,
|
||||
DataTexture,
|
||||
DepthTexture,
|
||||
DstAlphaFactor,
|
||||
DstColorFactor,
|
||||
FloatType,
|
||||
HalfFloatType,
|
||||
MathUtils,
|
||||
MeshNormalMaterial,
|
||||
NearestFilter,
|
||||
NoBlending,
|
||||
RedFormat,
|
||||
DepthStencilFormat,
|
||||
UnsignedInt248Type,
|
||||
RepeatWrapping,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
Vector3,
|
||||
WebGLRenderTarget,
|
||||
ZeroFactor
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { SimplexNoise } from '../math/SimplexNoise.js';
|
||||
import { SSAOBlurShader, SSAODepthShader, SSAOShader } from '../shaders/SSAOShader.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
|
||||
/**
|
||||
* A pass for a basic SSAO effect.
|
||||
*
|
||||
* {@link SAOPass} and {@link GTAPass} produce a more advanced AO but are also
|
||||
* more expensive.
|
||||
*
|
||||
* ```js
|
||||
* const ssaoPass = new SSAOPass( scene, camera, width, height );
|
||||
* composer.addPass( ssaoPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { SSAOPass } from 'three/addons/postprocessing/SSAOPass.js';
|
||||
*/
|
||||
class SSAOPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new SSAO pass.
|
||||
*
|
||||
* @param {Scene} scene - The scene to compute the AO for.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {number} [width=512] - The width of the effect.
|
||||
* @param {number} [height=512] - The height of the effect.
|
||||
* @param {number} [kernelSize=32] - The kernel size.
|
||||
*/
|
||||
constructor( scene, camera, width = 512, height = 512, kernelSize = 32 ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The width of the effect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 512
|
||||
*/
|
||||
this.width = width;
|
||||
|
||||
/**
|
||||
* The height of the effect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 512
|
||||
*/
|
||||
this.height = height;
|
||||
|
||||
/**
|
||||
* Overwritten to perform a clear operation by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.clear = true;
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* The scene to render the AO for.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The kernel radius controls how wide the
|
||||
* AO spreads.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 8
|
||||
*/
|
||||
this.kernelRadius = 8;
|
||||
this.kernel = [];
|
||||
this.noiseTexture = null;
|
||||
|
||||
/**
|
||||
* The output configuration.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.output = 0;
|
||||
|
||||
/**
|
||||
* Defines the minimum distance that should be
|
||||
* affected by the AO.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.005
|
||||
*/
|
||||
this.minDistance = 0.005;
|
||||
|
||||
/**
|
||||
* Defines the maximum distance that should be
|
||||
* affected by the AO.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.1
|
||||
*/
|
||||
this.maxDistance = 0.1;
|
||||
|
||||
this._visibilityCache = [];
|
||||
|
||||
//
|
||||
|
||||
this._generateSampleKernel( kernelSize );
|
||||
this._generateRandomKernelRotations();
|
||||
|
||||
// depth texture
|
||||
|
||||
const depthTexture = new DepthTexture();
|
||||
depthTexture.format = DepthStencilFormat;
|
||||
depthTexture.type = UnsignedInt248Type;
|
||||
|
||||
// normal render target with depth buffer
|
||||
|
||||
this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter,
|
||||
type: HalfFloatType,
|
||||
depthTexture: depthTexture
|
||||
} );
|
||||
|
||||
// ssao render target
|
||||
|
||||
this.ssaoRenderTarget = new WebGLRenderTarget( this.width, this.height, { type: HalfFloatType } );
|
||||
|
||||
this.blurRenderTarget = this.ssaoRenderTarget.clone();
|
||||
|
||||
// ssao material
|
||||
|
||||
this.ssaoMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SSAOShader.defines ),
|
||||
uniforms: UniformsUtils.clone( SSAOShader.uniforms ),
|
||||
vertexShader: SSAOShader.vertexShader,
|
||||
fragmentShader: SSAOShader.fragmentShader,
|
||||
blending: NoBlending
|
||||
} );
|
||||
|
||||
this.ssaoMaterial.defines[ 'KERNEL_SIZE' ] = kernelSize;
|
||||
|
||||
this.ssaoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
|
||||
this.ssaoMaterial.uniforms[ 'tDepth' ].value = this.normalRenderTarget.depthTexture;
|
||||
this.ssaoMaterial.uniforms[ 'tNoise' ].value = this.noiseTexture;
|
||||
this.ssaoMaterial.uniforms[ 'kernel' ].value = this.kernel;
|
||||
this.ssaoMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
|
||||
this.ssaoMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
|
||||
this.ssaoMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
|
||||
this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
|
||||
this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
|
||||
|
||||
// normal material
|
||||
|
||||
this.normalMaterial = new MeshNormalMaterial();
|
||||
this.normalMaterial.blending = NoBlending;
|
||||
|
||||
// blur material
|
||||
|
||||
this.blurMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SSAOBlurShader.defines ),
|
||||
uniforms: UniformsUtils.clone( SSAOBlurShader.uniforms ),
|
||||
vertexShader: SSAOBlurShader.vertexShader,
|
||||
fragmentShader: SSAOBlurShader.fragmentShader
|
||||
} );
|
||||
this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
|
||||
this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
|
||||
|
||||
// material for rendering the depth
|
||||
|
||||
this.depthRenderMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SSAODepthShader.defines ),
|
||||
uniforms: UniformsUtils.clone( SSAODepthShader.uniforms ),
|
||||
vertexShader: SSAODepthShader.vertexShader,
|
||||
fragmentShader: SSAODepthShader.fragmentShader,
|
||||
blending: NoBlending
|
||||
} );
|
||||
this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.normalRenderTarget.depthTexture;
|
||||
this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
|
||||
this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
|
||||
|
||||
// material for rendering the content of a render target
|
||||
|
||||
this.copyMaterial = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
transparent: true,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
blendSrc: DstColorFactor,
|
||||
blendDst: ZeroFactor,
|
||||
blendEquation: AddEquation,
|
||||
blendSrcAlpha: DstAlphaFactor,
|
||||
blendDstAlpha: ZeroFactor,
|
||||
blendEquationAlpha: AddEquation
|
||||
} );
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( null );
|
||||
|
||||
this._originalClearColor = new Color();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
// dispose render targets
|
||||
|
||||
this.normalRenderTarget.dispose();
|
||||
this.ssaoRenderTarget.dispose();
|
||||
this.blurRenderTarget.dispose();
|
||||
|
||||
// dispose materials
|
||||
|
||||
this.normalMaterial.dispose();
|
||||
this.blurMaterial.dispose();
|
||||
this.copyMaterial.dispose();
|
||||
this.depthRenderMaterial.dispose();
|
||||
|
||||
// dispose full screen quad
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the SSAO 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 */ ) {
|
||||
|
||||
// render normals and depth (honor only meshes, points and lines do not contribute to SSAO)
|
||||
|
||||
this._overrideVisibility();
|
||||
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
|
||||
this._restoreVisibility();
|
||||
|
||||
// render SSAO
|
||||
|
||||
this.ssaoMaterial.uniforms[ 'kernelRadius' ].value = this.kernelRadius;
|
||||
this.ssaoMaterial.uniforms[ 'minDistance' ].value = this.minDistance;
|
||||
this.ssaoMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
|
||||
this._renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget );
|
||||
|
||||
// render blur
|
||||
|
||||
this._renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
|
||||
|
||||
// output result to screen
|
||||
|
||||
switch ( this.output ) {
|
||||
|
||||
case SSAOPass.OUTPUT.SSAO:
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssaoRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case SSAOPass.OUTPUT.Blur:
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case SSAOPass.OUTPUT.Depth:
|
||||
|
||||
this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : readBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case SSAOPass.OUTPUT.Normal:
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case SSAOPass.OUTPUT.Default:
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
|
||||
this.copyMaterial.blending = CustomBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn( 'THREE.SSAOPass: Unknown output type.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.ssaoRenderTarget.setSize( width, height );
|
||||
this.normalRenderTarget.setSize( width, height );
|
||||
this.blurRenderTarget.setSize( width, height );
|
||||
|
||||
this.ssaoMaterial.uniforms[ 'resolution' ].value.set( width, height );
|
||||
this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
|
||||
this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
|
||||
|
||||
this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
// save original state
|
||||
renderer.getClearColor( this._originalClearColor );
|
||||
const originalClearAlpha = renderer.getClearAlpha();
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
|
||||
// setup pass state
|
||||
renderer.autoClear = false;
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this._fsQuad.material = passMaterial;
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this._originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
renderer.getClearColor( this._originalClearColor );
|
||||
const originalClearAlpha = renderer.getClearAlpha();
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.autoClear = false;
|
||||
|
||||
clearColor = overrideMaterial.clearColor || clearColor;
|
||||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
|
||||
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this.scene.overrideMaterial = overrideMaterial;
|
||||
renderer.render( this.scene, this.camera );
|
||||
this.scene.overrideMaterial = null;
|
||||
|
||||
// restore original state
|
||||
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this._originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
_generateSampleKernel( kernelSize ) {
|
||||
|
||||
const kernel = this.kernel;
|
||||
|
||||
for ( let i = 0; i < kernelSize; i ++ ) {
|
||||
|
||||
const sample = new Vector3();
|
||||
sample.x = ( Math.random() * 2 ) - 1;
|
||||
sample.y = ( Math.random() * 2 ) - 1;
|
||||
sample.z = Math.random();
|
||||
|
||||
sample.normalize();
|
||||
|
||||
let scale = i / kernelSize;
|
||||
scale = MathUtils.lerp( 0.1, 1, scale * scale );
|
||||
sample.multiplyScalar( scale );
|
||||
|
||||
kernel.push( sample );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_generateRandomKernelRotations() {
|
||||
|
||||
const width = 4, height = 4;
|
||||
|
||||
const simplex = new SimplexNoise();
|
||||
|
||||
const size = width * height;
|
||||
const data = new Float32Array( size );
|
||||
|
||||
for ( let i = 0; i < size; i ++ ) {
|
||||
|
||||
const x = ( Math.random() * 2 ) - 1;
|
||||
const y = ( Math.random() * 2 ) - 1;
|
||||
const z = 0;
|
||||
|
||||
data[ i ] = simplex.noise3d( x, y, z );
|
||||
|
||||
}
|
||||
|
||||
this.noiseTexture = new DataTexture( data, width, height, RedFormat, FloatType );
|
||||
this.noiseTexture.wrapS = RepeatWrapping;
|
||||
this.noiseTexture.wrapT = RepeatWrapping;
|
||||
this.noiseTexture.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
_overrideVisibility() {
|
||||
|
||||
const scene = this.scene;
|
||||
const cache = this._visibilityCache;
|
||||
|
||||
scene.traverse( function ( object ) {
|
||||
|
||||
if ( ( object.isPoints || object.isLine || object.isLine2 ) && object.visible ) {
|
||||
|
||||
object.visible = false;
|
||||
cache.push( object );
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_restoreVisibility() {
|
||||
|
||||
const cache = this._visibilityCache;
|
||||
|
||||
for ( let i = 0; i < cache.length; i ++ ) {
|
||||
|
||||
cache[ i ].visible = true;
|
||||
|
||||
}
|
||||
|
||||
cache.length = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SSAOPass.OUTPUT = {
|
||||
'Default': 0,
|
||||
'SSAO': 1,
|
||||
'Blur': 2,
|
||||
'Depth': 3,
|
||||
'Normal': 4
|
||||
};
|
||||
|
||||
export { SSAOPass };
|
||||
856
node_modules/three/examples/jsm/postprocessing/SSRPass.js
generated
vendored
Normal file
856
node_modules/three/examples/jsm/postprocessing/SSRPass.js
generated
vendored
Normal file
@@ -0,0 +1,856 @@
|
||||
import {
|
||||
AddEquation,
|
||||
Color,
|
||||
NormalBlending,
|
||||
DepthTexture,
|
||||
SrcAlphaFactor,
|
||||
OneMinusSrcAlphaFactor,
|
||||
MeshNormalMaterial,
|
||||
MeshBasicMaterial,
|
||||
NearestFilter,
|
||||
NoBlending,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
UnsignedShortType,
|
||||
WebGLRenderTarget,
|
||||
HalfFloatType,
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { SSRBlurShader, SSRDepthShader, SSRShader } from '../shaders/SSRShader.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
|
||||
/**
|
||||
* A pass for a basic SSR effect.
|
||||
*
|
||||
* ```js
|
||||
* const ssrPass = new SSRPass( {
|
||||
* renderer,
|
||||
* scene,
|
||||
* camera,
|
||||
* width: innerWidth,
|
||||
* height: innerHeight
|
||||
* } );
|
||||
* composer.addPass( ssrPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { SSRPass } from 'three/addons/postprocessing/SSRPass.js';
|
||||
*/
|
||||
class SSRPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new SSR pass.
|
||||
*
|
||||
* @param {SSRPass~Options} options - The pass options.
|
||||
*/
|
||||
constructor( { renderer, scene, camera, width = 512, height = 512, selects = null, bouncing = false, groundReflector = null } ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The width of the effect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 512
|
||||
*/
|
||||
this.width = width;
|
||||
|
||||
/**
|
||||
* The height of the effect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 512
|
||||
*/
|
||||
this.height = height;
|
||||
|
||||
/**
|
||||
* Overwritten to perform a clear operation by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.clear = true;
|
||||
|
||||
/**
|
||||
* The renderer.
|
||||
*
|
||||
* @type {WebGLRenderer}
|
||||
*/
|
||||
this.renderer = renderer;
|
||||
|
||||
/**
|
||||
* The scene to render.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* The camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* The ground reflector.
|
||||
*
|
||||
* @type {?ReflectorForSSRPass}
|
||||
* @default 0
|
||||
*/
|
||||
this.groundReflector = groundReflector;
|
||||
|
||||
/**
|
||||
* The opacity.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0.5
|
||||
*/
|
||||
this.opacity = SSRShader.uniforms.opacity.value;
|
||||
|
||||
/**
|
||||
* The output configuration.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.output = 0;
|
||||
|
||||
/**
|
||||
* Controls how far a fragment can reflect.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 180
|
||||
*/
|
||||
this.maxDistance = SSRShader.uniforms.maxDistance.value;
|
||||
|
||||
/**
|
||||
* Controls the cutoff between what counts as a
|
||||
* possible reflection hit and what does not.
|
||||
*
|
||||
* @type {number}
|
||||
* @default .018
|
||||
*/
|
||||
this.thickness = SSRShader.uniforms.thickness.value;
|
||||
|
||||
this.tempColor = new Color();
|
||||
|
||||
this._selects = selects;
|
||||
|
||||
this._resolutionScale = 1;
|
||||
|
||||
/**
|
||||
* Whether the pass is selective or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.selective = Array.isArray( this._selects );
|
||||
|
||||
/**
|
||||
* Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
|
||||
*
|
||||
* @name SSRPass#selects
|
||||
* @type {?Array<Object3D>}
|
||||
* @default null
|
||||
*/
|
||||
Object.defineProperty( this, 'selects', {
|
||||
get() {
|
||||
|
||||
return this._selects;
|
||||
|
||||
},
|
||||
set( val ) {
|
||||
|
||||
if ( this._selects === val ) return;
|
||||
this._selects = val;
|
||||
if ( Array.isArray( val ) ) {
|
||||
|
||||
this.selective = true;
|
||||
this.ssrMaterial.defines.SELECTIVE = true;
|
||||
this.ssrMaterial.needsUpdate = true;
|
||||
|
||||
} else {
|
||||
|
||||
this.selective = false;
|
||||
this.ssrMaterial.defines.SELECTIVE = false;
|
||||
this.ssrMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
this._bouncing = bouncing;
|
||||
|
||||
/**
|
||||
* Whether bouncing is enabled or not.
|
||||
*
|
||||
* @name SSRPass#bouncing
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
Object.defineProperty( this, 'bouncing', {
|
||||
get() {
|
||||
|
||||
return this._bouncing;
|
||||
|
||||
},
|
||||
set( val ) {
|
||||
|
||||
if ( this._bouncing === val ) return;
|
||||
this._bouncing = val;
|
||||
if ( val ) {
|
||||
|
||||
this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
|
||||
|
||||
} else {
|
||||
|
||||
this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
/**
|
||||
* Whether to blur reflections or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.blur = true;
|
||||
|
||||
this._distanceAttenuation = SSRShader.defines.DISTANCE_ATTENUATION;
|
||||
|
||||
/**
|
||||
* Whether to use distance attenuation or not.
|
||||
*
|
||||
* @name SSRPass#distanceAttenuation
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
Object.defineProperty( this, 'distanceAttenuation', {
|
||||
get() {
|
||||
|
||||
return this._distanceAttenuation;
|
||||
|
||||
},
|
||||
set( val ) {
|
||||
|
||||
if ( this._distanceAttenuation === val ) return;
|
||||
this._distanceAttenuation = val;
|
||||
this.ssrMaterial.defines.DISTANCE_ATTENUATION = val;
|
||||
this.ssrMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
this._fresnel = SSRShader.defines.FRESNEL;
|
||||
|
||||
/**
|
||||
* Whether to use fresnel or not.
|
||||
*
|
||||
* @name SSRPass#fresnel
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
Object.defineProperty( this, 'fresnel', {
|
||||
get() {
|
||||
|
||||
return this._fresnel;
|
||||
|
||||
},
|
||||
set( val ) {
|
||||
|
||||
if ( this._fresnel === val ) return;
|
||||
this._fresnel = val;
|
||||
this.ssrMaterial.defines.FRESNEL = val;
|
||||
this.ssrMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
this._infiniteThick = SSRShader.defines.INFINITE_THICK;
|
||||
|
||||
/**
|
||||
* Whether to use infinite thickness or not.
|
||||
*
|
||||
* @name SSRPass#infiniteThick
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
Object.defineProperty( this, 'infiniteThick', {
|
||||
get() {
|
||||
|
||||
return this._infiniteThick;
|
||||
|
||||
},
|
||||
set( val ) {
|
||||
|
||||
if ( this._infiniteThick === val ) return;
|
||||
this._infiniteThick = val;
|
||||
this.ssrMaterial.defines.INFINITE_THICK = val;
|
||||
this.ssrMaterial.needsUpdate = true;
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
// beauty render target with depth buffer
|
||||
|
||||
const depthTexture = new DepthTexture();
|
||||
depthTexture.type = UnsignedShortType;
|
||||
depthTexture.minFilter = NearestFilter;
|
||||
depthTexture.magFilter = NearestFilter;
|
||||
|
||||
this.beautyRenderTarget = new WebGLRenderTarget( this.width, this.height, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter,
|
||||
type: HalfFloatType,
|
||||
depthTexture: depthTexture,
|
||||
depthBuffer: true
|
||||
} );
|
||||
|
||||
//for bouncing
|
||||
this.prevRenderTarget = new WebGLRenderTarget( this.width, this.height, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter
|
||||
} );
|
||||
|
||||
// normal render target
|
||||
|
||||
this.normalRenderTarget = new WebGLRenderTarget( this.width, this.height, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter,
|
||||
type: HalfFloatType,
|
||||
} );
|
||||
|
||||
// metalness render target
|
||||
|
||||
this.metalnessRenderTarget = new WebGLRenderTarget( this.width, this.height, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter,
|
||||
type: HalfFloatType,
|
||||
} );
|
||||
|
||||
|
||||
|
||||
// ssr render target
|
||||
|
||||
this.ssrRenderTarget = new WebGLRenderTarget( this.width, this.height, {
|
||||
minFilter: NearestFilter,
|
||||
magFilter: NearestFilter
|
||||
} );
|
||||
|
||||
this.blurRenderTarget = this.ssrRenderTarget.clone();
|
||||
this.blurRenderTarget2 = this.ssrRenderTarget.clone();
|
||||
// this.blurRenderTarget3 = this.ssrRenderTarget.clone();
|
||||
|
||||
// ssr material
|
||||
|
||||
this.ssrMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SSRShader.defines, {
|
||||
MAX_STEP: Math.sqrt( this.width * this.width + this.height * this.height )
|
||||
} ),
|
||||
uniforms: UniformsUtils.clone( SSRShader.uniforms ),
|
||||
vertexShader: SSRShader.vertexShader,
|
||||
fragmentShader: SSRShader.fragmentShader,
|
||||
blending: NoBlending
|
||||
} );
|
||||
|
||||
this.ssrMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
|
||||
this.ssrMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
|
||||
this.ssrMaterial.defines.SELECTIVE = this.selective;
|
||||
this.ssrMaterial.needsUpdate = true;
|
||||
this.ssrMaterial.uniforms[ 'tMetalness' ].value = this.metalnessRenderTarget.texture;
|
||||
this.ssrMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
|
||||
this.ssrMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
|
||||
this.ssrMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
|
||||
this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
|
||||
this.ssrMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
|
||||
this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
|
||||
this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
|
||||
|
||||
// normal material
|
||||
|
||||
this.normalMaterial = new MeshNormalMaterial();
|
||||
this.normalMaterial.blending = NoBlending;
|
||||
|
||||
// metalnessOn material
|
||||
|
||||
this.metalnessOnMaterial = new MeshBasicMaterial( {
|
||||
color: 'white'
|
||||
} );
|
||||
|
||||
// metalnessOff material
|
||||
|
||||
this.metalnessOffMaterial = new MeshBasicMaterial( {
|
||||
color: 'black'
|
||||
} );
|
||||
|
||||
// blur material
|
||||
|
||||
this.blurMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SSRBlurShader.defines ),
|
||||
uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ),
|
||||
vertexShader: SSRBlurShader.vertexShader,
|
||||
fragmentShader: SSRBlurShader.fragmentShader
|
||||
} );
|
||||
this.blurMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
|
||||
this.blurMaterial.uniforms[ 'resolution' ].value.set( this.width, this.height );
|
||||
|
||||
// blur material 2
|
||||
|
||||
this.blurMaterial2 = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SSRBlurShader.defines ),
|
||||
uniforms: UniformsUtils.clone( SSRBlurShader.uniforms ),
|
||||
vertexShader: SSRBlurShader.vertexShader,
|
||||
fragmentShader: SSRBlurShader.fragmentShader
|
||||
} );
|
||||
this.blurMaterial2.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture;
|
||||
this.blurMaterial2.uniforms[ 'resolution' ].value.set( this.width, this.height );
|
||||
|
||||
// // blur material 3
|
||||
|
||||
// this.blurMaterial3 = new ShaderMaterial({
|
||||
// defines: Object.assign({}, SSRBlurShader.defines),
|
||||
// uniforms: UniformsUtils.clone(SSRBlurShader.uniforms),
|
||||
// vertexShader: SSRBlurShader.vertexShader,
|
||||
// fragmentShader: SSRBlurShader.fragmentShader
|
||||
// });
|
||||
// this.blurMaterial3.uniforms['tDiffuse'].value = this.blurRenderTarget2.texture;
|
||||
// this.blurMaterial3.uniforms['resolution'].value.set(this.width, this.height);
|
||||
|
||||
// material for rendering the depth
|
||||
|
||||
this.depthRenderMaterial = new ShaderMaterial( {
|
||||
defines: Object.assign( {}, SSRDepthShader.defines ),
|
||||
uniforms: UniformsUtils.clone( SSRDepthShader.uniforms ),
|
||||
vertexShader: SSRDepthShader.vertexShader,
|
||||
fragmentShader: SSRDepthShader.fragmentShader,
|
||||
blending: NoBlending
|
||||
} );
|
||||
this.depthRenderMaterial.uniforms[ 'tDepth' ].value = this.beautyRenderTarget.depthTexture;
|
||||
this.depthRenderMaterial.uniforms[ 'cameraNear' ].value = this.camera.near;
|
||||
this.depthRenderMaterial.uniforms[ 'cameraFar' ].value = this.camera.far;
|
||||
|
||||
// material for rendering the content of a render target
|
||||
|
||||
this.copyMaterial = new ShaderMaterial( {
|
||||
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
transparent: true,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
blendSrc: SrcAlphaFactor,
|
||||
blendDst: OneMinusSrcAlphaFactor,
|
||||
blendEquation: AddEquation,
|
||||
blendSrcAlpha: SrcAlphaFactor,
|
||||
blendDstAlpha: OneMinusSrcAlphaFactor,
|
||||
blendEquationAlpha: AddEquation,
|
||||
// premultipliedAlpha:true,
|
||||
} );
|
||||
|
||||
this.fsQuad = new FullScreenQuad( null );
|
||||
|
||||
this.originalClearColor = new Color();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The resolution scale. Valid values are in the range
|
||||
* `[0,1]`. `1` means best quality but also results in
|
||||
* more computational overhead. Setting to `0.5` means
|
||||
* the effect is computed in half-resolution.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
get resolutionScale() {
|
||||
|
||||
return this._resolutionScale;
|
||||
|
||||
}
|
||||
|
||||
set resolutionScale( value ) {
|
||||
|
||||
this._resolutionScale = value;
|
||||
this.setSize( this.width, this.height ); // force a resize when resolution scaling changes
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
// dispose render targets
|
||||
|
||||
this.beautyRenderTarget.dispose();
|
||||
this.prevRenderTarget.dispose();
|
||||
this.normalRenderTarget.dispose();
|
||||
this.metalnessRenderTarget.dispose();
|
||||
this.ssrRenderTarget.dispose();
|
||||
this.blurRenderTarget.dispose();
|
||||
this.blurRenderTarget2.dispose();
|
||||
// this.blurRenderTarget3.dispose();
|
||||
|
||||
// dispose materials
|
||||
|
||||
this.normalMaterial.dispose();
|
||||
this.metalnessOnMaterial.dispose();
|
||||
this.metalnessOffMaterial.dispose();
|
||||
this.blurMaterial.dispose();
|
||||
this.blurMaterial2.dispose();
|
||||
this.copyMaterial.dispose();
|
||||
this.depthRenderMaterial.dispose();
|
||||
|
||||
// dispose full screen quad
|
||||
|
||||
this.fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the SSR 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 */ ) {
|
||||
|
||||
// render beauty and depth
|
||||
|
||||
renderer.setRenderTarget( this.beautyRenderTarget );
|
||||
renderer.clear();
|
||||
if ( this.groundReflector ) {
|
||||
|
||||
this.groundReflector.visible = false;
|
||||
this.groundReflector.doRender( this.renderer, this.scene, this.camera );
|
||||
this.groundReflector.visible = true;
|
||||
|
||||
}
|
||||
|
||||
renderer.render( this.scene, this.camera );
|
||||
if ( this.groundReflector ) this.groundReflector.visible = false;
|
||||
|
||||
// render normals
|
||||
|
||||
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 );
|
||||
|
||||
// render metalnesses
|
||||
|
||||
if ( this.selective ) {
|
||||
|
||||
this._renderMetalness( renderer, this.metalnessOnMaterial, this.metalnessRenderTarget, 0, 0 );
|
||||
|
||||
}
|
||||
|
||||
// render SSR
|
||||
|
||||
this.ssrMaterial.uniforms[ 'opacity' ].value = this.opacity;
|
||||
this.ssrMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
|
||||
this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
|
||||
this._renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget );
|
||||
|
||||
|
||||
// render blur
|
||||
|
||||
if ( this.blur ) {
|
||||
|
||||
this._renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
|
||||
this._renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 );
|
||||
// this._renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3);
|
||||
|
||||
}
|
||||
|
||||
// output result to screen
|
||||
|
||||
switch ( this.output ) {
|
||||
|
||||
case SSRPass.OUTPUT.Default:
|
||||
|
||||
if ( this.bouncing ) {
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
|
||||
|
||||
if ( this.blur )
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
|
||||
else
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
|
||||
this.copyMaterial.blending = NormalBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
} else {
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
if ( this.blur )
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
|
||||
else
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
|
||||
this.copyMaterial.blending = NormalBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case SSRPass.OUTPUT.SSR:
|
||||
|
||||
if ( this.blur )
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
|
||||
else
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
if ( this.bouncing ) {
|
||||
|
||||
if ( this.blur )
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget2.texture;
|
||||
else
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
|
||||
this.copyMaterial.blending = NormalBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SSRPass.OUTPUT.Beauty:
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.beautyRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case SSRPass.OUTPUT.Depth:
|
||||
|
||||
this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case SSRPass.OUTPUT.Normal:
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.normalRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
case SSRPass.OUTPUT.Metalness:
|
||||
|
||||
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.metalnessRenderTarget.texture;
|
||||
this.copyMaterial.blending = NoBlending;
|
||||
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn( 'THREE.SSRPass: Unknown output type.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
const effectiveWidth = Math.round( this.resolutionScale * width );
|
||||
const effectiveHeight = Math.round( this.resolutionScale * height );
|
||||
|
||||
this.ssrMaterial.defines.MAX_STEP = Math.sqrt( effectiveWidth * effectiveWidth + effectiveHeight * effectiveHeight );
|
||||
this.ssrMaterial.needsUpdate = true;
|
||||
|
||||
this.beautyRenderTarget.setSize( width, height );
|
||||
this.normalRenderTarget.setSize( width, height );
|
||||
this.metalnessRenderTarget.setSize( width, height );
|
||||
this.ssrRenderTarget.setSize( effectiveWidth, effectiveHeight );
|
||||
this.prevRenderTarget.setSize( effectiveWidth, effectiveHeight );
|
||||
this.blurRenderTarget.setSize( effectiveWidth, effectiveHeight );
|
||||
this.blurRenderTarget2.setSize( effectiveWidth, effectiveHeight );
|
||||
// this.blurRenderTarget3.setSize(width, height);
|
||||
|
||||
this.ssrMaterial.uniforms[ 'resolution' ].value.set( effectiveWidth, effectiveHeight );
|
||||
this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
|
||||
this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
|
||||
|
||||
this.blurMaterial.uniforms[ 'resolution' ].value.set( effectiveWidth, effectiveHeight );
|
||||
this.blurMaterial2.uniforms[ 'resolution' ].value.set( effectiveWidth, effectiveHeight );
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
// save original state
|
||||
this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
|
||||
const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
|
||||
// setup pass state
|
||||
renderer.autoClear = false;
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this.fsQuad.material = passMaterial;
|
||||
this.fsQuad.render( renderer );
|
||||
|
||||
// restore original state
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this.originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
|
||||
const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.autoClear = false;
|
||||
|
||||
clearColor = overrideMaterial.clearColor || clearColor;
|
||||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
|
||||
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this.scene.overrideMaterial = overrideMaterial;
|
||||
renderer.render( this.scene, this.camera );
|
||||
this.scene.overrideMaterial = null;
|
||||
|
||||
// restore original state
|
||||
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this.originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
_renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
|
||||
|
||||
this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );
|
||||
const originalClearAlpha = renderer.getClearAlpha( this.tempColor );
|
||||
const originalAutoClear = renderer.autoClear;
|
||||
const originalBackground = this.scene.background;
|
||||
const originalFog = this.scene.fog;
|
||||
|
||||
renderer.setRenderTarget( renderTarget );
|
||||
renderer.autoClear = false;
|
||||
this.scene.background = null;
|
||||
this.scene.fog = null;
|
||||
|
||||
clearColor = overrideMaterial.clearColor || clearColor;
|
||||
clearAlpha = overrideMaterial.clearAlpha || clearAlpha;
|
||||
|
||||
if ( ( clearColor !== undefined ) && ( clearColor !== null ) ) {
|
||||
|
||||
renderer.setClearColor( clearColor );
|
||||
renderer.setClearAlpha( clearAlpha || 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this.scene.traverseVisible( child => {
|
||||
|
||||
child._SSRPassBackupMaterial = child.material;
|
||||
if ( this._selects.includes( child ) ) {
|
||||
|
||||
child.material = this.metalnessOnMaterial;
|
||||
|
||||
} else {
|
||||
|
||||
child.material = this.metalnessOffMaterial;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
renderer.render( this.scene, this.camera );
|
||||
this.scene.traverseVisible( child => {
|
||||
|
||||
child.material = child._SSRPassBackupMaterial;
|
||||
|
||||
} );
|
||||
|
||||
// restore original state
|
||||
|
||||
renderer.autoClear = originalAutoClear;
|
||||
renderer.setClearColor( this.originalClearColor );
|
||||
renderer.setClearAlpha( originalClearAlpha );
|
||||
this.scene.background = originalBackground;
|
||||
this.scene.fog = originalFog;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor options of `SSRPass`.
|
||||
*
|
||||
* @typedef {Object} SSRPass~Options
|
||||
* @property {WebGLRenderer} renderer - The renderer.
|
||||
* @property {Scene} scene - The scene to render.
|
||||
* @property {Camera} camera - The camera.
|
||||
* @property {number} [width=512] - The width of the effect.
|
||||
* @property {number} [height=512] - The width of the effect.
|
||||
* @property {?Array<Object3D>} [selects=null] - Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
|
||||
* @property {boolean} [bouncing=false] - Whether bouncing is enabled or not.
|
||||
* @property {?ReflectorForSSRPass} [groundReflector=null] - A ground reflector.
|
||||
**/
|
||||
|
||||
SSRPass.OUTPUT = {
|
||||
'Default': 0,
|
||||
'SSR': 1,
|
||||
'Beauty': 3,
|
||||
'Depth': 4,
|
||||
'Normal': 5,
|
||||
'Metalness': 7,
|
||||
};
|
||||
|
||||
export { SSRPass };
|
||||
132
node_modules/three/examples/jsm/postprocessing/SavePass.js
generated
vendored
Normal file
132
node_modules/three/examples/jsm/postprocessing/SavePass.js
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
import {
|
||||
HalfFloatType,
|
||||
NoBlending,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
|
||||
/**
|
||||
* A pass that saves the contents of the current read buffer in a render target.
|
||||
*
|
||||
* ```js
|
||||
* const savePass = new SavePass( customRenderTarget );
|
||||
* composer.addPass( savePass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { SavePass } from 'three/addons/postprocessing/SavePass.js';
|
||||
*/
|
||||
class SavePass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new save pass.
|
||||
*
|
||||
* @param {WebGLRenderTarget} [renderTarget] - The render target for saving the read buffer.
|
||||
* If not provided, the pass automatically creates a render target.
|
||||
*/
|
||||
constructor( renderTarget ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The pass uniforms.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = UniformsUtils.clone( CopyShader.uniforms );
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.material = new ShaderMaterial( {
|
||||
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
blending: NoBlending
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* The render target which is used to save the read buffer.
|
||||
*
|
||||
* @type {WebGLRenderTarget}
|
||||
*/
|
||||
this.renderTarget = renderTarget;
|
||||
|
||||
if ( this.renderTarget === undefined ) {
|
||||
|
||||
this.renderTarget = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
|
||||
this.renderTarget.texture.name = 'SavePass.rt';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the save 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[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
|
||||
renderer.setRenderTarget( this.renderTarget );
|
||||
if ( this.clear ) renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this.renderTarget.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.renderTarget.dispose();
|
||||
|
||||
this.material.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { SavePass };
|
||||
135
node_modules/three/examples/jsm/postprocessing/ShaderPass.js
generated
vendored
Normal file
135
node_modules/three/examples/jsm/postprocessing/ShaderPass.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
import {
|
||||
ShaderMaterial,
|
||||
UniformsUtils
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
|
||||
/**
|
||||
* This pass can be used to create a post processing effect
|
||||
* with a raw GLSL shader object. Useful for implementing custom
|
||||
* effects.
|
||||
*
|
||||
* ```js
|
||||
* const fxaaPass = new ShaderPass( FXAAShader );
|
||||
* composer.addPass( fxaaPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
|
||||
*/
|
||||
class ShaderPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new shader pass.
|
||||
*
|
||||
* @param {Object|ShaderMaterial} [shader] - A shader object holding vertex and fragment shader as well as
|
||||
* defines and uniforms. It's also valid to pass a custom shader material.
|
||||
* @param {string} [textureID='tDiffuse'] - The name of the texture uniform that should sample
|
||||
* the read buffer.
|
||||
*/
|
||||
constructor( shader, textureID = 'tDiffuse' ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The name of the texture uniform that should sample the read buffer.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'tDiffuse'
|
||||
*/
|
||||
this.textureID = textureID;
|
||||
|
||||
/**
|
||||
* The pass uniforms.
|
||||
*
|
||||
* @type {?Object}
|
||||
*/
|
||||
this.uniforms = null;
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {?ShaderMaterial}
|
||||
*/
|
||||
this.material = null;
|
||||
|
||||
if ( shader instanceof ShaderMaterial ) {
|
||||
|
||||
this.uniforms = shader.uniforms;
|
||||
|
||||
this.material = shader;
|
||||
|
||||
} else if ( shader ) {
|
||||
|
||||
this.uniforms = UniformsUtils.clone( shader.uniforms );
|
||||
|
||||
this.material = new ShaderMaterial( {
|
||||
|
||||
name: ( shader.name !== undefined ) ? shader.name : 'unspecified',
|
||||
defines: Object.assign( {}, shader.defines ),
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( this.material );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the shader 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 ( this.uniforms[ this.textureID ] ) {
|
||||
|
||||
this.uniforms[ this.textureID ].value = readBuffer.texture;
|
||||
|
||||
}
|
||||
|
||||
this._fsQuad.material = this.material;
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
// TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
|
||||
if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.material.dispose();
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { ShaderPass };
|
||||
243
node_modules/three/examples/jsm/postprocessing/TAARenderPass.js
generated
vendored
Normal file
243
node_modules/three/examples/jsm/postprocessing/TAARenderPass.js
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
import {
|
||||
HalfFloatType,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { SSAARenderPass } from './SSAARenderPass.js';
|
||||
|
||||
/**
|
||||
*
|
||||
* Temporal Anti-Aliasing Render Pass.
|
||||
*
|
||||
* When there is no motion in the scene, the TAA render pass accumulates jittered camera
|
||||
* samples across frames to create a high quality anti-aliased result.
|
||||
*
|
||||
* Note: This effect uses no reprojection so it is no TRAA implementation.
|
||||
*
|
||||
* ```js
|
||||
* const taaRenderPass = new TAARenderPass( scene, camera );
|
||||
* taaRenderPass.unbiased = false;
|
||||
* composer.addPass( taaRenderPass );
|
||||
* ```
|
||||
*
|
||||
* @augments SSAARenderPass
|
||||
* @three_import import { TAARenderPass } from 'three/addons/postprocessing/TAARenderPass.js';
|
||||
*/
|
||||
class TAARenderPass extends SSAARenderPass {
|
||||
|
||||
/**
|
||||
* Constructs a new TAA render pass.
|
||||
*
|
||||
* @param {Scene} scene - The scene to render.
|
||||
* @param {Camera} camera - The camera.
|
||||
* @param {?(number|Color|string)} [clearColor=0x000000] - The clear color of the render pass.
|
||||
* @param {?number} [clearAlpha=0] - The clear alpha of the render pass.
|
||||
*/
|
||||
constructor( scene, camera, clearColor, clearAlpha ) {
|
||||
|
||||
super( scene, camera, clearColor, clearAlpha );
|
||||
|
||||
/**
|
||||
* Overwritten and set to 0 by default.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.sampleLevel = 0;
|
||||
|
||||
/**
|
||||
* Whether to accumulate frames or not. This enables
|
||||
* the TAA.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.accumulate = false;
|
||||
|
||||
/**
|
||||
* The accumulation index.
|
||||
*
|
||||
* @type {number}
|
||||
* @default -1
|
||||
*/
|
||||
this.accumulateIndex = - 1;
|
||||
|
||||
// internals
|
||||
|
||||
this._sampleRenderTarget = null;
|
||||
this._holdRenderTarget = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the TAA render 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 ( this.accumulate === false ) {
|
||||
|
||||
super.render( renderer, writeBuffer, readBuffer, deltaTime );
|
||||
|
||||
this.accumulateIndex = - 1;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
const jitterOffsets = _JitterVectors[ 5 ];
|
||||
|
||||
if ( this._sampleRenderTarget === null ) {
|
||||
|
||||
this._sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } );
|
||||
this._sampleRenderTarget.texture.name = 'TAARenderPass.sample';
|
||||
|
||||
}
|
||||
|
||||
if ( this._holdRenderTarget === null ) {
|
||||
|
||||
this._holdRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } );
|
||||
this._holdRenderTarget.texture.name = 'TAARenderPass.hold';
|
||||
|
||||
}
|
||||
|
||||
if ( this.accumulateIndex === - 1 ) {
|
||||
|
||||
super.render( renderer, this._holdRenderTarget, readBuffer, deltaTime );
|
||||
|
||||
this.accumulateIndex = 0;
|
||||
|
||||
}
|
||||
|
||||
const autoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
const oldClearAlpha = renderer.getClearAlpha();
|
||||
|
||||
const sampleWeight = 1.0 / ( jitterOffsets.length );
|
||||
|
||||
if ( this.accumulateIndex >= 0 && this.accumulateIndex < jitterOffsets.length ) {
|
||||
|
||||
this._copyUniforms[ 'opacity' ].value = sampleWeight;
|
||||
this._copyUniforms[ 'tDiffuse' ].value = writeBuffer.texture;
|
||||
|
||||
// render the scene multiple times, each slightly jitter offset from the last and accumulate the results.
|
||||
const numSamplesPerFrame = Math.pow( 2, this.sampleLevel );
|
||||
for ( let i = 0; i < numSamplesPerFrame; i ++ ) {
|
||||
|
||||
const j = this.accumulateIndex;
|
||||
const jitterOffset = jitterOffsets[ j ];
|
||||
|
||||
if ( this.camera.setViewOffset ) {
|
||||
|
||||
this.camera.setViewOffset( readBuffer.width, readBuffer.height,
|
||||
jitterOffset[ 0 ] * 0.0625, jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16
|
||||
readBuffer.width, readBuffer.height );
|
||||
|
||||
}
|
||||
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
renderer.setClearColor( this.clearColor, this.clearAlpha );
|
||||
renderer.clear();
|
||||
renderer.render( this.scene, this.camera );
|
||||
|
||||
renderer.setRenderTarget( this._sampleRenderTarget );
|
||||
if ( this.accumulateIndex === 0 ) {
|
||||
|
||||
renderer.setClearColor( 0x000000, 0.0 );
|
||||
renderer.clear();
|
||||
|
||||
}
|
||||
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
this.accumulateIndex ++;
|
||||
|
||||
if ( this.accumulateIndex >= jitterOffsets.length ) break;
|
||||
|
||||
}
|
||||
|
||||
if ( this.camera.clearViewOffset ) this.camera.clearViewOffset();
|
||||
|
||||
}
|
||||
|
||||
renderer.setClearColor( this.clearColor, this.clearAlpha );
|
||||
const accumulationWeight = this.accumulateIndex * sampleWeight;
|
||||
|
||||
if ( accumulationWeight > 0 ) {
|
||||
|
||||
this._copyUniforms[ 'opacity' ].value = 1.0;
|
||||
this._copyUniforms[ 'tDiffuse' ].value = this._sampleRenderTarget.texture;
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
if ( accumulationWeight < 1.0 ) {
|
||||
|
||||
this._copyUniforms[ 'opacity' ].value = 1.0 - accumulationWeight;
|
||||
this._copyUniforms[ 'tDiffuse' ].value = this._holdRenderTarget.texture;
|
||||
renderer.setRenderTarget( writeBuffer );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
renderer.autoClear = autoClear;
|
||||
renderer.setClearColor( this._oldClearColor, oldClearAlpha );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
super.dispose();
|
||||
|
||||
if ( this._holdRenderTarget ) this._holdRenderTarget.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const _JitterVectors = [
|
||||
[
|
||||
[ 0, 0 ]
|
||||
],
|
||||
[
|
||||
[ 4, 4 ], [ - 4, - 4 ]
|
||||
],
|
||||
[
|
||||
[ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]
|
||||
],
|
||||
[
|
||||
[ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ],
|
||||
[ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]
|
||||
],
|
||||
[
|
||||
[ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ],
|
||||
[ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ],
|
||||
[ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ],
|
||||
[ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]
|
||||
],
|
||||
[
|
||||
[ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ],
|
||||
[ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ],
|
||||
[ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ],
|
||||
[ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ],
|
||||
[ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ],
|
||||
[ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ],
|
||||
[ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ],
|
||||
[ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]
|
||||
]
|
||||
];
|
||||
|
||||
export { TAARenderPass };
|
||||
131
node_modules/three/examples/jsm/postprocessing/TexturePass.js
generated
vendored
Normal file
131
node_modules/three/examples/jsm/postprocessing/TexturePass.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
import {
|
||||
ShaderMaterial,
|
||||
UniformsUtils
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
|
||||
/**
|
||||
* This pass can be used to render a texture over the entire screen.
|
||||
*
|
||||
* ```js
|
||||
* const texture = new THREE.TextureLoader().load( 'textures/2294472375_24a3b8ef46_o.jpg' );
|
||||
* texture.colorSpace = THREE.SRGBColorSpace;
|
||||
*
|
||||
* const texturePass = new TexturePass( texture );
|
||||
* composer.addPass( texturePass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { TexturePass } from 'three/addons/postprocessing/TexturePass.js';
|
||||
*/
|
||||
class TexturePass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new texture pass.
|
||||
*
|
||||
* @param {Texture} map - The texture to render.
|
||||
* @param {number} [opacity=1] - The opacity.
|
||||
*/
|
||||
constructor( map, opacity = 1 ) {
|
||||
|
||||
super();
|
||||
|
||||
const shader = CopyShader;
|
||||
|
||||
/**
|
||||
* The texture to render.
|
||||
*
|
||||
* @type {Texture}
|
||||
*/
|
||||
this.map = map;
|
||||
|
||||
/**
|
||||
* The opacity.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.opacity = opacity;
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
/**
|
||||
* The pass uniforms.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.uniforms = UniformsUtils.clone( shader.uniforms );
|
||||
|
||||
/**
|
||||
* The pass material.
|
||||
*
|
||||
* @type {ShaderMaterial}
|
||||
*/
|
||||
this.material = new ShaderMaterial( {
|
||||
|
||||
uniforms: this.uniforms,
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
premultipliedAlpha: true
|
||||
|
||||
} );
|
||||
|
||||
// internals
|
||||
|
||||
this._fsQuad = new FullScreenQuad( null );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the texture 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 */ ) {
|
||||
|
||||
const oldAutoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
this._fsQuad.material = this.material;
|
||||
|
||||
this.uniforms[ 'opacity' ].value = this.opacity;
|
||||
this.uniforms[ 'tDiffuse' ].value = this.map;
|
||||
this.material.transparent = ( this.opacity < 1.0 );
|
||||
|
||||
renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
|
||||
if ( this.clear ) renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
renderer.autoClear = oldAutoClear;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.material.dispose();
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { TexturePass };
|
||||
524
node_modules/three/examples/jsm/postprocessing/UnrealBloomPass.js
generated
vendored
Normal file
524
node_modules/three/examples/jsm/postprocessing/UnrealBloomPass.js
generated
vendored
Normal file
@@ -0,0 +1,524 @@
|
||||
import {
|
||||
AdditiveBlending,
|
||||
Color,
|
||||
HalfFloatType,
|
||||
MeshBasicMaterial,
|
||||
ShaderMaterial,
|
||||
UniformsUtils,
|
||||
Vector2,
|
||||
Vector3,
|
||||
WebGLRenderTarget
|
||||
} from 'three';
|
||||
import { Pass, FullScreenQuad } from './Pass.js';
|
||||
import { CopyShader } from '../shaders/CopyShader.js';
|
||||
import { LuminosityHighPassShader } from '../shaders/LuminosityHighPassShader.js';
|
||||
|
||||
/**
|
||||
* This pass is inspired by the bloom pass of Unreal Engine. It creates a
|
||||
* mip map chain of bloom textures and blurs them with different radii. Because
|
||||
* of the weighted combination of mips, and because larger blurs are done on
|
||||
* higher mips, this effect provides good quality and performance.
|
||||
*
|
||||
* When using this pass, tone mapping must be enabled in the renderer settings.
|
||||
*
|
||||
* Reference:
|
||||
* - [Bloom in Unreal Engine](https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/)
|
||||
*
|
||||
* ```js
|
||||
* const resolution = new THREE.Vector2( window.innerWidth, window.innerHeight );
|
||||
* const bloomPass = new UnrealBloomPass( resolution, 1.5, 0.4, 0.85 );
|
||||
* composer.addPass( bloomPass );
|
||||
* ```
|
||||
*
|
||||
* @augments Pass
|
||||
* @three_import import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
|
||||
*/
|
||||
class UnrealBloomPass extends Pass {
|
||||
|
||||
/**
|
||||
* Constructs a new Unreal Bloom pass.
|
||||
*
|
||||
* @param {Vector2} [resolution] - The effect's resolution.
|
||||
* @param {number} [strength=1] - The Bloom strength.
|
||||
* @param {number} radius - The Bloom radius.
|
||||
* @param {number} threshold - The luminance threshold limits which bright areas contribute to the Bloom effect.
|
||||
*/
|
||||
constructor( resolution, strength = 1, radius, threshold ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The Bloom strength.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.strength = strength;
|
||||
|
||||
/**
|
||||
* The Bloom radius. Must be in the range `[0,1]`.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
this.radius = radius;
|
||||
|
||||
/**
|
||||
* The luminance threshold limits which bright areas contribute to the Bloom effect.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
this.threshold = threshold;
|
||||
|
||||
/**
|
||||
* The effect's resolution.
|
||||
*
|
||||
* @type {Vector2}
|
||||
* @default (256,256)
|
||||
*/
|
||||
this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 );
|
||||
|
||||
/**
|
||||
* The effect's clear color
|
||||
*
|
||||
* @type {Color}
|
||||
* @default (0,0,0)
|
||||
*/
|
||||
this.clearColor = new Color( 0, 0, 0 );
|
||||
|
||||
/**
|
||||
* Overwritten to disable the swap.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsSwap = false;
|
||||
|
||||
// internals
|
||||
|
||||
// render targets
|
||||
this.renderTargetsHorizontal = [];
|
||||
this.renderTargetsVertical = [];
|
||||
this.nMips = 5;
|
||||
let resx = Math.round( this.resolution.x / 2 );
|
||||
let resy = Math.round( this.resolution.y / 2 );
|
||||
|
||||
this.renderTargetBright = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
|
||||
this.renderTargetBright.texture.name = 'UnrealBloomPass.bright';
|
||||
this.renderTargetBright.texture.generateMipmaps = false;
|
||||
|
||||
for ( let i = 0; i < this.nMips; i ++ ) {
|
||||
|
||||
const renderTargetHorizontal = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
|
||||
|
||||
renderTargetHorizontal.texture.name = 'UnrealBloomPass.h' + i;
|
||||
renderTargetHorizontal.texture.generateMipmaps = false;
|
||||
|
||||
this.renderTargetsHorizontal.push( renderTargetHorizontal );
|
||||
|
||||
const renderTargetVertical = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );
|
||||
|
||||
renderTargetVertical.texture.name = 'UnrealBloomPass.v' + i;
|
||||
renderTargetVertical.texture.generateMipmaps = false;
|
||||
|
||||
this.renderTargetsVertical.push( renderTargetVertical );
|
||||
|
||||
resx = Math.round( resx / 2 );
|
||||
|
||||
resy = Math.round( resy / 2 );
|
||||
|
||||
}
|
||||
|
||||
// luminosity high pass material
|
||||
|
||||
const highPassShader = LuminosityHighPassShader;
|
||||
this.highPassUniforms = UniformsUtils.clone( highPassShader.uniforms );
|
||||
|
||||
this.highPassUniforms[ 'luminosityThreshold' ].value = threshold;
|
||||
this.highPassUniforms[ 'smoothWidth' ].value = 0.01;
|
||||
|
||||
this.materialHighPassFilter = new ShaderMaterial( {
|
||||
uniforms: this.highPassUniforms,
|
||||
vertexShader: highPassShader.vertexShader,
|
||||
fragmentShader: highPassShader.fragmentShader
|
||||
} );
|
||||
|
||||
// gaussian blur materials
|
||||
|
||||
this.separableBlurMaterials = [];
|
||||
// These sizes have been changed to account for the altered coefficients-calculation to avoid blockiness,
|
||||
// while retaining the same blur-strength. For details see https://github.com/mrdoob/three.js/pull/31528
|
||||
const kernelSizeArray = [ 6, 10, 14, 18, 22 ];
|
||||
resx = Math.round( this.resolution.x / 2 );
|
||||
resy = Math.round( this.resolution.y / 2 );
|
||||
|
||||
for ( let i = 0; i < this.nMips; i ++ ) {
|
||||
|
||||
this.separableBlurMaterials.push( this._getSeparableBlurMaterial( kernelSizeArray[ i ] ) );
|
||||
|
||||
this.separableBlurMaterials[ i ].uniforms[ 'invSize' ].value = new Vector2( 1 / resx, 1 / resy );
|
||||
|
||||
resx = Math.round( resx / 2 );
|
||||
|
||||
resy = Math.round( resy / 2 );
|
||||
|
||||
}
|
||||
|
||||
// composite material
|
||||
|
||||
this.compositeMaterial = this._getCompositeMaterial( this.nMips );
|
||||
this.compositeMaterial.uniforms[ 'blurTexture1' ].value = this.renderTargetsVertical[ 0 ].texture;
|
||||
this.compositeMaterial.uniforms[ 'blurTexture2' ].value = this.renderTargetsVertical[ 1 ].texture;
|
||||
this.compositeMaterial.uniforms[ 'blurTexture3' ].value = this.renderTargetsVertical[ 2 ].texture;
|
||||
this.compositeMaterial.uniforms[ 'blurTexture4' ].value = this.renderTargetsVertical[ 3 ].texture;
|
||||
this.compositeMaterial.uniforms[ 'blurTexture5' ].value = this.renderTargetsVertical[ 4 ].texture;
|
||||
this.compositeMaterial.uniforms[ 'bloomStrength' ].value = strength;
|
||||
this.compositeMaterial.uniforms[ 'bloomRadius' ].value = 0.1;
|
||||
|
||||
const bloomFactors = [ 1.0, 0.8, 0.6, 0.4, 0.2 ];
|
||||
this.compositeMaterial.uniforms[ 'bloomFactors' ].value = bloomFactors;
|
||||
this.bloomTintColors = [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ];
|
||||
this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors;
|
||||
|
||||
// blend material
|
||||
|
||||
this.copyUniforms = UniformsUtils.clone( CopyShader.uniforms );
|
||||
|
||||
this.blendMaterial = new ShaderMaterial( {
|
||||
uniforms: this.copyUniforms,
|
||||
vertexShader: CopyShader.vertexShader,
|
||||
fragmentShader: CopyShader.fragmentShader,
|
||||
premultipliedAlpha: true,
|
||||
blending: AdditiveBlending,
|
||||
depthTest: false,
|
||||
depthWrite: false,
|
||||
transparent: true
|
||||
} );
|
||||
|
||||
this._oldClearColor = new Color();
|
||||
this._oldClearAlpha = 1;
|
||||
|
||||
this._basic = new MeshBasicMaterial();
|
||||
|
||||
this._fsQuad = new FullScreenQuad( null );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the GPU-related resources allocated by this instance. Call this
|
||||
* method whenever the pass is no longer used in your app.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
for ( let i = 0; i < this.renderTargetsHorizontal.length; i ++ ) {
|
||||
|
||||
this.renderTargetsHorizontal[ i ].dispose();
|
||||
|
||||
}
|
||||
|
||||
for ( let i = 0; i < this.renderTargetsVertical.length; i ++ ) {
|
||||
|
||||
this.renderTargetsVertical[ i ].dispose();
|
||||
|
||||
}
|
||||
|
||||
this.renderTargetBright.dispose();
|
||||
|
||||
//
|
||||
|
||||
for ( let i = 0; i < this.separableBlurMaterials.length; i ++ ) {
|
||||
|
||||
this.separableBlurMaterials[ i ].dispose();
|
||||
|
||||
}
|
||||
|
||||
this.compositeMaterial.dispose();
|
||||
this.blendMaterial.dispose();
|
||||
this._basic.dispose();
|
||||
|
||||
//
|
||||
|
||||
this._fsQuad.dispose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
let resx = Math.round( width / 2 );
|
||||
let resy = Math.round( height / 2 );
|
||||
|
||||
this.renderTargetBright.setSize( resx, resy );
|
||||
|
||||
for ( let i = 0; i < this.nMips; i ++ ) {
|
||||
|
||||
this.renderTargetsHorizontal[ i ].setSize( resx, resy );
|
||||
this.renderTargetsVertical[ i ].setSize( resx, resy );
|
||||
|
||||
this.separableBlurMaterials[ i ].uniforms[ 'invSize' ].value = new Vector2( 1 / resx, 1 / resy );
|
||||
|
||||
resx = Math.round( resx / 2 );
|
||||
resy = Math.round( resy / 2 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ) {
|
||||
|
||||
renderer.getClearColor( this._oldClearColor );
|
||||
this._oldClearAlpha = renderer.getClearAlpha();
|
||||
const oldAutoClear = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
|
||||
renderer.setClearColor( this.clearColor, 0 );
|
||||
|
||||
if ( maskActive ) renderer.state.buffers.stencil.setTest( false );
|
||||
|
||||
// Render input to screen
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
this._fsQuad.material = this._basic;
|
||||
this._basic.map = readBuffer.texture;
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
// 1. Extract Bright Areas
|
||||
|
||||
this.highPassUniforms[ 'tDiffuse' ].value = readBuffer.texture;
|
||||
this.highPassUniforms[ 'luminosityThreshold' ].value = this.threshold;
|
||||
this._fsQuad.material = this.materialHighPassFilter;
|
||||
|
||||
renderer.setRenderTarget( this.renderTargetBright );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// 2. Blur All the mips progressively
|
||||
|
||||
let inputRenderTarget = this.renderTargetBright;
|
||||
|
||||
for ( let i = 0; i < this.nMips; i ++ ) {
|
||||
|
||||
this._fsQuad.material = this.separableBlurMaterials[ i ];
|
||||
|
||||
this.separableBlurMaterials[ i ].uniforms[ 'colorTexture' ].value = inputRenderTarget.texture;
|
||||
this.separableBlurMaterials[ i ].uniforms[ 'direction' ].value = UnrealBloomPass.BlurDirectionX;
|
||||
renderer.setRenderTarget( this.renderTargetsHorizontal[ i ] );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
this.separableBlurMaterials[ i ].uniforms[ 'colorTexture' ].value = this.renderTargetsHorizontal[ i ].texture;
|
||||
this.separableBlurMaterials[ i ].uniforms[ 'direction' ].value = UnrealBloomPass.BlurDirectionY;
|
||||
renderer.setRenderTarget( this.renderTargetsVertical[ i ] );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
inputRenderTarget = this.renderTargetsVertical[ i ];
|
||||
|
||||
}
|
||||
|
||||
// Composite All the mips
|
||||
|
||||
this._fsQuad.material = this.compositeMaterial;
|
||||
this.compositeMaterial.uniforms[ 'bloomStrength' ].value = this.strength;
|
||||
this.compositeMaterial.uniforms[ 'bloomRadius' ].value = this.radius;
|
||||
this.compositeMaterial.uniforms[ 'bloomTintColors' ].value = this.bloomTintColors;
|
||||
|
||||
renderer.setRenderTarget( this.renderTargetsHorizontal[ 0 ] );
|
||||
renderer.clear();
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
// Blend it additively over the input texture
|
||||
|
||||
this._fsQuad.material = this.blendMaterial;
|
||||
this.copyUniforms[ 'tDiffuse' ].value = this.renderTargetsHorizontal[ 0 ].texture;
|
||||
|
||||
if ( maskActive ) renderer.state.buffers.stencil.setTest( true );
|
||||
|
||||
if ( this.renderToScreen ) {
|
||||
|
||||
renderer.setRenderTarget( null );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.setRenderTarget( readBuffer );
|
||||
this._fsQuad.render( renderer );
|
||||
|
||||
}
|
||||
|
||||
// Restore renderer settings
|
||||
|
||||
renderer.setClearColor( this._oldClearColor, this._oldClearAlpha );
|
||||
renderer.autoClear = oldAutoClear;
|
||||
|
||||
}
|
||||
|
||||
// internals
|
||||
|
||||
_getSeparableBlurMaterial( kernelRadius ) {
|
||||
|
||||
const coefficients = [];
|
||||
const sigma = kernelRadius / 3;
|
||||
|
||||
for ( let i = 0; i < kernelRadius; i ++ ) {
|
||||
|
||||
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( sigma * sigma ) ) / sigma );
|
||||
|
||||
}
|
||||
|
||||
return new ShaderMaterial( {
|
||||
|
||||
defines: {
|
||||
'KERNEL_RADIUS': kernelRadius
|
||||
},
|
||||
|
||||
uniforms: {
|
||||
'colorTexture': { value: null },
|
||||
'invSize': { value: new Vector2( 0.5, 0.5 ) }, // inverse texture size
|
||||
'direction': { value: new Vector2( 0.5, 0.5 ) },
|
||||
'gaussianCoefficients': { value: coefficients } // precomputed Gaussian coefficients
|
||||
},
|
||||
|
||||
vertexShader: /* glsl */`
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}`,
|
||||
|
||||
fragmentShader: /* glsl */`
|
||||
|
||||
#include <common>
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
uniform sampler2D colorTexture;
|
||||
uniform vec2 invSize;
|
||||
uniform vec2 direction;
|
||||
uniform float gaussianCoefficients[KERNEL_RADIUS];
|
||||
|
||||
void main() {
|
||||
|
||||
float weightSum = gaussianCoefficients[0];
|
||||
vec3 diffuseSum = texture2D( colorTexture, vUv ).rgb * weightSum;
|
||||
|
||||
for ( int i = 1; i < KERNEL_RADIUS; i ++ ) {
|
||||
|
||||
float x = float( i );
|
||||
float w = gaussianCoefficients[i];
|
||||
vec2 uvOffset = direction * invSize * x;
|
||||
vec3 sample1 = texture2D( colorTexture, vUv + uvOffset ).rgb;
|
||||
vec3 sample2 = texture2D( colorTexture, vUv - uvOffset ).rgb;
|
||||
diffuseSum += ( sample1 + sample2 ) * w;
|
||||
|
||||
}
|
||||
|
||||
gl_FragColor = vec4( diffuseSum, 1.0 );
|
||||
|
||||
}`
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
_getCompositeMaterial( nMips ) {
|
||||
|
||||
return new ShaderMaterial( {
|
||||
|
||||
defines: {
|
||||
'NUM_MIPS': nMips
|
||||
},
|
||||
|
||||
uniforms: {
|
||||
'blurTexture1': { value: null },
|
||||
'blurTexture2': { value: null },
|
||||
'blurTexture3': { value: null },
|
||||
'blurTexture4': { value: null },
|
||||
'blurTexture5': { value: null },
|
||||
'bloomStrength': { value: 1.0 },
|
||||
'bloomFactors': { value: null },
|
||||
'bloomTintColors': { value: null },
|
||||
'bloomRadius': { value: 0.0 }
|
||||
},
|
||||
|
||||
vertexShader: /* glsl */`
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||
|
||||
}`,
|
||||
|
||||
fragmentShader: /* glsl */`
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
uniform sampler2D blurTexture1;
|
||||
uniform sampler2D blurTexture2;
|
||||
uniform sampler2D blurTexture3;
|
||||
uniform sampler2D blurTexture4;
|
||||
uniform sampler2D blurTexture5;
|
||||
uniform float bloomStrength;
|
||||
uniform float bloomRadius;
|
||||
uniform float bloomFactors[NUM_MIPS];
|
||||
uniform vec3 bloomTintColors[NUM_MIPS];
|
||||
|
||||
float lerpBloomFactor( const in float factor ) {
|
||||
|
||||
float mirrorFactor = 1.2 - factor;
|
||||
return mix( factor, mirrorFactor, bloomRadius );
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
// 3.0 for backwards compatibility with previous alpha-based intensity
|
||||
vec3 bloom = 3.0 * bloomStrength * (
|
||||
lerpBloomFactor( bloomFactors[ 0 ] ) * bloomTintColors[ 0 ] * texture2D( blurTexture1, vUv ).rgb +
|
||||
lerpBloomFactor( bloomFactors[ 1 ] ) * bloomTintColors[ 1 ] * texture2D( blurTexture2, vUv ).rgb +
|
||||
lerpBloomFactor( bloomFactors[ 2 ] ) * bloomTintColors[ 2 ] * texture2D( blurTexture3, vUv ).rgb +
|
||||
lerpBloomFactor( bloomFactors[ 3 ] ) * bloomTintColors[ 3 ] * texture2D( blurTexture4, vUv ).rgb +
|
||||
lerpBloomFactor( bloomFactors[ 4 ] ) * bloomTintColors[ 4 ] * texture2D( blurTexture5, vUv ).rgb
|
||||
);
|
||||
|
||||
float bloomAlpha = max( bloom.r, max( bloom.g, bloom.b ) );
|
||||
gl_FragColor = vec4( bloom, bloomAlpha );
|
||||
|
||||
}`
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UnrealBloomPass.BlurDirectionX = new Vector2( 1.0, 0.0 );
|
||||
UnrealBloomPass.BlurDirectionY = new Vector2( 0.0, 1.0 );
|
||||
|
||||
export { UnrealBloomPass };
|
||||
Reference in New Issue
Block a user