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 };
 |