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