UNPKG

@google/model-viewer

Version:

Easily display interactive 3D models on the web and in AR!

172 lines (156 loc) 6.22 kB
/** * @author Richard M. / https://github.com/richardmonette * @author WestLangley / http://github.com/WestLangley */ import * as ThreeModule from 'three'; const THREE = Object.assign({}, ThreeModule); export const CubemapGenerator = 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(); // NOTE(cdata): Remove reference to large texture so that it can be GC'd: mesh.material.uniforms.tEquirect.value = null; return camera.renderTarget; }; // export const EquirectangularToCubeGenerator = 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; })(); //# sourceMappingURL=EquirectangularToCubeGenerator.js.map