| |
| |
| |
| |
|
|
| THREE.CubemapGenerator = function ( renderer ) { |
|
|
| this.renderer = renderer; |
|
|
| }; |
|
|
| THREE.CubemapGenerator.prototype.fromEquirectangular = function ( texture, options ) { |
|
|
| options = options || {}; |
|
|
| var scene = new THREE.Scene(); |
|
|
| var shader = { |
|
|
| uniforms: { |
| tEquirect: { value: null }, |
| }, |
|
|
| vertexShader: |
|
|
| ` |
| varying vec3 vWorldDirection; |
| |
| //include <common> |
| vec3 transformDirection( in vec3 dir, in mat4 matrix ) { |
| |
| return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); |
| |
| } |
| |
| void main() { |
| |
| vWorldDirection = transformDirection( position, modelMatrix ); |
| |
| #include <begin_vertex> |
| #include <project_vertex> |
| |
| } |
| `, |
|
|
| fragmentShader: |
|
|
| ` |
| uniform sampler2D tEquirect; |
| |
| varying vec3 vWorldDirection; |
| |
| //include <common> |
| #define RECIPROCAL_PI 0.31830988618 |
| #define RECIPROCAL_PI2 0.15915494 |
| |
| void main() { |
| |
| vec3 direction = normalize( vWorldDirection ); |
| |
| vec2 sampleUV; |
| |
| sampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5; |
| |
| sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5; |
| |
| gl_FragColor = texture2D( tEquirect, sampleUV ); |
| |
| } |
| ` |
| }; |
|
|
| var material = new THREE.ShaderMaterial( { |
|
|
| type: 'CubemapFromEquirect', |
|
|
| uniforms: THREE.UniformsUtils.clone( shader.uniforms ), |
| vertexShader: shader.vertexShader, |
| fragmentShader: shader.fragmentShader, |
| side: THREE.BackSide, |
| blending: THREE.NoBlending |
|
|
| } ); |
|
|
| material.uniforms.tEquirect.value = texture; |
|
|
| var mesh = new THREE.Mesh( new THREE.BoxBufferGeometry( 5, 5, 5 ), material ); |
|
|
| scene.add( mesh ); |
|
|
| var resolution = options.resolution || 512; |
|
|
| var params = { |
| type: texture.type, |
| format: texture.format, |
| encoding: texture.encoding, |
| generateMipmaps: ( options.generateMipmaps !== undefined ) ? options.generateMipmaps : texture.generateMipmaps, |
| minFilter: ( options.minFilter !== undefined ) ? options.minFilter : texture.minFilter, |
| magFilter: ( options.magFilter !== undefined ) ? options.magFilter : texture.magFilter |
| }; |
|
|
| var camera = new THREE.CubeCamera( 1, 10, resolution, params ); |
|
|
| camera.update( this.renderer, scene ); |
|
|
| mesh.geometry.dispose(); |
| mesh.material.dispose(); |
|
|
| return camera.renderTarget; |
|
|
| }; |
|
|
| |
|
|
| THREE.EquirectangularToCubeGenerator = ( function () { |
|
|
| var camera = new THREE.PerspectiveCamera( 90, 1, 0.1, 10 ); |
| var scene = new THREE.Scene(); |
| var boxMesh = new THREE.Mesh( new THREE.BoxBufferGeometry( 1, 1, 1 ), getShader() ); |
| boxMesh.material.side = THREE.BackSide; |
| scene.add( boxMesh ); |
|
|
| var EquirectangularToCubeGenerator = function ( sourceTexture, options ) { |
|
|
| options = options || {}; |
|
|
| this.sourceTexture = sourceTexture; |
| this.resolution = options.resolution || 512; |
|
|
| this.views = [ |
| { t: [ 1, 0, 0 ], u: [ 0, - 1, 0 ] }, |
| { t: [ - 1, 0, 0 ], u: [ 0, - 1, 0 ] }, |
| { t: [ 0, 1, 0 ], u: [ 0, 0, 1 ] }, |
| { t: [ 0, - 1, 0 ], u: [ 0, 0, - 1 ] }, |
| { t: [ 0, 0, 1 ], u: [ 0, - 1, 0 ] }, |
| { t: [ 0, 0, - 1 ], u: [ 0, - 1, 0 ] }, |
| ]; |
|
|
| var params = { |
| format: options.format || this.sourceTexture.format, |
| magFilter: this.sourceTexture.magFilter, |
| minFilter: this.sourceTexture.minFilter, |
| type: options.type || this.sourceTexture.type, |
| generateMipmaps: this.sourceTexture.generateMipmaps, |
| anisotropy: this.sourceTexture.anisotropy, |
| encoding: this.sourceTexture.encoding |
| }; |
|
|
| this.renderTarget = new THREE.WebGLRenderTargetCube( this.resolution, this.resolution, params ); |
|
|
| }; |
|
|
| EquirectangularToCubeGenerator.prototype = { |
|
|
| constructor: EquirectangularToCubeGenerator, |
|
|
| update: function ( renderer ) { |
|
|
| var currentRenderTarget = renderer.getRenderTarget(); |
|
|
| boxMesh.material.uniforms.equirectangularMap.value = this.sourceTexture; |
|
|
| for ( var i = 0; i < 6; i ++ ) { |
|
|
| var v = this.views[ i ]; |
|
|
| camera.position.set( 0, 0, 0 ); |
| camera.up.set( v.u[ 0 ], v.u[ 1 ], v.u[ 2 ] ); |
| camera.lookAt( v.t[ 0 ], v.t[ 1 ], v.t[ 2 ] ); |
|
|
| renderer.setRenderTarget( this.renderTarget, i ); |
| renderer.clear(); |
| renderer.render( scene, camera ); |
|
|
| } |
|
|
| renderer.setRenderTarget( currentRenderTarget ); |
|
|
| return this.renderTarget.texture; |
|
|
| }, |
|
|
| dispose: function () { |
|
|
| this.renderTarget.dispose(); |
|
|
| } |
|
|
| }; |
|
|
| function getShader() { |
|
|
| var shaderMaterial = new THREE.ShaderMaterial( { |
|
|
| uniforms: { |
| "equirectangularMap": { value: null }, |
| }, |
|
|
| vertexShader: |
| "varying vec3 localPosition;\n\ |
| \n\ |
| void main() {\n\ |
| localPosition = position;\n\ |
| gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\ |
| }", |
|
|
| fragmentShader: |
| "#include <common>\n\ |
| varying vec3 localPosition;\n\ |
| uniform sampler2D equirectangularMap;\n\ |
| \n\ |
| vec2 EquirectangularSampleUV(vec3 v) {\n\ |
| vec2 uv = vec2(atan(v.z, v.x), asin(v.y));\n\ |
| uv *= vec2(0.1591, 0.3183); // inverse atan\n\ |
| uv += 0.5;\n\ |
| return uv;\n\ |
| }\n\ |
| \n\ |
| void main() {\n\ |
| vec2 uv = EquirectangularSampleUV(normalize(localPosition));\n\ |
| gl_FragColor = texture2D(equirectangularMap, uv);\n\ |
| }", |
|
|
| blending: THREE.NoBlending |
|
|
| } ); |
|
|
| shaderMaterial.type = 'EquirectangularToCubeGenerator'; |
|
|
| return shaderMaterial; |
|
|
| } |
|
|
| return EquirectangularToCubeGenerator; |
|
|
| } )(); |
|
|