@google/model-viewer
Version:
Easily display interactive 3D models on the web and in AR!
172 lines (156 loc) • 6.22 kB
JavaScript
/**
* @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