@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
164 lines (141 loc) • 4.46 kB
JavaScript
import { CubeTextureLoader, LinearFilter, PMREMGenerator, sRGBEncoding, TextureLoader, UnsignedByteType } from "three";
import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
import { HDRCubeTextureLoader } from "three/examples/jsm/loaders/HDRCubeTextureLoader.js";
import { noop } from "../../../../core/function/noop.js";
import { computeFileExtension } from "../../../../core/path/computeFileExtension.js";
/**
*
* @param {string[]|string} paths
* @return {Promise<THREE.CubeTexture>}
*/
function load_cube_texture(paths) {
// piece-wise cubemap, a collection of images for each face
const cubeTextureLoader = new CubeTextureLoader();
return new Promise((resolve, reject) => {
cubeTextureLoader.load(
paths,
texture => {
texture.magFilter = LinearFilter;
texture.encoding = sRGBEncoding;
resolve(texture);
},
noop,
reject
);
});
}
/**
*
* @param {string[]|string} paths
* @return {Promise<THREE.CubeTexture>}
*/
function load_hdr_cube_texture(paths) {
// piece-wise cubemap, a collection of images for each face
const cubeTextureLoader = new HDRCubeTextureLoader();
return new Promise((resolve, reject) => {
cubeTextureLoader.load(
paths,
texture => {
resolve(texture);
},
noop,
reject
);
});
}
/**
*
* @param {string} path
* @return {Promise<THREE.Texture>}
*/
function load_exr_texture(path) {
return new Promise((resolve, reject) => {
new EXRLoader()
.setDataType(UnsignedByteType)
.load(path, texture => {
resolve(texture);
}, noop, reject);
})
}
/**
*
* @param {string} path
* @return {Promise<THREE.Texture>}
*/
function load_standard_texture(path) {
return new Promise((resolve, reject) => {
new TextureLoader()
.load(path, texture => {
texture.encoding = sRGBEncoding;
resolve(texture);
}, noop, reject);
})
}
/**
*
* @param {string|string[]} path
* @param {THREE.WebGLRenderer} [renderer]
* @param {boolean} [original]
* @param {boolean} [filtered]
* @returns {{original?:THREE.CubeTexture, filtered?: THREE.CubeTexture}}
*/
export async function load_environment_map({ path, renderer, original = false, filtered = true }) {
/**
* @type {string} 'e' or 'c'
*/
let type;
/**
* @type {THREE.WebGLCubeRenderTarget}
*/
let cube_rt;
/**
* @type {THREE.Texture|THREE.CubeTexture}
*/
let texture;
if (Array.isArray(path)) {
const ext = computeFileExtension(path[0]);
if (ext === 'hdr') {
texture = await load_hdr_cube_texture(path);
} else {
texture = await load_cube_texture(path);
}
type = 'c';
} else if (typeof path === 'string') {
// single cubemap
const extension = computeFileExtension(path).toLowerCase();
if (extension === 'exr') {
texture = await load_exr_texture(path);
} else if (extension === 'jpg') {
texture = await load_standard_texture(path);
} else {
// unsupported extension
throw new Error(`Unsupported cube map texture extension '${extension}'`);
}
type = 'e';
} else {
throw new Error(`Unsupported parameter format: '${path}'`);
}
const result = {};
if (filtered) {
if (renderer === undefined) {
throw new Error('renderer argument not supplied, expected a WebGLRenderer');
}
const pmremGenerator = new PMREMGenerator(renderer);
if (type === 'c') {
cube_rt = pmremGenerator.fromCubemap(texture);
} else if (type === 'e') {
cube_rt = pmremGenerator.fromEquirectangular(texture);
} else {
throw new Error(`Unsupported cubemap type '${type}'`);
}
pmremGenerator.dispose();
result.filtered = cube_rt.texture;
}
if (original) {
result.original = texture;
} else {
// cleanup
texture.dispose();
}
return result;
}