194 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			194 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 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 }; |