playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
56 lines (55 loc) • 1.55 kB
JavaScript
const floatView = new Float32Array(1);
const int32View = new Int32Array(floatView.buffer);
class FloatPacking {
/**
* Packs a float to a 16-bit half-float representation used by the GPU.
*
* @param {number} value - The float value to pack.
* @returns {number} The 16-bit half-float representation as an integer.
* @example
* const half = pc.FloatPacking.float2Half(1.5);
*/
static float2Half(value) {
floatView[0] = value;
const x = int32View[0];
let bits = x >> 16 & 32768;
let m = x >> 12 & 2047;
const e = x >> 23 & 255;
if (e < 103) {
return bits;
}
if (e > 142) {
bits |= 31744;
bits |= (e === 255 ? 0 : 1) && x & 8388607;
return bits;
}
if (e < 113) {
m |= 2048;
bits |= (m >> 114 - e) + (m >> 113 - e & 1);
return bits;
}
bits |= e - 112 << 10 | m >> 1;
bits += m & 1;
return bits;
}
/**
* Converts bits of a 32-bit float into RGBA8 format and stores the result in a provided color.
* The float can be reconstructed in shader using the uintBitsToFloat instruction.
*
* @param {number} value - The float value to convert.
* @param {Color} data - The color to store the RGBA8 packed value in.
*
* @ignore
*/
static float2RGBA8(value, data) {
floatView[0] = value;
const intBits = int32View[0];
data.r = (intBits >> 24 & 255) / 255;
data.g = (intBits >> 16 & 255) / 255;
data.b = (intBits >> 8 & 255) / 255;
data.a = (intBits & 255) / 255;
}
}
export {
FloatPacking
};