修改静态资源文件夹位置
This commit is contained in:
		
							
								
								
									
										104
									
								
								public/sdk/three/jsm/postprocessing/AfterimagePass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								public/sdk/three/jsm/postprocessing/AfterimagePass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | ||||
| import { | ||||
| 	HalfFloatType, | ||||
| 	MeshBasicMaterial, | ||||
| 	NearestFilter, | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils, | ||||
| 	WebGLRenderTarget | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { AfterimageShader } from '../shaders/AfterimageShader.js'; | ||||
|  | ||||
| class AfterimagePass extends Pass { | ||||
|  | ||||
| 	constructor( damp = 0.96 ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.shader = AfterimageShader; | ||||
|  | ||||
| 		this.uniforms = UniformsUtils.clone( this.shader.uniforms ); | ||||
|  | ||||
| 		this.uniforms[ 'damp' ].value = damp; | ||||
|  | ||||
| 		this.textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { | ||||
| 			magFilter: NearestFilter, | ||||
| 			type: HalfFloatType | ||||
| 		} ); | ||||
|  | ||||
| 		this.textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, { | ||||
| 			magFilter: NearestFilter, | ||||
| 			type: HalfFloatType | ||||
| 		} ); | ||||
|  | ||||
| 		this.compFsMaterial = new ShaderMaterial( { | ||||
|  | ||||
| 			uniforms: this.uniforms, | ||||
| 			vertexShader: this.shader.vertexShader, | ||||
| 			fragmentShader: this.shader.fragmentShader | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		this.compFsQuad = new FullScreenQuad( this.compFsMaterial ); | ||||
|  | ||||
| 		this.copyFsMaterial = new MeshBasicMaterial(); | ||||
| 		this.copyFsQuad = new FullScreenQuad( this.copyFsMaterial ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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.map = 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. | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( width, height ) { | ||||
|  | ||||
| 		this.textureComp.setSize( width, height ); | ||||
| 		this.textureOld.setSize( width, height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.textureComp.dispose(); | ||||
| 		this.textureOld.dispose(); | ||||
|  | ||||
| 		this.compFsMaterial.dispose(); | ||||
| 		this.copyFsMaterial.dispose(); | ||||
|  | ||||
| 		this.compFsQuad.dispose(); | ||||
| 		this.copyFsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { AfterimagePass }; | ||||
							
								
								
									
										172
									
								
								public/sdk/three/jsm/postprocessing/BloomPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								public/sdk/three/jsm/postprocessing/BloomPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,172 @@ | ||||
| import { | ||||
| 	AdditiveBlending, | ||||
| 	HalfFloatType, | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils, | ||||
| 	Vector2, | ||||
| 	WebGLRenderTarget | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { ConvolutionShader } from '../shaders/ConvolutionShader.js'; | ||||
|  | ||||
| class BloomPass extends Pass { | ||||
|  | ||||
| 	constructor( strength = 1, kernelSize = 25, sigma = 4 ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		// render targets | ||||
|  | ||||
| 		this.renderTargetX = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later | ||||
| 		this.renderTargetX.texture.name = 'BloomPass.x'; | ||||
| 		this.renderTargetY = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later | ||||
| 		this.renderTargetY.texture.name = 'BloomPass.y'; | ||||
|  | ||||
| 		// combine material | ||||
|  | ||||
| 		this.combineUniforms = UniformsUtils.clone( CombineShader.uniforms ); | ||||
|  | ||||
| 		this.combineUniforms[ 'strength' ].value = strength; | ||||
|  | ||||
| 		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; | ||||
|  | ||||
| 		this.convolutionUniforms = UniformsUtils.clone( convolutionShader.uniforms ); | ||||
|  | ||||
| 		this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX; | ||||
| 		this.convolutionUniforms[ 'cKernel' ].value = ConvolutionShader.buildKernel( sigma ); | ||||
|  | ||||
| 		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 ) | ||||
| 			} | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( null ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) { | ||||
|  | ||||
| 		if ( maskActive ) renderer.state.buffers.stencil.setTest( false ); | ||||
|  | ||||
| 		// Render quad with blured 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 blured 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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( width, height ) { | ||||
|  | ||||
| 		this.renderTargetX.setSize( width, height ); | ||||
| 		this.renderTargetY.setSize( width, height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| export { BloomPass }; | ||||
							
								
								
									
										141
									
								
								public/sdk/three/jsm/postprocessing/BokehPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								public/sdk/three/jsm/postprocessing/BokehPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | ||||
| import { | ||||
| 	Color, | ||||
| 	HalfFloatType, | ||||
| 	MeshDepthMaterial, | ||||
| 	NearestFilter, | ||||
| 	NoBlending, | ||||
| 	RGBADepthPacking, | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils, | ||||
| 	WebGLRenderTarget | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { BokehShader } from '../shaders/BokehShader.js'; | ||||
|  | ||||
| /** | ||||
|  * Depth-of-field post-process with bokeh shader | ||||
|  */ | ||||
|  | ||||
| class BokehPass extends Pass { | ||||
|  | ||||
| 	constructor( scene, camera, params ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.scene = scene; | ||||
| 		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 bokehShader = BokehShader; | ||||
| 		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; | ||||
|  | ||||
| 		this.materialBokeh = new ShaderMaterial( { | ||||
| 			defines: Object.assign( {}, bokehShader.defines ), | ||||
| 			uniforms: bokehUniforms, | ||||
| 			vertexShader: bokehShader.vertexShader, | ||||
| 			fragmentShader: bokehShader.fragmentShader | ||||
| 		} ); | ||||
|  | ||||
| 		this.uniforms = bokehUniforms; | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.materialBokeh ); | ||||
|  | ||||
| 		this._oldClearColor = new Color(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( width, height ) { | ||||
|  | ||||
| 		this.materialBokeh.uniforms[ 'aspect' ].value = width / height; | ||||
|  | ||||
| 		this.renderTargetDepth.setSize( width, height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.renderTargetDepth.dispose(); | ||||
|  | ||||
| 		this.materialDepth.dispose(); | ||||
| 		this.materialBokeh.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { BokehPass }; | ||||
							
								
								
									
										46
									
								
								public/sdk/three/jsm/postprocessing/ClearPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								public/sdk/three/jsm/postprocessing/ClearPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| import { | ||||
| 	Color | ||||
| } from 'three'; | ||||
| import { Pass } from './Pass.js'; | ||||
|  | ||||
| class ClearPass extends Pass { | ||||
|  | ||||
| 	constructor( clearColor, clearAlpha ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000; | ||||
| 		this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; | ||||
| 		this._oldClearColor = new Color(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 }; | ||||
							
								
								
									
										85
									
								
								public/sdk/three/jsm/postprocessing/CubeTexturePass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								public/sdk/three/jsm/postprocessing/CubeTexturePass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,85 @@ | ||||
| import { | ||||
| 	BackSide, | ||||
| 	BoxGeometry, | ||||
| 	Mesh, | ||||
| 	PerspectiveCamera, | ||||
| 	Scene, | ||||
| 	ShaderLib, | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils | ||||
| } from 'three'; | ||||
| import { Pass } from './Pass.js'; | ||||
|  | ||||
| class CubeTexturePass extends Pass { | ||||
|  | ||||
| 	constructor( camera, tCube, opacity = 1 ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.camera = camera; | ||||
|  | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this.cubeShader = ShaderLib[ 'cube' ]; | ||||
| 		this.cubeMesh = new Mesh( | ||||
| 			new BoxGeometry( 10, 10, 10 ), | ||||
| 			new ShaderMaterial( { | ||||
| 				uniforms: UniformsUtils.clone( this.cubeShader.uniforms ), | ||||
| 				vertexShader: this.cubeShader.vertexShader, | ||||
| 				fragmentShader: this.cubeShader.fragmentShader, | ||||
| 				depthTest: false, | ||||
| 				depthWrite: false, | ||||
| 				side: BackSide | ||||
| 			} ) | ||||
| 		); | ||||
|  | ||||
| 		Object.defineProperty( this.cubeMesh.material, 'envMap', { | ||||
|  | ||||
| 			get: function () { | ||||
|  | ||||
| 				return this.uniforms.tCube.value; | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		this.tCube = tCube; | ||||
| 		this.opacity = opacity; | ||||
|  | ||||
| 		this.cubeScene = new Scene(); | ||||
| 		this.cubeCamera = new PerspectiveCamera(); | ||||
| 		this.cubeScene.add( this.cubeMesh ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.cubeMesh.geometry.dispose(); | ||||
| 		this.cubeMesh.material.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { CubeTexturePass }; | ||||
							
								
								
									
										65
									
								
								public/sdk/three/jsm/postprocessing/DotScreenPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								public/sdk/three/jsm/postprocessing/DotScreenPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| import { | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { DotScreenShader } from '../shaders/DotScreenShader.js'; | ||||
|  | ||||
| class DotScreenPass extends Pass { | ||||
|  | ||||
| 	constructor( center, angle, scale ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		const shader = DotScreenShader; | ||||
|  | ||||
| 		this.uniforms = UniformsUtils.clone( shader.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; | ||||
|  | ||||
| 		this.material = new ShaderMaterial( { | ||||
|  | ||||
| 			name: shader.name, | ||||
| 			uniforms: this.uniforms, | ||||
| 			vertexShader: shader.vertexShader, | ||||
| 			fragmentShader: shader.fragmentShader | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.material.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { DotScreenPass }; | ||||
							
								
								
									
										231
									
								
								public/sdk/three/jsm/postprocessing/EffectComposer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								public/sdk/three/jsm/postprocessing/EffectComposer.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,231 @@ | ||||
| import { | ||||
| 	Clock, | ||||
| 	HalfFloatType, | ||||
| 	NoBlending, | ||||
| 	Vector2, | ||||
| 	WebGLRenderTarget | ||||
| } from 'three'; | ||||
| import { CopyShader } from '../shaders/CopyShader.js'; | ||||
| import { ShaderPass } from './ShaderPass.js'; | ||||
| import { MaskPass } from './MaskPass.js'; | ||||
| import { ClearMaskPass } from './MaskPass.js'; | ||||
|  | ||||
| class EffectComposer { | ||||
|  | ||||
| 	constructor( renderer, renderTarget ) { | ||||
|  | ||||
| 		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'; | ||||
|  | ||||
| 		this.writeBuffer = this.renderTarget1; | ||||
| 		this.readBuffer = this.renderTarget2; | ||||
|  | ||||
| 		this.renderToScreen = true; | ||||
|  | ||||
| 		this.passes = []; | ||||
|  | ||||
| 		this.copyPass = new ShaderPass( CopyShader ); | ||||
| 		this.copyPass.material.blending = NoBlending; | ||||
|  | ||||
| 		this.clock = new Clock(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	swapBuffers() { | ||||
|  | ||||
| 		const tmp = this.readBuffer; | ||||
| 		this.readBuffer = this.writeBuffer; | ||||
| 		this.writeBuffer = tmp; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	addPass( pass ) { | ||||
|  | ||||
| 		this.passes.push( pass ); | ||||
| 		pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	insertPass( pass, index ) { | ||||
|  | ||||
| 		this.passes.splice( index, 0, pass ); | ||||
| 		pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	removePass( pass ) { | ||||
|  | ||||
| 		const index = this.passes.indexOf( pass ); | ||||
|  | ||||
| 		if ( index !== - 1 ) { | ||||
|  | ||||
| 			this.passes.splice( index, 1 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	isLastEnabledPass( passIndex ) { | ||||
|  | ||||
| 		for ( let i = passIndex + 1; i < this.passes.length; i ++ ) { | ||||
|  | ||||
| 			if ( this.passes[ i ].enabled ) { | ||||
|  | ||||
| 				return false; | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setPixelRatio( pixelRatio ) { | ||||
|  | ||||
| 		this._pixelRatio = pixelRatio; | ||||
|  | ||||
| 		this.setSize( this._width, this._height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.renderTarget1.dispose(); | ||||
| 		this.renderTarget2.dispose(); | ||||
|  | ||||
| 		this.copyPass.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { EffectComposer }; | ||||
							
								
								
									
										64
									
								
								public/sdk/three/jsm/postprocessing/FilmPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								public/sdk/three/jsm/postprocessing/FilmPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| import { | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { FilmShader } from '../shaders/FilmShader.js'; | ||||
|  | ||||
| class FilmPass extends Pass { | ||||
|  | ||||
| 	constructor( intensity = 0.5, grayscale = false ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		const shader = FilmShader; | ||||
|  | ||||
| 		this.uniforms = UniformsUtils.clone( shader.uniforms ); | ||||
|  | ||||
| 		this.material = new ShaderMaterial( { | ||||
|  | ||||
| 			name: shader.name, | ||||
| 			uniforms: this.uniforms, | ||||
| 			vertexShader: shader.vertexShader, | ||||
| 			fragmentShader: shader.fragmentShader | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		this.uniforms.intensity.value = intensity; // (0 = no effect, 1 = full effect) | ||||
| 		this.uniforms.grayscale.value = grayscale; | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.material.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { FilmPass }; | ||||
							
								
								
									
										582
									
								
								public/sdk/three/jsm/postprocessing/GTAOPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										582
									
								
								public/sdk/three/jsm/postprocessing/GTAOPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,582 @@ | ||||
| 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'; | ||||
|  | ||||
| class GTAOPass extends Pass { | ||||
|  | ||||
| 	constructor( scene, camera, width, height, parameters, aoParameters, pdParameters ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.width = ( width !== undefined ) ? width : 512; | ||||
| 		this.height = ( height !== undefined ) ? height : 512; | ||||
| 		this.clear = true; | ||||
| 		this.camera = camera; | ||||
| 		this.scene = scene; | ||||
| 		this.output = 0; | ||||
| 		this._renderGBuffer = true; | ||||
| 		this._visibilityCache = new Map(); | ||||
| 		this.blendIntensity = 1.; | ||||
|  | ||||
| 		this.pdRings = 2.; | ||||
| 		this.pdRadiusExponent = 2.; | ||||
| 		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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	get gtaoMap() { | ||||
|  | ||||
| 		return this.pdRenderTarget.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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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.' ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	overrideVisibility() { | ||||
|  | ||||
| 		const scene = this.scene; | ||||
| 		const cache = this._visibilityCache; | ||||
|  | ||||
| 		scene.traverse( function ( object ) { | ||||
|  | ||||
| 			cache.set( object, object.visible ); | ||||
|  | ||||
| 			if ( object.isPoints || object.isLine ) object.visible = false; | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	restoreVisibility() { | ||||
|  | ||||
| 		const scene = this.scene; | ||||
| 		const cache = this._visibilityCache; | ||||
|  | ||||
| 		scene.traverse( function ( object ) { | ||||
|  | ||||
| 			const visible = cache.get( object ); | ||||
| 			object.visible = visible; | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		cache.clear(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 }; | ||||
							
								
								
									
										125
									
								
								public/sdk/three/jsm/postprocessing/GlitchPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								public/sdk/three/jsm/postprocessing/GlitchPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,125 @@ | ||||
| import { | ||||
| 	DataTexture, | ||||
| 	FloatType, | ||||
| 	MathUtils, | ||||
| 	RedFormat, | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { DigitalGlitch } from '../shaders/DigitalGlitch.js'; | ||||
|  | ||||
| class GlitchPass extends Pass { | ||||
|  | ||||
| 	constructor( dt_size = 64 ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		const shader = DigitalGlitch; | ||||
|  | ||||
| 		this.uniforms = UniformsUtils.clone( shader.uniforms ); | ||||
|  | ||||
| 		this.heightMap = this.generateHeightmap( dt_size ); | ||||
|  | ||||
| 		this.uniforms[ 'tDisp' ].value = this.heightMap; | ||||
|  | ||||
| 		this.material = new ShaderMaterial( { | ||||
| 			uniforms: this.uniforms, | ||||
| 			vertexShader: shader.vertexShader, | ||||
| 			fragmentShader: shader.fragmentShader | ||||
| 		} ); | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 		this.goWild = false; | ||||
| 		this.curF = 0; | ||||
| 		this.generateTrigger(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.material.dispose(); | ||||
|  | ||||
| 		this.heightMap.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { GlitchPass }; | ||||
							
								
								
									
										79
									
								
								public/sdk/three/jsm/postprocessing/HalftonePass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								public/sdk/three/jsm/postprocessing/HalftonePass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| import { | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { HalftoneShader } from '../shaders/HalftoneShader.js'; | ||||
|  | ||||
| /** | ||||
|  * RGB Halftone pass for three.js effects composer. Requires HalftoneShader. | ||||
|  */ | ||||
|  | ||||
| class HalftonePass extends Pass { | ||||
|  | ||||
| 	constructor( width, height, params ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 	 	this.uniforms = UniformsUtils.clone( HalftoneShader.uniforms ); | ||||
| 	 	this.material = new ShaderMaterial( { | ||||
| 	 		uniforms: this.uniforms, | ||||
| 	 		fragmentShader: HalftoneShader.fragmentShader, | ||||
| 	 		vertexShader: HalftoneShader.vertexShader | ||||
| 	 	} ); | ||||
|  | ||||
| 		// set params | ||||
| 		this.uniforms.width.value = width; | ||||
| 		this.uniforms.height.value = height; | ||||
|  | ||||
| 		for ( const key in params ) { | ||||
|  | ||||
| 			if ( params.hasOwnProperty( key ) && this.uniforms.hasOwnProperty( key ) ) { | ||||
|  | ||||
| 				this.uniforms[ key ].value = params[ key ]; | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
|  	} | ||||
|  | ||||
|  	setSize( width, height ) { | ||||
|  | ||||
|  		this.uniforms.width.value = width; | ||||
|  		this.uniforms.height.value = height; | ||||
|  | ||||
|  	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.material.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { HalftonePass }; | ||||
							
								
								
									
										108
									
								
								public/sdk/three/jsm/postprocessing/LUTPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								public/sdk/three/jsm/postprocessing/LUTPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | ||||
| 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 ) ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	`, | ||||
|  | ||||
| }; | ||||
|  | ||||
| class LUTPass extends ShaderPass { | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	constructor( options = {} ) { | ||||
|  | ||||
| 		super( LUTShader ); | ||||
| 		this.lut = options.lut || null; | ||||
| 		this.intensity = 'intensity' in options ? options.intensity : 1; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { LUTPass }; | ||||
							
								
								
									
										104
									
								
								public/sdk/three/jsm/postprocessing/MaskPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								public/sdk/three/jsm/postprocessing/MaskPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | ||||
| import { Pass } from './Pass.js'; | ||||
|  | ||||
| class MaskPass extends Pass { | ||||
|  | ||||
| 	constructor( scene, camera ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.scene = scene; | ||||
| 		this.camera = camera; | ||||
|  | ||||
| 		this.clear = true; | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this.inverse = false; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| class ClearMaskPass extends Pass { | ||||
|  | ||||
| 	constructor() { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) { | ||||
|  | ||||
| 		renderer.state.buffers.stencil.setLocked( false ); | ||||
| 		renderer.state.buffers.stencil.setTest( false ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { MaskPass, ClearMaskPass }; | ||||
							
								
								
									
										654
									
								
								public/sdk/three/jsm/postprocessing/OutlinePass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										654
									
								
								public/sdk/three/jsm/postprocessing/OutlinePass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,654 @@ | ||||
| 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'; | ||||
|  | ||||
| class OutlinePass extends Pass { | ||||
|  | ||||
| 	constructor( resolution, scene, camera, selectedObjects ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.renderScene = scene; | ||||
| 		this.renderCamera = camera; | ||||
| 		this.selectedObjects = selectedObjects !== undefined ? selectedObjects : []; | ||||
| 		this.visibleEdgeColor = new Color( 1, 1, 1 ); | ||||
| 		this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 ); | ||||
| 		this.edgeGlow = 0.0; | ||||
| 		this.usePatternTexture = false; | ||||
| 		this.edgeThickness = 1.0; | ||||
| 		this.edgeStrength = 3.0; | ||||
| 		this.downSampleRatio = 2; | ||||
| 		this.pulsePeriod = 0; | ||||
|  | ||||
| 		this._visibilityCache = new Map(); | ||||
|  | ||||
|  | ||||
| 		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.getSeperableBlurMaterial( MAX_EDGE_THICKNESS ); | ||||
| 		this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy ); | ||||
| 		this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1; | ||||
| 		this.separableBlurMaterial2 = this.getSeperableBlurMaterial( 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' ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	changeVisibilityOfSelectedObjects( bVisible ) { | ||||
|  | ||||
| 		const cache = this._visibilityCache; | ||||
|  | ||||
| 		function gatherSelectedMeshesCallBack( object ) { | ||||
|  | ||||
| 			if ( object.isMesh ) { | ||||
|  | ||||
| 				if ( bVisible === true ) { | ||||
|  | ||||
| 					object.visible = cache.get( object ); | ||||
|  | ||||
| 				} else { | ||||
|  | ||||
| 					cache.set( object, object.visible ); | ||||
| 					object.visible = bVisible; | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		for ( let i = 0; i < this.selectedObjects.length; i ++ ) { | ||||
|  | ||||
| 			const selectedObject = this.selectedObjects[ i ]; | ||||
| 			selectedObject.traverse( gatherSelectedMeshesCallBack ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	changeVisibilityOfNonSelectedObjects( bVisible ) { | ||||
|  | ||||
| 		const cache = this._visibilityCache; | ||||
| 		const selectedMeshes = []; | ||||
|  | ||||
| 		function gatherSelectedMeshesCallBack( object ) { | ||||
|  | ||||
| 			if ( object.isMesh ) selectedMeshes.push( object ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		for ( let i = 0; i < this.selectedObjects.length; i ++ ) { | ||||
|  | ||||
| 			const selectedObject = this.selectedObjects[ i ]; | ||||
| 			selectedObject.traverse( gatherSelectedMeshesCallBack ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		function VisibilityChangeCallBack( object ) { | ||||
|  | ||||
| 			if ( object.isMesh || object.isSprite ) { | ||||
|  | ||||
| 				// only meshes and sprites are supported by OutlinePass | ||||
|  | ||||
| 				let bFound = false; | ||||
|  | ||||
| 				for ( let i = 0; i < selectedMeshes.length; i ++ ) { | ||||
|  | ||||
| 					const selectedObjectId = selectedMeshes[ i ].id; | ||||
|  | ||||
| 					if ( selectedObjectId === object.id ) { | ||||
|  | ||||
| 						bFound = true; | ||||
| 						break; | ||||
|  | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				if ( bFound === false ) { | ||||
|  | ||||
| 					const visibility = object.visible; | ||||
|  | ||||
| 					if ( bVisible === false || cache.get( object ) === true ) { | ||||
|  | ||||
| 						object.visible = bVisible; | ||||
|  | ||||
| 					} | ||||
|  | ||||
| 					cache.set( object, visibility ); | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 			} else if ( object.isPoints || object.isLine ) { | ||||
|  | ||||
| 				// the visibilty of points and lines is always set to false in order to | ||||
| 				// not affect the outline computation | ||||
|  | ||||
| 				if ( bVisible === true ) { | ||||
|  | ||||
| 					object.visible = cache.get( object ); // restore | ||||
|  | ||||
| 				} else { | ||||
|  | ||||
| 					cache.set( object, object.visible ); | ||||
| 					object.visible = bVisible; | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 			// Make selected objects invisible | ||||
| 			this.changeVisibilityOfSelectedObjects( false ); | ||||
|  | ||||
| 			const currentBackground = this.renderScene.background; | ||||
| 			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.renderScene.overrideMaterial = null; | ||||
| 			this.changeVisibilityOfNonSelectedObjects( true ); | ||||
| 			this._visibilityCache.clear(); | ||||
|  | ||||
| 			this.renderScene.background = currentBackground; | ||||
|  | ||||
| 			// 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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	getPrepareMaskMaterial() { | ||||
|  | ||||
| 		return new ShaderMaterial( { | ||||
|  | ||||
| 			uniforms: { | ||||
| 				'depthTexture': { value: null }, | ||||
| 				'cameraNearFar': { value: new Vector2( 0.5, 0.5 ) }, | ||||
| 				'textureMatrix': { value: null } | ||||
| 			}, | ||||
|  | ||||
| 			vertexShader: | ||||
| 				`#include <morphtarget_pars_vertex> | ||||
| 				#include <skinning_pars_vertex> | ||||
|  | ||||
| 				varying vec4 projTexCoord; | ||||
| 				varying vec4 vPosition; | ||||
| 				uniform mat4 textureMatrix; | ||||
|  | ||||
| 				void main() { | ||||
|  | ||||
| 					#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); | ||||
| 				}` | ||||
| 		} ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	getSeperableBlurMaterial( 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 }; | ||||
							
								
								
									
										97
									
								
								public/sdk/three/jsm/postprocessing/OutputPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								public/sdk/three/jsm/postprocessing/OutputPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,97 @@ | ||||
| import { | ||||
| 	ColorManagement, | ||||
| 	RawShaderMaterial, | ||||
| 	UniformsUtils, | ||||
| 	LinearToneMapping, | ||||
| 	ReinhardToneMapping, | ||||
| 	CineonToneMapping, | ||||
| 	AgXToneMapping, | ||||
| 	ACESFilmicToneMapping, | ||||
| 	NeutralToneMapping, | ||||
| 	SRGBTransfer | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { OutputShader } from '../shaders/OutputShader.js'; | ||||
|  | ||||
| class OutputPass extends Pass { | ||||
|  | ||||
| 	constructor() { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		// | ||||
|  | ||||
| 		const shader = OutputShader; | ||||
|  | ||||
| 		this.uniforms = UniformsUtils.clone( shader.uniforms ); | ||||
|  | ||||
| 		this.material = new RawShaderMaterial( { | ||||
| 			name: shader.name, | ||||
| 			uniforms: this.uniforms, | ||||
| 			vertexShader: shader.vertexShader, | ||||
| 			fragmentShader: shader.fragmentShader | ||||
| 		} ); | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 		// internal cache | ||||
|  | ||||
| 		this._outputColorSpace = null; | ||||
| 		this._toneMapping = null; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 = ''; | ||||
|  | ||||
| 			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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.material.dispose(); | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { OutputPass }; | ||||
							
								
								
									
										95
									
								
								public/sdk/three/jsm/postprocessing/Pass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								public/sdk/three/jsm/postprocessing/Pass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | ||||
| import { | ||||
| 	BufferGeometry, | ||||
| 	Float32BufferAttribute, | ||||
| 	OrthographicCamera, | ||||
| 	Mesh | ||||
| } from 'three'; | ||||
|  | ||||
| class Pass { | ||||
|  | ||||
| 	constructor() { | ||||
|  | ||||
| 		this.isPass = true; | ||||
|  | ||||
| 		// if set to true, the pass is processed by the composer | ||||
| 		this.enabled = true; | ||||
|  | ||||
| 		// if set to true, the pass indicates to swap read and write buffer after rendering | ||||
| 		this.needsSwap = true; | ||||
|  | ||||
| 		// if set to true, the pass clears its buffer before rendering | ||||
| 		this.clear = false; | ||||
|  | ||||
| 		// if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer. | ||||
| 		this.renderToScreen = false; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( /* width, height */ ) {} | ||||
|  | ||||
| 	render( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) { | ||||
|  | ||||
| 		console.error( 'THREE.Pass: .render() must be implemented in derived pass.' ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| class FullScreenQuad { | ||||
|  | ||||
| 	constructor( material ) { | ||||
|  | ||||
| 		this._mesh = new Mesh( _geometry, material ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this._mesh.geometry.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer ) { | ||||
|  | ||||
| 		renderer.render( this._mesh, _camera ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	get material() { | ||||
|  | ||||
| 		return this._mesh.material; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	set material( value ) { | ||||
|  | ||||
| 		this._mesh.material = value; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { Pass, FullScreenQuad }; | ||||
							
								
								
									
										99
									
								
								public/sdk/three/jsm/postprocessing/RenderPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								public/sdk/three/jsm/postprocessing/RenderPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| import { | ||||
| 	Color | ||||
| } from 'three'; | ||||
| import { Pass } from './Pass.js'; | ||||
|  | ||||
| class RenderPass extends Pass { | ||||
|  | ||||
| 	constructor( scene, camera, overrideMaterial = null, clearColor = null, clearAlpha = null ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.scene = scene; | ||||
| 		this.camera = camera; | ||||
|  | ||||
| 		this.overrideMaterial = overrideMaterial; | ||||
|  | ||||
| 		this.clearColor = clearColor; | ||||
| 		this.clearAlpha = clearAlpha; | ||||
|  | ||||
| 		this.clear = true; | ||||
| 		this.clearDepth = false; | ||||
| 		this.needsSwap = false; | ||||
| 		this._oldClearColor = new Color(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		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 }; | ||||
							
								
								
									
										235
									
								
								public/sdk/three/jsm/postprocessing/RenderPixelatedPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								public/sdk/three/jsm/postprocessing/RenderPixelatedPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,235 @@ | ||||
| import { | ||||
| 	WebGLRenderTarget, | ||||
| 	MeshNormalMaterial, | ||||
| 	ShaderMaterial, | ||||
| 	Vector2, | ||||
| 	Vector4, | ||||
| 	DepthTexture, | ||||
| 	NearestFilter, | ||||
| 	HalfFloatType | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
|  | ||||
| class RenderPixelatedPass extends Pass { | ||||
|  | ||||
| 	constructor( pixelSize, scene, camera, options = {} ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.pixelSize = pixelSize; | ||||
| 		this.resolution = new Vector2(); | ||||
| 		this.renderResolution = new Vector2(); | ||||
|  | ||||
| 		this.pixelatedMaterial = this.createPixelatedMaterial(); | ||||
| 		this.normalMaterial = new MeshNormalMaterial(); | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.pixelatedMaterial ); | ||||
| 		this.scene = scene; | ||||
| 		this.camera = camera; | ||||
|  | ||||
| 		this.normalEdgeStrength = options.normalEdgeStrength || 0.3; | ||||
| 		this.depthEdgeStrength = options.depthEdgeStrength || 0.4; | ||||
|  | ||||
| 		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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.beautyRenderTarget.dispose(); | ||||
| 		this.normalRenderTarget.dispose(); | ||||
|  | ||||
| 		this.pixelatedMaterial.dispose(); | ||||
| 		this.normalMaterial.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setPixelSize( pixelSize ) { | ||||
|  | ||||
| 		this.pixelSize = pixelSize; | ||||
| 		this.setSize( this.resolution.x, this.resolution.y ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer, writeBuffer ) { | ||||
|  | ||||
| 		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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	createPixelatedMaterial() { | ||||
|  | ||||
| 		return new ShaderMaterial( { | ||||
| 			uniforms: { | ||||
| 				tDiffuse: { value: null }, | ||||
| 				tDepth: { value: null }, | ||||
| 				tNormal: { value: null }, | ||||
| 				resolution: { | ||||
| 					value: new Vector4( | ||||
| 						this.renderResolution.x, | ||||
| 						this.renderResolution.y, | ||||
| 						1 / this.renderResolution.x, | ||||
| 						1 / this.renderResolution.y, | ||||
| 					) | ||||
| 				}, | ||||
| 				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 }; | ||||
							
								
								
									
										193
									
								
								public/sdk/three/jsm/postprocessing/RenderTransitionPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								public/sdk/three/jsm/postprocessing/RenderTransitionPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,193 @@ | ||||
| import { | ||||
| 	HalfFloatType, | ||||
| 	ShaderMaterial, | ||||
| 	WebGLRenderTarget | ||||
| } from 'three'; | ||||
| import { FullScreenQuad, Pass } from './Pass.js'; | ||||
|  | ||||
| class RenderTransitionPass extends Pass { | ||||
|  | ||||
| 	constructor( sceneA, cameraA, sceneB, cameraB ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.material = this.createMaterial(); | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 		this.sceneA = sceneA; | ||||
| 		this.cameraA = cameraA; | ||||
| 		this.sceneB = sceneB; | ||||
| 		this.cameraB = cameraB; | ||||
|  | ||||
| 		this.renderTargetA = new WebGLRenderTarget(); | ||||
| 		this.renderTargetA.texture.type = HalfFloatType; | ||||
| 		this.renderTargetB = new WebGLRenderTarget(); | ||||
| 		this.renderTargetB.texture.type = HalfFloatType; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setTransition( value ) { | ||||
|  | ||||
| 		this.material.uniforms.mixRatio.value = value; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	useTexture( value ) { | ||||
|  | ||||
| 		this.material.uniforms.useTexture.value = value ? 1 : 0; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setTexture( value ) { | ||||
|  | ||||
| 		this.material.uniforms.tMixTexture.value = value; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setTextureThreshold( value ) { | ||||
|  | ||||
| 		this.material.uniforms.threshold.value = value; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( width, height ) { | ||||
|  | ||||
| 		this.renderTargetA.setSize( width, height ); | ||||
| 		this.renderTargetB.setSize( width, height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer, writeBuffer ) { | ||||
|  | ||||
| 		const uniforms = this.fsQuad.material.uniforms; | ||||
| 		const transition = uniforms.mixRatio.value; | ||||
|  | ||||
| 		// Prevent render both scenes when it's not necessary | ||||
|  | ||||
| 		if ( transition === 0 ) { | ||||
|  | ||||
| 			renderer.setRenderTarget( writeBuffer ); | ||||
| 			if ( this.clear ) renderer.clear(); | ||||
| 			renderer.render( this.sceneB, this.cameraB ); | ||||
|  | ||||
| 		} else if ( transition === 1 ) { | ||||
|  | ||||
| 			renderer.setRenderTarget( writeBuffer ); | ||||
| 			if ( this.clear ) renderer.clear(); | ||||
| 			renderer.render( this.sceneA, this.cameraA ); | ||||
|  | ||||
| 		} else { | ||||
|  | ||||
| 			// When 0 < transition < 1 render transition between two scenes | ||||
|  | ||||
| 			renderer.setRenderTarget( this.renderTargetA ); | ||||
| 			renderer.render( this.sceneA, this.cameraA ); | ||||
| 			renderer.setRenderTarget( this.renderTargetB ); | ||||
| 			renderer.render( this.sceneB, this.cameraB ); | ||||
|  | ||||
| 			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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.renderTargetA.dispose(); | ||||
| 		this.renderTargetB.dispose(); | ||||
| 		this.material.dispose(); | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 					} | ||||
|  | ||||
| 					#include <tonemapping_fragment> | ||||
| 					#include <colorspace_fragment> | ||||
|  | ||||
| 				} | ||||
| 			` | ||||
| 		} ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { RenderTransitionPass }; | ||||
							
								
								
									
										334
									
								
								public/sdk/three/jsm/postprocessing/SAOPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								public/sdk/three/jsm/postprocessing/SAOPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,334 @@ | ||||
| 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 { DepthLimitedBlurShader } from '../shaders/DepthLimitedBlurShader.js'; | ||||
| import { BlurShaderUtils } from '../shaders/DepthLimitedBlurShader.js'; | ||||
| import { CopyShader } from '../shaders/CopyShader.js'; | ||||
|  | ||||
| /** | ||||
|  * SAO implementation inspired from bhouston previous SAO work | ||||
|  */ | ||||
|  | ||||
| class SAOPass extends Pass { | ||||
|  | ||||
| 	constructor( scene, camera, resolution = new Vector2( 256, 256 ) ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.scene = scene; | ||||
| 		this.camera = camera; | ||||
|  | ||||
| 		this.clear = true; | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this.originalClearColor = new Color(); | ||||
| 		this._oldClearColor = new Color(); | ||||
| 		this.oldClearAlpha = 1; | ||||
|  | ||||
| 		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 | ||||
| 		}; | ||||
|  | ||||
| 		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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| SAOPass.OUTPUT = { | ||||
| 	'Default': 0, | ||||
| 	'SAO': 1, | ||||
| 	'Normal': 2 | ||||
| }; | ||||
|  | ||||
| export { SAOPass }; | ||||
							
								
								
									
										199
									
								
								public/sdk/three/jsm/postprocessing/SMAAPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								public/sdk/three/jsm/postprocessing/SMAAPass.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										228
									
								
								public/sdk/three/jsm/postprocessing/SSAARenderPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								public/sdk/three/jsm/postprocessing/SSAARenderPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,228 @@ | ||||
| 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. | ||||
| * | ||||
| * References: https://en.wikipedia.org/wiki/Supersampling | ||||
| * | ||||
| */ | ||||
|  | ||||
| class SSAARenderPass extends Pass { | ||||
|  | ||||
| 	constructor( scene, camera, clearColor, clearAlpha ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.scene = scene; | ||||
| 		this.camera = camera; | ||||
|  | ||||
| 		this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16. | ||||
| 		this.unbiased = true; | ||||
|  | ||||
| 		// as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black. | ||||
| 		this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000; | ||||
| 		this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0; | ||||
| 		this._oldClearColor = new Color(); | ||||
|  | ||||
| 		const copyShader = CopyShader; | ||||
| 		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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		if ( this.sampleRenderTarget ) { | ||||
|  | ||||
| 			this.sampleRenderTarget.dispose(); | ||||
| 			this.sampleRenderTarget = null; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		this.copyMaterial.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( width, height ) { | ||||
|  | ||||
| 		if ( this.sampleRenderTarget )	this.sampleRenderTarget.setSize( width, height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer, writeBuffer, readBuffer ) { | ||||
|  | ||||
| 		if ( ! this.sampleRenderTarget ) { | ||||
|  | ||||
| 			this.sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } ); | ||||
| 			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 }; | ||||
							
								
								
									
										417
									
								
								public/sdk/three/jsm/postprocessing/SSAOPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										417
									
								
								public/sdk/three/jsm/postprocessing/SSAOPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,417 @@ | ||||
| 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 { SSAOShader } from '../shaders/SSAOShader.js'; | ||||
| import { SSAOBlurShader } from '../shaders/SSAOShader.js'; | ||||
| import { SSAODepthShader } from '../shaders/SSAOShader.js'; | ||||
| import { CopyShader } from '../shaders/CopyShader.js'; | ||||
|  | ||||
| class SSAOPass extends Pass { | ||||
|  | ||||
| 	constructor( scene, camera, width, height, kernelSize = 32 ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.width = ( width !== undefined ) ? width : 512; | ||||
| 		this.height = ( height !== undefined ) ? height : 512; | ||||
|  | ||||
| 		this.clear = true; | ||||
|  | ||||
| 		this.camera = camera; | ||||
| 		this.scene = scene; | ||||
|  | ||||
| 		this.kernelRadius = 8; | ||||
| 		this.kernel = []; | ||||
| 		this.noiseTexture = null; | ||||
| 		this.output = 0; | ||||
|  | ||||
| 		this.minDistance = 0.005; | ||||
| 		this.maxDistance = 0.1; | ||||
|  | ||||
| 		this._visibilityCache = new Map(); | ||||
|  | ||||
| 		// | ||||
|  | ||||
| 		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 | ||||
| 		} ); | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( null ); | ||||
|  | ||||
| 		this.originalClearColor = new Color(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| 		// dipsose full screen quad | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 : writeBuffer ); | ||||
|  | ||||
| 				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 : writeBuffer ); | ||||
|  | ||||
| 				break; | ||||
|  | ||||
| 			case SSAOPass.OUTPUT.Depth: | ||||
|  | ||||
| 				this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer ); | ||||
|  | ||||
| 				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 : writeBuffer ); | ||||
|  | ||||
| 				break; | ||||
|  | ||||
| 			case SSAOPass.OUTPUT.Default: | ||||
|  | ||||
| 				this.copyMaterial.uniforms[ 'tDiffuse' ].value = readBuffer.texture; | ||||
| 				this.copyMaterial.blending = NoBlending; | ||||
| 				this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer ); | ||||
|  | ||||
| 				this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.blurRenderTarget.texture; | ||||
| 				this.copyMaterial.blending = CustomBlending; | ||||
| 				this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer ); | ||||
|  | ||||
| 				break; | ||||
|  | ||||
| 			default: | ||||
| 				console.warn( 'THREE.SSAOPass: Unknown output type.' ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ) { | ||||
|  | ||||
| 			cache.set( object, object.visible ); | ||||
|  | ||||
| 			if ( object.isPoints || object.isLine ) object.visible = false; | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	restoreVisibility() { | ||||
|  | ||||
| 		const scene = this.scene; | ||||
| 		const cache = this._visibilityCache; | ||||
|  | ||||
| 		scene.traverse( function ( object ) { | ||||
|  | ||||
| 			const visible = cache.get( object ); | ||||
| 			object.visible = visible; | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		cache.clear(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| SSAOPass.OUTPUT = { | ||||
| 	'Default': 0, | ||||
| 	'SSAO': 1, | ||||
| 	'Blur': 2, | ||||
| 	'Depth': 3, | ||||
| 	'Normal': 4 | ||||
| }; | ||||
|  | ||||
| export { SSAOPass }; | ||||
							
								
								
									
										641
									
								
								public/sdk/three/jsm/postprocessing/SSRPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										641
									
								
								public/sdk/three/jsm/postprocessing/SSRPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,641 @@ | ||||
| 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 { SSRShader } from '../shaders/SSRShader.js'; | ||||
| import { SSRBlurShader } from '../shaders/SSRShader.js'; | ||||
| import { SSRDepthShader } from '../shaders/SSRShader.js'; | ||||
| import { CopyShader } from '../shaders/CopyShader.js'; | ||||
|  | ||||
| class SSRPass extends Pass { | ||||
|  | ||||
| 	constructor( { renderer, scene, camera, width, height, selects, bouncing = false, groundReflector } ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.width = ( width !== undefined ) ? width : 512; | ||||
| 		this.height = ( height !== undefined ) ? height : 512; | ||||
|  | ||||
| 		this.clear = true; | ||||
|  | ||||
| 		this.renderer = renderer; | ||||
| 		this.scene = scene; | ||||
| 		this.camera = camera; | ||||
| 		this.groundReflector = groundReflector; | ||||
|  | ||||
| 		this.opacity = SSRShader.uniforms.opacity.value; | ||||
| 		this.output = 0; | ||||
|  | ||||
| 		this.maxDistance = SSRShader.uniforms.maxDistance.value; | ||||
| 		this.thickness = SSRShader.uniforms.thickness.value; | ||||
|  | ||||
| 		this.tempColor = new Color(); | ||||
|  | ||||
| 		this._selects = selects; | ||||
| 		this.selective = Array.isArray( this._selects ); | ||||
| 		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; | ||||
| 		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; | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
| 		} ); | ||||
|  | ||||
| 		this.blur = true; | ||||
|  | ||||
| 		this._distanceAttenuation = SSRShader.defines.DISTANCE_ATTENUATION; | ||||
| 		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; | ||||
| 		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; | ||||
| 		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(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| 		// dipsose full screen quad | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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.' ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 		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.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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( width, height ) { | ||||
|  | ||||
| 		this.width = width; | ||||
| 		this.height = height; | ||||
|  | ||||
| 		this.ssrMaterial.defines.MAX_STEP = Math.sqrt( width * width + height * height ); | ||||
| 		this.ssrMaterial.needsUpdate = true; | ||||
| 		this.beautyRenderTarget.setSize( width, height ); | ||||
| 		this.prevRenderTarget.setSize( width, height ); | ||||
| 		this.ssrRenderTarget.setSize( width, height ); | ||||
| 		this.normalRenderTarget.setSize( width, height ); | ||||
| 		this.metalnessRenderTarget.setSize( width, height ); | ||||
| 		this.blurRenderTarget.setSize( width, height ); | ||||
| 		this.blurRenderTarget2.setSize( width, height ); | ||||
| 		// this.blurRenderTarget3.setSize(width, height); | ||||
|  | ||||
| 		this.ssrMaterial.uniforms[ 'resolution' ].value.set( width, height ); | ||||
| 		this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix ); | ||||
| 		this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse ); | ||||
|  | ||||
| 		this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height ); | ||||
| 		this.blurMaterial2.uniforms[ 'resolution' ].value.set( width, height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| SSRPass.OUTPUT = { | ||||
| 	'Default': 0, | ||||
| 	'SSR': 1, | ||||
| 	'Beauty': 3, | ||||
| 	'Depth': 4, | ||||
| 	'Normal': 5, | ||||
| 	'Metalness': 7, | ||||
| }; | ||||
|  | ||||
| export { SSRPass }; | ||||
							
								
								
									
										79
									
								
								public/sdk/three/jsm/postprocessing/SavePass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								public/sdk/three/jsm/postprocessing/SavePass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| import { | ||||
| 	HalfFloatType, | ||||
| 	NoBlending, | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils, | ||||
| 	WebGLRenderTarget | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { CopyShader } from '../shaders/CopyShader.js'; | ||||
|  | ||||
| class SavePass extends Pass { | ||||
|  | ||||
| 	constructor( renderTarget ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		const shader = CopyShader; | ||||
|  | ||||
| 		this.textureID = 'tDiffuse'; | ||||
|  | ||||
| 		this.uniforms = UniformsUtils.clone( shader.uniforms ); | ||||
|  | ||||
| 		this.material = new ShaderMaterial( { | ||||
|  | ||||
| 			uniforms: this.uniforms, | ||||
| 			vertexShader: shader.vertexShader, | ||||
| 			fragmentShader: shader.fragmentShader, | ||||
| 			blending: NoBlending | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		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'; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive */ ) { | ||||
|  | ||||
| 		if ( this.uniforms[ this.textureID ] ) { | ||||
|  | ||||
| 			this.uniforms[ this.textureID ].value = readBuffer.texture; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		renderer.setRenderTarget( this.renderTarget ); | ||||
| 		if ( this.clear ) renderer.clear(); | ||||
| 		this.fsQuad.render( renderer ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	setSize( width, height ) { | ||||
|  | ||||
| 		this.renderTarget.setSize( width, height ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.renderTarget.dispose(); | ||||
|  | ||||
| 		this.material.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { SavePass }; | ||||
							
								
								
									
										77
									
								
								public/sdk/three/jsm/postprocessing/ShaderPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								public/sdk/three/jsm/postprocessing/ShaderPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| import { | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
|  | ||||
| class ShaderPass extends Pass { | ||||
|  | ||||
| 	constructor( shader, textureID ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.textureID = ( textureID !== undefined ) ? textureID : 'tDiffuse'; | ||||
|  | ||||
| 		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 | ||||
|  | ||||
| 			} ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( this.material ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.material.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { ShaderPass }; | ||||
							
								
								
									
										188
									
								
								public/sdk/three/jsm/postprocessing/TAARenderPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								public/sdk/three/jsm/postprocessing/TAARenderPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,188 @@ | ||||
| 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. | ||||
|  * | ||||
|  * References: | ||||
|  * | ||||
|  * TODO: Add support for motion vector pas so that accumulation of samples across frames can occur on dynamics scenes. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| class TAARenderPass extends SSAARenderPass { | ||||
|  | ||||
| 	constructor( scene, camera, clearColor, clearAlpha ) { | ||||
|  | ||||
| 		super( scene, camera, clearColor, clearAlpha ); | ||||
|  | ||||
| 		this.sampleLevel = 0; | ||||
| 		this.accumulate = false; | ||||
| 		this.accumulateIndex = - 1; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	render( renderer, writeBuffer, readBuffer, deltaTime ) { | ||||
|  | ||||
| 		if ( this.accumulate === false ) { | ||||
|  | ||||
| 			super.render( renderer, writeBuffer, readBuffer, deltaTime ); | ||||
|  | ||||
| 			this.accumulateIndex = - 1; | ||||
| 			return; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		const jitterOffsets = _JitterVectors[ 5 ]; | ||||
|  | ||||
| 		if ( this.sampleRenderTarget === undefined ) { | ||||
|  | ||||
| 			this.sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } ); | ||||
| 			this.sampleRenderTarget.texture.name = 'TAARenderPass.sample'; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		if ( this.holdRenderTarget === undefined ) { | ||||
|  | ||||
| 			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 ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 }; | ||||
							
								
								
									
										67
									
								
								public/sdk/three/jsm/postprocessing/TexturePass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								public/sdk/three/jsm/postprocessing/TexturePass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| import { | ||||
| 	ShaderMaterial, | ||||
| 	UniformsUtils | ||||
| } from 'three'; | ||||
| import { Pass, FullScreenQuad } from './Pass.js'; | ||||
| import { CopyShader } from '../shaders/CopyShader.js'; | ||||
|  | ||||
| class TexturePass extends Pass { | ||||
|  | ||||
| 	constructor( map, opacity ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		const shader = CopyShader; | ||||
|  | ||||
| 		this.map = map; | ||||
| 		this.opacity = ( opacity !== undefined ) ? opacity : 1.0; | ||||
|  | ||||
| 		this.uniforms = UniformsUtils.clone( shader.uniforms ); | ||||
|  | ||||
| 		this.material = new ShaderMaterial( { | ||||
|  | ||||
| 			uniforms: this.uniforms, | ||||
| 			vertexShader: shader.vertexShader, | ||||
| 			fragmentShader: shader.fragmentShader, | ||||
| 			depthTest: false, | ||||
| 			depthWrite: false, | ||||
| 			premultipliedAlpha: true | ||||
|  | ||||
| 		} ); | ||||
|  | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( null ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	dispose() { | ||||
|  | ||||
| 		this.material.dispose(); | ||||
|  | ||||
| 		this.fsQuad.dispose(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| export { TexturePass }; | ||||
							
								
								
									
										415
									
								
								public/sdk/three/jsm/postprocessing/UnrealBloomPass.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										415
									
								
								public/sdk/three/jsm/postprocessing/UnrealBloomPass.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,415 @@ | ||||
| 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'; | ||||
|  | ||||
| /** | ||||
|  * UnrealBloomPass 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. | ||||
|  * | ||||
|  * Reference: | ||||
|  * - https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/ | ||||
|  */ | ||||
| class UnrealBloomPass extends Pass { | ||||
|  | ||||
| 	constructor( resolution, strength, radius, threshold ) { | ||||
|  | ||||
| 		super(); | ||||
|  | ||||
| 		this.strength = ( strength !== undefined ) ? strength : 1; | ||||
| 		this.radius = radius; | ||||
| 		this.threshold = threshold; | ||||
| 		this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 ); | ||||
|  | ||||
| 		// create color only once here, reuse it later inside the render function | ||||
| 		this.clearColor = new Color( 0, 0, 0 ); | ||||
|  | ||||
| 		// 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 renderTargetHorizonal = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } ); | ||||
|  | ||||
| 			renderTargetHorizonal.texture.name = 'UnrealBloomPass.h' + i; | ||||
| 			renderTargetHorizonal.texture.generateMipmaps = false; | ||||
|  | ||||
| 			this.renderTargetsHorizontal.push( renderTargetHorizonal ); | ||||
|  | ||||
| 			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 = []; | ||||
| 		const kernelSizeArray = [ 3, 5, 7, 9, 11 ]; | ||||
| 		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.getSeperableBlurMaterial( 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 | ||||
|  | ||||
| 		const copyShader = CopyShader; | ||||
|  | ||||
| 		this.copyUniforms = UniformsUtils.clone( copyShader.uniforms ); | ||||
|  | ||||
| 		this.blendMaterial = new ShaderMaterial( { | ||||
| 			uniforms: this.copyUniforms, | ||||
| 			vertexShader: copyShader.vertexShader, | ||||
| 			fragmentShader: copyShader.fragmentShader, | ||||
| 			blending: AdditiveBlending, | ||||
| 			depthTest: false, | ||||
| 			depthWrite: false, | ||||
| 			transparent: true | ||||
| 		} ); | ||||
|  | ||||
| 		this.enabled = true; | ||||
| 		this.needsSwap = false; | ||||
|  | ||||
| 		this._oldClearColor = new Color(); | ||||
| 		this.oldClearAlpha = 1; | ||||
|  | ||||
| 		this.basic = new MeshBasicMaterial(); | ||||
|  | ||||
| 		this.fsQuad = new FullScreenQuad( null ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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(); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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 ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	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; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	getSeperableBlurMaterial( kernelRadius ) { | ||||
|  | ||||
| 		const coefficients = []; | ||||
|  | ||||
| 		for ( let i = 0; i < kernelRadius; i ++ ) { | ||||
|  | ||||
| 			coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		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: | ||||
| 				`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 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; | ||||
| 						weightSum += 2.0 * w; | ||||
| 					} | ||||
| 					gl_FragColor = vec4(diffuseSum/weightSum, 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: | ||||
| 				`varying vec2 vUv; | ||||
| 				void main() { | ||||
| 					vUv = uv; | ||||
| 					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); | ||||
| 				}`, | ||||
|  | ||||
| 			fragmentShader: | ||||
| 				`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() { | ||||
| 					gl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) + | ||||
| 						lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) + | ||||
| 						lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) + | ||||
| 						lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) + | ||||
| 						lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) ); | ||||
| 				}` | ||||
| 		} ); | ||||
|  | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| 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