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