UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

72 lines (52 loc) 2.36 kB
const _floatView = new Float32Array(1); const _int32View = new Int32Array(_floatView.buffer); /** * Converts float32 to float16 (encoded as uint16 value). * @param {number} val * @returns {number} */ export function to_half_float_uint16(val) { let _val = val; // Only clamp finite overflow; leave NaN and ±Infinity to the special-value // branch (e === 255) below so their bit patterns are preserved. if (Number.isFinite(_val) && _val > 65504) { console.warn('to_half_float_uint16(): value exceeds 65504.'); _val = 65504; // maximum representable value in float16 } // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410 /* This method is faster than the OpenEXR implementation (very often used, eg. in Ogre), with the additional benefit of rounding, inspired by James Tursa's half-precision code. */ _floatView[0] = _val; const x = _int32View[0]; let bits = (x >> 16) & 0x8000; /* Get the sign */ let m = (x >> 12) & 0x07ff; /* Keep one extra bit for rounding */ const e = (x >> 23) & 0xff; /* Using int is faster here */ /* If zero, or denormal, or exponent underflows too much for a denormal * half, return signed zero. */ if (e < 103) return bits; /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */ if (e > 142) { bits |= 0x7c00; // Preserve NaN: a float32 with exponent 0xff and a non-zero mantissa is // NaN. Set the high mantissa bit so the half-float result decodes as a // quiet NaN rather than Infinity. if (e === 255 && (x & 0x007fffff) !== 0) { bits |= 0x0200; } return bits; } /* If exponent underflows but not too much, return a denormal */ if (e < 113) { m |= 0x0800; /* Extra rounding may overflow and set mantissa to 0 and exponent * to 1, which is OK. */ bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); return bits; } bits |= ((e - 112) << 10) | (m >> 1); /* Extra rounding. An overflow will set mantissa to 0 and increment the exponent, which is OK. */ bits += m & 1; return bits; }