hdr-canvas 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hdr-canvas.js +289 -8
- package/dist/hdr-canvas.js.map +1 -1
- package/dist/hdr-canvas.min.js +1 -1
- package/dist/hdr-canvas.min.js.map +1 -1
- package/dist/hdr-canvas.umd.js +289 -8
- package/dist/hdr-canvas.umd.js.map +1 -1
- package/docs/release-notes-0.1.0.md +6 -6
- package/docs/release-notes-0.1.1.md +19 -0
- package/docs/release-notes-0.1.2.md +16 -0
- package/docs/release.md +13 -0
- package/package.json +15 -14
- package/scripts/check.sh +1 -0
- package/src/Float16Image.ts +20 -7
- package/src/Uint16Image.ts +1 -0
- package/src/hdr-canvas.ts +5 -2
- package/src/types/HDRCanvas.d.ts +5 -0
- package/three/HDRWebGPUBackend.js +36 -73
- package/three/HDRWebGPURenderer.js +1 -0
package/dist/hdr-canvas.umd.js
CHANGED
|
@@ -5908,6 +5908,283 @@
|
|
|
5908
5908
|
}
|
|
5909
5909
|
}
|
|
5910
5910
|
|
|
5911
|
+
/* eslint-disable no-restricted-globals, no-restricted-syntax */
|
|
5912
|
+
/* global SharedArrayBuffer */
|
|
5913
|
+
|
|
5914
|
+
|
|
5915
|
+
/** @type {<T extends (...args: any) => any>(target: T) => (thisArg: ThisType<T>, ...args: any[]) => any} */
|
|
5916
|
+
function uncurryThis(target) {
|
|
5917
|
+
return (thisArg, ...args) => {
|
|
5918
|
+
return ReflectApply(target, thisArg, args);
|
|
5919
|
+
};
|
|
5920
|
+
}
|
|
5921
|
+
|
|
5922
|
+
/** @type {(target: any, key: string | symbol) => (thisArg: any, ...args: any[]) => any} */
|
|
5923
|
+
function uncurryThisGetter(target, key) {
|
|
5924
|
+
return uncurryThis(
|
|
5925
|
+
ReflectGetOwnPropertyDescriptor(
|
|
5926
|
+
target,
|
|
5927
|
+
key
|
|
5928
|
+
).get
|
|
5929
|
+
);
|
|
5930
|
+
}
|
|
5931
|
+
|
|
5932
|
+
// Reflect
|
|
5933
|
+
const {
|
|
5934
|
+
apply: ReflectApply,
|
|
5935
|
+
getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,
|
|
5936
|
+
getPrototypeOf: ReflectGetPrototypeOf} = Reflect;
|
|
5937
|
+
|
|
5938
|
+
// Number
|
|
5939
|
+
const {
|
|
5940
|
+
EPSILON,
|
|
5941
|
+
isFinite: NumberIsFinite,
|
|
5942
|
+
isNaN: NumberIsNaN,
|
|
5943
|
+
} = Number;
|
|
5944
|
+
|
|
5945
|
+
// Symbol
|
|
5946
|
+
const {
|
|
5947
|
+
iterator: SymbolIterator,
|
|
5948
|
+
toStringTag: SymbolToStringTag} = Symbol;
|
|
5949
|
+
|
|
5950
|
+
// Math
|
|
5951
|
+
const {
|
|
5952
|
+
abs: MathAbs} = Math;
|
|
5953
|
+
|
|
5954
|
+
// ArrayBuffer
|
|
5955
|
+
const NativeArrayBuffer = ArrayBuffer;
|
|
5956
|
+
const ArrayBufferPrototype = NativeArrayBuffer.prototype;
|
|
5957
|
+
/** @type {(buffer: ArrayBuffer) => ArrayBuffer} */
|
|
5958
|
+
uncurryThisGetter(ArrayBufferPrototype, "byteLength");
|
|
5959
|
+
|
|
5960
|
+
// SharedArrayBuffer
|
|
5961
|
+
const NativeSharedArrayBuffer = typeof SharedArrayBuffer !== "undefined" ? SharedArrayBuffer : null;
|
|
5962
|
+
/** @type {(buffer: SharedArrayBuffer) => SharedArrayBuffer} */
|
|
5963
|
+
NativeSharedArrayBuffer
|
|
5964
|
+
&& uncurryThisGetter(NativeSharedArrayBuffer.prototype, "byteLength");
|
|
5965
|
+
|
|
5966
|
+
// TypedArray
|
|
5967
|
+
/** @typedef {Uint8Array|Uint8ClampedArray|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array|BigUint64Array|BigInt64Array} TypedArray */
|
|
5968
|
+
/** @type {any} */
|
|
5969
|
+
const TypedArray = ReflectGetPrototypeOf(Uint8Array);
|
|
5970
|
+
TypedArray.from;
|
|
5971
|
+
const TypedArrayPrototype = TypedArray.prototype;
|
|
5972
|
+
TypedArrayPrototype[SymbolIterator];
|
|
5973
|
+
/** @type {(typedArray: TypedArray) => IterableIterator<number>} */
|
|
5974
|
+
uncurryThis(TypedArrayPrototype.keys);
|
|
5975
|
+
/** @type {(typedArray: TypedArray) => IterableIterator<number>} */
|
|
5976
|
+
uncurryThis(
|
|
5977
|
+
TypedArrayPrototype.values
|
|
5978
|
+
);
|
|
5979
|
+
/** @type {(typedArray: TypedArray) => IterableIterator<[number, number]>} */
|
|
5980
|
+
uncurryThis(
|
|
5981
|
+
TypedArrayPrototype.entries
|
|
5982
|
+
);
|
|
5983
|
+
/** @type {(typedArray: TypedArray, array: ArrayLike<number>, offset?: number) => void} */
|
|
5984
|
+
uncurryThis(TypedArrayPrototype.set);
|
|
5985
|
+
/** @type {<T extends TypedArray>(typedArray: T) => T} */
|
|
5986
|
+
uncurryThis(
|
|
5987
|
+
TypedArrayPrototype.reverse
|
|
5988
|
+
);
|
|
5989
|
+
/** @type {<T extends TypedArray>(typedArray: T, value: number, start?: number, end?: number) => T} */
|
|
5990
|
+
uncurryThis(TypedArrayPrototype.fill);
|
|
5991
|
+
/** @type {<T extends TypedArray>(typedArray: T, target: number, start: number, end?: number) => T} */
|
|
5992
|
+
uncurryThis(
|
|
5993
|
+
TypedArrayPrototype.copyWithin
|
|
5994
|
+
);
|
|
5995
|
+
/** @type {<T extends TypedArray>(typedArray: T, compareFn?: (a: number, b: number) => number) => T} */
|
|
5996
|
+
uncurryThis(TypedArrayPrototype.sort);
|
|
5997
|
+
/** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */
|
|
5998
|
+
uncurryThis(TypedArrayPrototype.slice);
|
|
5999
|
+
/** @type {<T extends TypedArray>(typedArray: T, start?: number, end?: number) => T} */
|
|
6000
|
+
uncurryThis(
|
|
6001
|
+
TypedArrayPrototype.subarray
|
|
6002
|
+
);
|
|
6003
|
+
/** @type {((typedArray: TypedArray) => ArrayBuffer)} */
|
|
6004
|
+
uncurryThisGetter(
|
|
6005
|
+
TypedArrayPrototype,
|
|
6006
|
+
"buffer"
|
|
6007
|
+
);
|
|
6008
|
+
/** @type {((typedArray: TypedArray) => number)} */
|
|
6009
|
+
uncurryThisGetter(
|
|
6010
|
+
TypedArrayPrototype,
|
|
6011
|
+
"byteOffset"
|
|
6012
|
+
);
|
|
6013
|
+
/** @type {((typedArray: TypedArray) => number)} */
|
|
6014
|
+
uncurryThisGetter(
|
|
6015
|
+
TypedArrayPrototype,
|
|
6016
|
+
"length"
|
|
6017
|
+
);
|
|
6018
|
+
/** @type {(target: unknown) => string} */
|
|
6019
|
+
uncurryThisGetter(
|
|
6020
|
+
TypedArrayPrototype,
|
|
6021
|
+
SymbolToStringTag
|
|
6022
|
+
);
|
|
6023
|
+
|
|
6024
|
+
// Uint8Array
|
|
6025
|
+
const NativeUint8Array = Uint8Array;
|
|
6026
|
+
|
|
6027
|
+
// Uint16Array
|
|
6028
|
+
const NativeUint16Array = Uint16Array;
|
|
6029
|
+
|
|
6030
|
+
// Uint32Array
|
|
6031
|
+
const NativeUint32Array = Uint32Array;
|
|
6032
|
+
|
|
6033
|
+
// ArrayIterator
|
|
6034
|
+
/** @type {any} */
|
|
6035
|
+
const ArrayIteratorPrototype = ReflectGetPrototypeOf([][SymbolIterator]());
|
|
6036
|
+
/** @type {<T>(arrayIterator: IterableIterator<T>) => IteratorResult<T>} */
|
|
6037
|
+
uncurryThis(ArrayIteratorPrototype.next);
|
|
6038
|
+
|
|
6039
|
+
// Generator
|
|
6040
|
+
/** @type {<T = unknown, TReturn = any, TNext = unknown>(generator: Generator<T, TReturn, TNext>, value?: TNext) => T} */
|
|
6041
|
+
uncurryThis((function* () {})().next);
|
|
6042
|
+
|
|
6043
|
+
// Iterator
|
|
6044
|
+
ReflectGetPrototypeOf(ArrayIteratorPrototype);
|
|
6045
|
+
|
|
6046
|
+
const INVERSE_OF_EPSILON = 1 / EPSILON;
|
|
6047
|
+
|
|
6048
|
+
/**
|
|
6049
|
+
* rounds to the nearest value;
|
|
6050
|
+
* if the number falls midway, it is rounded to the nearest value with an even least significant digit
|
|
6051
|
+
* @param {number} num
|
|
6052
|
+
* @returns {number}
|
|
6053
|
+
*/
|
|
6054
|
+
function roundTiesToEven(num) {
|
|
6055
|
+
return (num + INVERSE_OF_EPSILON) - INVERSE_OF_EPSILON;
|
|
6056
|
+
}
|
|
6057
|
+
|
|
6058
|
+
const FLOAT16_MIN_VALUE = 6.103515625e-05;
|
|
6059
|
+
const FLOAT16_MAX_VALUE = 65504;
|
|
6060
|
+
const FLOAT16_EPSILON = 0.0009765625;
|
|
6061
|
+
|
|
6062
|
+
const FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE = FLOAT16_EPSILON * FLOAT16_MIN_VALUE;
|
|
6063
|
+
const FLOAT16_EPSILON_DEVIDED_BY_EPSILON = FLOAT16_EPSILON * INVERSE_OF_EPSILON;
|
|
6064
|
+
|
|
6065
|
+
/**
|
|
6066
|
+
* round a number to a half float number
|
|
6067
|
+
* @param {unknown} num - double float
|
|
6068
|
+
* @returns {number} half float number
|
|
6069
|
+
*/
|
|
6070
|
+
function roundToFloat16(num) {
|
|
6071
|
+
const number = +num;
|
|
6072
|
+
|
|
6073
|
+
// NaN, Infinity, -Infinity, 0, -0
|
|
6074
|
+
if (!NumberIsFinite(number) || number === 0) {
|
|
6075
|
+
return number;
|
|
6076
|
+
}
|
|
6077
|
+
|
|
6078
|
+
// finite except 0, -0
|
|
6079
|
+
const sign = number > 0 ? 1 : -1;
|
|
6080
|
+
const absolute = MathAbs(number);
|
|
6081
|
+
|
|
6082
|
+
// small number
|
|
6083
|
+
if (absolute < FLOAT16_MIN_VALUE) {
|
|
6084
|
+
return sign * roundTiesToEven(absolute / FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE) * FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE;
|
|
6085
|
+
}
|
|
6086
|
+
|
|
6087
|
+
const temp = (1 + FLOAT16_EPSILON_DEVIDED_BY_EPSILON) * absolute;
|
|
6088
|
+
const result = temp - (temp - absolute);
|
|
6089
|
+
|
|
6090
|
+
// large number
|
|
6091
|
+
if (result > FLOAT16_MAX_VALUE || NumberIsNaN(result)) {
|
|
6092
|
+
return sign * Infinity;
|
|
6093
|
+
}
|
|
6094
|
+
|
|
6095
|
+
return sign * result;
|
|
6096
|
+
}
|
|
6097
|
+
|
|
6098
|
+
const baseTable = new NativeUint16Array(512);
|
|
6099
|
+
const shiftTable = new NativeUint8Array(512);
|
|
6100
|
+
|
|
6101
|
+
for (let i = 0; i < 256; ++i) {
|
|
6102
|
+
const e = i - 127;
|
|
6103
|
+
|
|
6104
|
+
// very small number (0, -0)
|
|
6105
|
+
if (e < -24) {
|
|
6106
|
+
baseTable[i] = 0x0000;
|
|
6107
|
+
baseTable[i | 0x100] = 0x8000;
|
|
6108
|
+
shiftTable[i] = 24;
|
|
6109
|
+
shiftTable[i | 0x100] = 24;
|
|
6110
|
+
|
|
6111
|
+
// small number (denorm)
|
|
6112
|
+
} else if (e < -14) {
|
|
6113
|
+
baseTable[i] = 0x0400 >> (-e - 14);
|
|
6114
|
+
baseTable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000;
|
|
6115
|
+
shiftTable[i] = -e - 1;
|
|
6116
|
+
shiftTable[i | 0x100] = -e - 1;
|
|
6117
|
+
|
|
6118
|
+
// normal number
|
|
6119
|
+
} else if (e <= 15) {
|
|
6120
|
+
baseTable[i] = (e + 15) << 10;
|
|
6121
|
+
baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000;
|
|
6122
|
+
shiftTable[i] = 13;
|
|
6123
|
+
shiftTable[i | 0x100] = 13;
|
|
6124
|
+
|
|
6125
|
+
// large number (Infinity, -Infinity)
|
|
6126
|
+
} else if (e < 128) {
|
|
6127
|
+
baseTable[i] = 0x7c00;
|
|
6128
|
+
baseTable[i | 0x100] = 0xfc00;
|
|
6129
|
+
shiftTable[i] = 24;
|
|
6130
|
+
shiftTable[i | 0x100] = 24;
|
|
6131
|
+
|
|
6132
|
+
// stay (NaN, Infinity, -Infinity)
|
|
6133
|
+
} else {
|
|
6134
|
+
baseTable[i] = 0x7c00;
|
|
6135
|
+
baseTable[i | 0x100] = 0xfc00;
|
|
6136
|
+
shiftTable[i] = 13;
|
|
6137
|
+
shiftTable[i | 0x100] = 13;
|
|
6138
|
+
}
|
|
6139
|
+
}
|
|
6140
|
+
|
|
6141
|
+
const mantissaTable = new NativeUint32Array(2048);
|
|
6142
|
+
for (let i = 1; i < 1024; ++i) {
|
|
6143
|
+
let m = i << 13; // zero pad mantissa bits
|
|
6144
|
+
let e = 0; // zero exponent
|
|
6145
|
+
|
|
6146
|
+
// normalized
|
|
6147
|
+
while ((m & 0x00800000) === 0) {
|
|
6148
|
+
m <<= 1;
|
|
6149
|
+
e -= 0x00800000; // decrement exponent
|
|
6150
|
+
}
|
|
6151
|
+
|
|
6152
|
+
m &= -8388609; // clear leading 1 bit
|
|
6153
|
+
e += 0x38800000; // adjust bias
|
|
6154
|
+
|
|
6155
|
+
mantissaTable[i] = m | e;
|
|
6156
|
+
}
|
|
6157
|
+
for (let i = 1024; i < 2048; ++i) {
|
|
6158
|
+
mantissaTable[i] = 0x38000000 + ((i - 1024) << 13);
|
|
6159
|
+
}
|
|
6160
|
+
|
|
6161
|
+
const exponentTable = new NativeUint32Array(64);
|
|
6162
|
+
for (let i = 1; i < 31; ++i) {
|
|
6163
|
+
exponentTable[i] = i << 23;
|
|
6164
|
+
}
|
|
6165
|
+
exponentTable[31] = 0x47800000;
|
|
6166
|
+
exponentTable[32] = 0x80000000;
|
|
6167
|
+
for (let i = 33; i < 63; ++i) {
|
|
6168
|
+
exponentTable[i] = 0x80000000 + ((i - 32) << 23);
|
|
6169
|
+
}
|
|
6170
|
+
exponentTable[63] = 0xc7800000;
|
|
6171
|
+
|
|
6172
|
+
const offsetTable = new NativeUint16Array(64);
|
|
6173
|
+
for (let i = 1; i < 64; ++i) {
|
|
6174
|
+
if (i !== 32) {
|
|
6175
|
+
offsetTable[i] = 1024;
|
|
6176
|
+
}
|
|
6177
|
+
}
|
|
6178
|
+
|
|
6179
|
+
/**
|
|
6180
|
+
* returns the nearest half-precision float representation of a number
|
|
6181
|
+
* @param {number} x
|
|
6182
|
+
* @returns {number}
|
|
6183
|
+
*/
|
|
6184
|
+
function f16round(x) {
|
|
6185
|
+
return roundToFloat16(x);
|
|
6186
|
+
}
|
|
6187
|
+
|
|
5911
6188
|
class Float16Image extends HDRImage {
|
|
5912
6189
|
data;
|
|
5913
6190
|
static DEFAULT_PIXELFORMAT = "rgba-float16";
|
|
@@ -5964,17 +6241,17 @@
|
|
|
5964
6241
|
return Float16Array.from(hlg);
|
|
5965
6242
|
}
|
|
5966
6243
|
static convertArrayToRec2100_hlg(data) {
|
|
5967
|
-
const
|
|
5968
|
-
for (let i = 0; i < data.length; i
|
|
5969
|
-
const
|
|
5970
|
-
|
|
5971
|
-
uint16Data.set(pixel, i);
|
|
6244
|
+
const float16Array = new Float16Array(data.length);
|
|
6245
|
+
for (let i = 0; i < data.length; i++) {
|
|
6246
|
+
const normalizedFloat = data[i] / 255.0;
|
|
6247
|
+
float16Array[i] = f16round(normalizedFloat);
|
|
5972
6248
|
}
|
|
5973
|
-
return
|
|
6249
|
+
return float16Array;
|
|
5974
6250
|
}
|
|
5975
6251
|
pixelCallback(fn) {
|
|
5976
6252
|
for (let i = 0; i < this.data.length; i += 4) {
|
|
5977
|
-
|
|
6253
|
+
const pixel = fn(this.data[i], this.data[i + 1], this.data[i + 2], this.data[i + 3]);
|
|
6254
|
+
this.data.set(pixel, i);
|
|
5978
6255
|
}
|
|
5979
6256
|
}
|
|
5980
6257
|
static fromImageData(imageData) {
|
|
@@ -6040,6 +6317,7 @@
|
|
|
6040
6317
|
if (browserMajorVersion == null) {
|
|
6041
6318
|
console.warn(`Unsupported / untested browser (${navigator.userAgent}) detected - using more modern defaults`);
|
|
6042
6319
|
hdrOptions["colorType"] = "float16";
|
|
6320
|
+
hdrOptions["toneMapping"] = { mode: "extended" };
|
|
6043
6321
|
}
|
|
6044
6322
|
else {
|
|
6045
6323
|
if (browserMajorVersion < 134) {
|
|
@@ -6052,7 +6330,10 @@
|
|
|
6052
6330
|
return hdrOptions;
|
|
6053
6331
|
}
|
|
6054
6332
|
function initHDRCanvas(canvas) {
|
|
6055
|
-
|
|
6333
|
+
const browserMajorVersion = getBrowserVersion();
|
|
6334
|
+
if (browserMajorVersion !== null && browserMajorVersion < 134) {
|
|
6335
|
+
canvas.configureHighDynamicRange({ mode: "extended" });
|
|
6336
|
+
}
|
|
6056
6337
|
const ctx = canvas.getContext("2d", getHdrOptions());
|
|
6057
6338
|
return ctx;
|
|
6058
6339
|
}
|