UNPKG

threepipe

Version:

A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.

76 lines 3.51 kB
import { DataTexture, DataUtils, FileLoader, FloatType, HalfFloatType, LinearFilter, RGBAFormat, SRGBColorSpace, } from 'three'; import { imageUrlToImageData } from 'ts-browser-helpers'; /** * 8bit HDR image in png format * not properly working with files from hdrpng.js but used in {@link GLTFViewerConfigExtension}, so a slightly modified version is used here */ export class RGBEPNGLoader extends FileLoader { constructor(manager) { super(manager); this.type = HalfFloatType; } async loadAsync(url, onProgress) { const image = await this.parseAsync(url, onProgress, false); const texture = new DataTexture(image.data, image.width, image.height, RGBAFormat, this.type); texture.needsUpdate = true; texture.flipY = true; texture.colorSpace = SRGBColorSpace; texture.minFilter = LinearFilter; texture.magFilter = LinearFilter; texture.source.data.complete = true; return texture; } async parseAsync(url, onProgress, isFloat16Data = false) { let created = false; if (!url.startsWith('data:') && !url.startsWith('blob:')) { this.responseType = 'blob'; const blob = await super.loadAsync(url, onProgress); // url = await blobToDataURL(blob) // console.log(url) // url = url.replace('application/octet-stream', 'image/png') url = URL.createObjectURL(blob); created = true; } const imageData = await imageUrlToImageData(url); if (created) URL.revokeObjectURL(url); let aType = Uint8Array; if (this.type === HalfFloatType) aType = Uint16Array; else if (this.type === FloatType) aType = Float32Array; const buffer = rgbeToHalfFloat(imageData.data, 4, aType, isFloat16Data); return { data: buffer, width: imageData.width, height: imageData.height }; } setDataType(value) { this.type = value; return this; } } // adapted from https://github.com/enkimute/hdrpng.js/blob/3a62b3ae2940189777df9f669df5ece3e78d9c16/hdrpng.js#L253 // channels = 4 for RGBA data or 3 for RGB data. res to use with THREE.DataTexture function rgbeToHalfFloat(buffer, channels = 3, type = Uint16Array, float16Data = false) { let s; const l = buffer.byteLength >> 2; const res = new type(l * channels); for (let i = 0; i < l; i++) { s = Math.pow(2, buffer[i * 4 + 3] - (128 + 8)); if (float16Data) { res[i * channels] = Math.min(buffer[i * 4] * s, 65504); res[i * channels + 1] = Math.min(buffer[i * 4 + 1] * s, 65504); res[i * channels + 2] = Math.min(buffer[i * 4 + 2] * s, 65504); } else { res[i * channels] = DataUtils.toHalfFloat(Math.min(buffer[i * 4] * s, 65504)); res[i * channels + 1] = DataUtils.toHalfFloat(Math.min(buffer[i * 4 + 1] * s, 65504)); res[i * channels + 2] = DataUtils.toHalfFloat(Math.min(buffer[i * 4 + 2] * s, 65504)); } // res[i * channels] = Math.min(15360, buffer[i * 4] * s) // res[i * channels + 1] = Math.min(15360, buffer[i * 4 + 1] * s) // res[i * channels + 2] = Math.min(15360, buffer[i * 4 + 2] * s) if (channels === 4) res[i * channels + 3] = DataUtils.toHalfFloat(1); // alpha is always 1 // todo: handle for uint8 and float32 } return res; } //# sourceMappingURL=RGBEPNGLoader.js.map