Image Gallery in WebVR with Transitions
Transitions in WebVR
Today, we’ll be using WebGLRenderTarget
to create a transition between two scenes. WebGLRenderTarget
will help us to create postprocessing effects to create the transitions between scenes.
This is part of #DaysInVR series. View All VR Projects Yesterday, we learnt how to create music visualization in WebVR. Today, we’ll see how to create image gallery in WebVR with transitions.
Join 6000+ Students
Upgrade your programming skills to include Virtual Reality. A premium step-by-step training course to get you building real world Virtual Reality apps and website components. You’ll have access to 40+ WebVR & Unity lessons along with their source code.
Start Learning Now
Creating the scenes
We’ll first create our required scenes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
function Scene(filename) { this.effect = new THREE.VREffect(renderer); this.effect.setSize(window.innerWidth, window.innerHeight); this.scene = new THREE.Scene(); var geometry = new THREE.SphereGeometry(500, 60, 40); var texture = new THREE.TextureLoader().load('/common/'+filename+'.jpg'); var material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide }); this.mesh = new THREE.Mesh(geometry, material); this.mesh.position.set(0, controls.userHeight, -1); this.scene.add(this.mesh); renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false }; this.fbo = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, renderTargetParameters ); this.render = function(rtt) { if (rtt) { this.effect.render(this.scene, camera, this.fbo, true); } else { this.effect.render(this.scene, camera); } } } |
We’re creating a similar mesh, that we created back in our 360 photos in VR tutorial. The difference is we have added WebGLRenderTarget
.
Creating the transition
We’ll be using ShaderMaterial
to create the material for transition. We’ll loop through 5 type of transition using different textures.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
this.quadmaterial = new THREE.ShaderMaterial( { uniforms: { tDiffuse1: { value: null }, tDiffuse2: { value: null }, mixRatio: { value: 0.0 }, threshold: { value: 0.1 }, useTexture: { value: 1 }, tMixTexture: { value: this.textures[ 0 ] } }, vertexShader: [ "varying vec2 vUv;", "void main() {", "vUv = vec2( uv.x, uv.y );", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join( "\n" ), fragmentShader: [ "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 );", "}", "}" ].join( "\n" ) } ); |
We’ll be using an OrthographicCamera
and PlaneBufferGeometry
to create the mesh for transitions. The render
function of the Transition
function will be responsible for rendering all the scenes and doing the actual transition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Transition animation if ( transitionParams.animateTransition ) { var t = ( 1 + Math.sin( transitionParams.transitionSpeed * clock.getElapsedTime() / Math.PI ) ) / 2; transitionParams.transition = THREE.Math.smoothstep( t, 0.3, 0.7 ); // Change the current alpha texture after each transition if ( transitionParams.loopTexture && ( transitionParams.transition == 0 || transitionParams.transition == 1 ) ) { if ( this.needChange ) { transitionParams.texture = ( transitionParams.texture + 1 ) % this.textures.length; this.quadmaterial.uniforms.tMixTexture.value = this.textures[ transitionParams.texture ]; this.needChange = false; } } else this.needChange = true; } this.quadmaterial.uniforms.mixRatio.value = transitionParams.transition; // Prevent render both scenes when it's not necessary if ( transitionParams.transition == 0 ) { this.sceneB.render( false ); } else if ( transitionParams.transition == 1 ) { this.sceneA.render( false ); } else { // When 0<transition<1 render transition between two scenes this.sceneA.render( true ); this.sceneB.render( true ); this.effect.render( this.scene, this.cameraOrtho, null, true ); } |
We have to call this render function inside our animate()
function for the entire system to work. You can check out the full source to get a complete picture of the code.
Its your turn
Try adding more panos and even videos to the transition group. Don’t forget to share what you’ve made in the comments below.
Download Source Code
Kickstart VR development by downloading source code for this project. You’ll have instant access to source code and asset files. You can use them in your personal or commercial projects.
Wow!