diff --git a/examples/webgl_materials_cars_parallaxbarrier.html b/examples/webgl_materials_cars_parallaxbarrier.html new file mode 100644 index 0000000000000000000000000000000000000000..02998b05093b9e23225350ba8d48566a12ecb0b6 --- /dev/null +++ b/examples/webgl_materials_cars_parallaxbarrier.html @@ -0,0 +1,614 @@ + + + + three.js webgl - materials - cube reflection [cars] + + + + + + +
+
+ three.js webgl demo : + texture by Humus : + + Bugatti Veyron model + by Troyano + + +
+ +
+ + + + +
+ +
+
+ + + + + + + + + + + + diff --git a/src/extras/renderers/ParallaxBarrierWebGLRenderer.js b/src/extras/renderers/ParallaxBarrierWebGLRenderer.js new file mode 100644 index 0000000000000000000000000000000000000000..ff41b32297dbcfe04043c5f9902c80154e42cd4c --- /dev/null +++ b/src/extras/renderers/ParallaxBarrierWebGLRenderer.js @@ -0,0 +1,161 @@ +/** + * @author mrdoob / http://mrdoob.com/ + */ + +if ( THREE.WebGLRenderer ) { + + THREE.ParallaxBarrierWebGLRenderer = function ( parameters ) { + + THREE.WebGLRenderer.call( this, parameters ); + + var _this = this, _setSize = this.setSize, _render = this.render; + + var _cameraL = new THREE.PerspectiveCamera(), + _cameraR = new THREE.PerspectiveCamera(); + + var eyeRight = new THREE.Matrix4(), + eyeLeft = new THREE.Matrix4(), + focalLength = 125, + aspect, near, fov; + + _cameraL.matrixAutoUpdate = _cameraR.matrixAutoUpdate = false; + + var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat }; + + var _renderTargetL = new THREE.WebGLRenderTarget( 512, 512, _params ), + _renderTargetR = new THREE.WebGLRenderTarget( 512, 512, _params ); + + var _camera = new THREE.PerspectiveCamera( 53, 1, 1, 10000 ); + _camera.position.z = 2; + + _material = new THREE.ShaderMaterial( { + + uniforms: { + + "mapLeft": { type: "t", value: 0, texture: _renderTargetL }, + "mapRight": { type: "t", value: 1, texture: _renderTargetR } + + }, + + vertexShader: [ + + "varying vec2 vUv;", + + "void main() {", + + "vUv = vec2( uv.x, 1.0 - uv.y );", + "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", + + "}" + + ].join("\n"), + + fragmentShader: [ + + "uniform sampler2D mapLeft;", + "uniform sampler2D mapRight;", + "varying vec2 vUv;", + + "void main() {", + + "vec2 uv = vUv;", + + "if ( ( mod(gl_FragCoord.x, 2.0) ) > 1.00 ) {", + + "gl_FragColor = texture2D( mapLeft, uv );", + + "} else {", + + "gl_FragColor = texture2D( mapRight, uv );", + + "}", + + "}" + + ].join("\n") + + } ); + + var _scene = new THREE.Scene(); + _scene.add( new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), _material ) ); + + this.setSize = function ( width, height ) { + + _setSize.call( _this, width, height ); + + _renderTargetL.width = width; + _renderTargetL.height = height; + + _renderTargetR.width = width; + _renderTargetR.height = height; + + }; + + /* + * Renderer now uses an asymmetric perspective projection (http://paulbourke.net/miscellaneous/stereographics/stereorender/). + * Each camera is offset by the eye seperation and its projection matrix is also skewed asymetrically back to converge on the same + * projection plane. Added a focal length parameter to, this is where the parallax is equal to 0. + */ + + this.render = function ( scene, camera, renderTarget, forceClear ) { + + camera.update( null, true ); + + var hasCameraChanged = aspect !== camera.aspect || near !== camera.near || fov !== camera.fov; + + if( hasCameraChanged ) { + + aspect = camera.aspect; + near = camera.near; + fov = camera.fov; + + var projectionMatrix = camera.projectionMatrix.clone(), + eyeSep = focalLength / 30 * 0.5, + eyeSepOnProjection = eyeSep * near / focalLength, + ymax = near * Math.tan( fov * Math.PI / 360 ), + xmin, xmax; + + //translate xOffset + + eyeRight.n14 = eyeSep; + eyeLeft.n14 = -eyeSep; + + //For left eye + + xmin = -ymax * aspect + eyeSepOnProjection; + xmax = ymax * aspect + eyeSepOnProjection; + projectionMatrix.n11 = 2 * near / ( xmax - xmin ); + projectionMatrix.n13 = ( xmax + xmin ) / ( xmax - xmin ); + _cameraL.projectionMatrix = projectionMatrix.clone(); + + //for right eye + + xmin = -ymax * aspect - eyeSepOnProjection; + xmax = ymax * aspect - eyeSepOnProjection; + projectionMatrix.n11 = 2 * near / ( xmax - xmin ); + projectionMatrix.n13 = ( xmax + xmin ) / ( xmax - xmin ); + _cameraR.projectionMatrix = projectionMatrix.clone(); + + } + + _cameraL.matrix = camera.matrixWorld.clone().multiplySelf( eyeLeft ); + _cameraL.update( null, true ); + _cameraL.position.copy( camera.position ); + _cameraL.near = near; + _cameraL.far = camera.far; + _render.call( _this, scene, _cameraL, _renderTargetL, true ); + + _cameraR.matrix = camera.matrixWorld.clone().multiplySelf( eyeRight ); + _cameraR.update( null, true ); + _cameraR.position.copy( camera.position ); + _cameraR.near = near; + _cameraR.far = camera.far; + _render.call( _this, scene, _cameraR, _renderTargetR, true ); + + _render.call( _this, _scene, _camera ); + + }; + + }; + +};