micro-gl 0.1.0

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.
Files changed (82) hide show
  1. package/README.md +556 -0
  2. package/package.json +37 -0
  3. package/src/2d/cameras/Camera2d.js +46 -0
  4. package/src/2d/constants.js +3 -0
  5. package/src/2d/controls/DragControls2d.js +174 -0
  6. package/src/2d/controls/PanZoomControls.js +64 -0
  7. package/src/2d/core/GpuResources2d.js +163 -0
  8. package/src/2d/core/InstancedShape2d.js +74 -0
  9. package/src/2d/core/Object2d.js +107 -0
  10. package/src/2d/core/Pipelines2d.js +110 -0
  11. package/src/2d/core/Renderer2d.js +353 -0
  12. package/src/2d/core/Scene2d.js +13 -0
  13. package/src/2d/core/Shape2d.js +13 -0
  14. package/src/2d/core/Uniforms2d.js +13 -0
  15. package/src/2d/geometries/CircleGeometry.js +27 -0
  16. package/src/2d/geometries/Geometry2d.js +108 -0
  17. package/src/2d/geometries/RectGeometry.js +23 -0
  18. package/src/2d/materials/BasicMaterial2d.js +12 -0
  19. package/src/2d/materials/Material2d.js +78 -0
  20. package/src/2d/materials/SpriteMaterial2d.js +28 -0
  21. package/src/2d/shaders/fragments.js +23 -0
  22. package/src/2d/shaders/shared.js +28 -0
  23. package/src/2d/shaders/vertexLayout.js +74 -0
  24. package/src/2d/shaders/vertexStages.js +59 -0
  25. package/src/3d/cameras/Camera.js +66 -0
  26. package/src/3d/cameras/OrthographicCamera.js +35 -0
  27. package/src/3d/cameras/PerspectiveCamera.js +25 -0
  28. package/src/3d/constants.js +18 -0
  29. package/src/3d/controls/DragControls.js +168 -0
  30. package/src/3d/controls/OrbitControls.js +125 -0
  31. package/src/3d/core/DirectionalShadowMap.js +283 -0
  32. package/src/3d/core/GpuResources.js +174 -0
  33. package/src/3d/core/InstanceMatrix.js +55 -0
  34. package/src/3d/core/InstancedBounds.js +114 -0
  35. package/src/3d/core/InstancedMesh.js +124 -0
  36. package/src/3d/core/Mesh.js +26 -0
  37. package/src/3d/core/Object3d.js +101 -0
  38. package/src/3d/core/Pipelines.js +125 -0
  39. package/src/3d/core/RayIntersection.js +184 -0
  40. package/src/3d/core/Raycaster.js +246 -0
  41. package/src/3d/core/Renderer.js +492 -0
  42. package/src/3d/core/Scene.js +13 -0
  43. package/src/3d/core/ShadowPipelines.js +64 -0
  44. package/src/3d/core/Uniforms.js +132 -0
  45. package/src/3d/geometries/BoxGeometry.js +56 -0
  46. package/src/3d/geometries/Geometry.js +97 -0
  47. package/src/3d/geometries/PlaneGeometry.js +24 -0
  48. package/src/3d/geometries/SphereGeometry.js +46 -0
  49. package/src/3d/geometries/WireframeGeometry.js +39 -0
  50. package/src/3d/helpers/GridHelper.js +43 -0
  51. package/src/3d/lights/AmbientLight.js +18 -0
  52. package/src/3d/lights/DirectionalLight.js +26 -0
  53. package/src/3d/lights/DirectionalShadow.js +29 -0
  54. package/src/3d/lights/PointLight.js +23 -0
  55. package/src/3d/materials/BasicMaterial.js +11 -0
  56. package/src/3d/materials/LambertMaterial.js +13 -0
  57. package/src/3d/materials/Material.js +87 -0
  58. package/src/3d/materials/TextureMaterial.js +24 -0
  59. package/src/3d/shaders/fragments.js +34 -0
  60. package/src/3d/shaders/shadows.js +52 -0
  61. package/src/3d/shaders/shared.js +129 -0
  62. package/src/3d/shaders/vertexLayout.js +85 -0
  63. package/src/3d/shaders/vertexStages.js +70 -0
  64. package/src/core/PointerControls.js +258 -0
  65. package/src/core/Texture.js +87 -0
  66. package/src/core/createMaterialPipelineLayouts.js +114 -0
  67. package/src/core/deviceLease.js +67 -0
  68. package/src/core/generateMipmaps.js +115 -0
  69. package/src/core/indexedTriangles.js +53 -0
  70. package/src/core/initWebGpu.js +65 -0
  71. package/src/core/materialResources.js +18 -0
  72. package/src/core/objectGpuResources.js +68 -0
  73. package/src/core/pipelineConstants.js +68 -0
  74. package/src/core/rendererConfig.js +66 -0
  75. package/src/core/uploadTexture.js +57 -0
  76. package/src/index.js +68 -0
  77. package/src/math/Frustum.js +143 -0
  78. package/src/math/Mat3.js +165 -0
  79. package/src/math/Mat4.js +359 -0
  80. package/src/math/Vec2.js +72 -0
  81. package/src/math/Vec3.js +98 -0
  82. package/src/math/color.js +20 -0
@@ -0,0 +1,359 @@
1
+ /**
2
+ * A 4x4 matrix stored in column-major order (same layout WebGPU expects
3
+ * inside uniform buffers, so `elements` can be uploaded directly).
4
+ */
5
+ export class Mat4 {
6
+ constructor() {
7
+ this.elements = new Float32Array(16);
8
+ this.identity();
9
+ }
10
+
11
+ identity() {
12
+ const e = this.elements;
13
+ e.fill(0);
14
+ e[0] = e[5] = e[10] = e[15] = 1;
15
+ return this;
16
+ }
17
+
18
+ copy(m) {
19
+ this.elements.set(m.elements);
20
+ return this;
21
+ }
22
+
23
+ /** this = this * m */
24
+ multiply(m) {
25
+ return this.multiplyMatrices(this, m);
26
+ }
27
+
28
+ /** this = m * this */
29
+ premultiply(m) {
30
+ return this.multiplyMatrices(m, this);
31
+ }
32
+
33
+ /** this = a * b (safe even when this === a or this === b) */
34
+ multiplyMatrices(a, b) {
35
+ const ae = a.elements;
36
+ const be = b.elements;
37
+ const te = this.elements;
38
+
39
+ const a11 = ae[0],
40
+ a12 = ae[4],
41
+ a13 = ae[8],
42
+ a14 = ae[12];
43
+ const a21 = ae[1],
44
+ a22 = ae[5],
45
+ a23 = ae[9],
46
+ a24 = ae[13];
47
+ const a31 = ae[2],
48
+ a32 = ae[6],
49
+ a33 = ae[10],
50
+ a34 = ae[14];
51
+ const a41 = ae[3],
52
+ a42 = ae[7],
53
+ a43 = ae[11],
54
+ a44 = ae[15];
55
+
56
+ const b11 = be[0],
57
+ b12 = be[4],
58
+ b13 = be[8],
59
+ b14 = be[12];
60
+ const b21 = be[1],
61
+ b22 = be[5],
62
+ b23 = be[9],
63
+ b24 = be[13];
64
+ const b31 = be[2],
65
+ b32 = be[6],
66
+ b33 = be[10],
67
+ b34 = be[14];
68
+ const b41 = be[3],
69
+ b42 = be[7],
70
+ b43 = be[11],
71
+ b44 = be[15];
72
+
73
+ te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
74
+ te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
75
+ te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
76
+ te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
77
+
78
+ te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
79
+ te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
80
+ te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
81
+ te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
82
+
83
+ te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
84
+ te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
85
+ te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
86
+ te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
87
+
88
+ te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
89
+ te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
90
+ te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
91
+ te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
92
+
93
+ return this;
94
+ }
95
+
96
+ makeTranslation(x, y, z) {
97
+ this.identity();
98
+ const e = this.elements;
99
+ e[12] = x;
100
+ e[13] = y;
101
+ e[14] = z;
102
+ return this;
103
+ }
104
+
105
+ makeRotationX(angle) {
106
+ this.identity();
107
+ const c = Math.cos(angle),
108
+ s = Math.sin(angle);
109
+ const e = this.elements;
110
+ e[5] = c;
111
+ e[9] = -s;
112
+ e[6] = s;
113
+ e[10] = c;
114
+ return this;
115
+ }
116
+
117
+ makeRotationY(angle) {
118
+ this.identity();
119
+ const c = Math.cos(angle),
120
+ s = Math.sin(angle);
121
+ const e = this.elements;
122
+ e[0] = c;
123
+ e[8] = s;
124
+ e[2] = -s;
125
+ e[10] = c;
126
+ return this;
127
+ }
128
+
129
+ makeRotationZ(angle) {
130
+ this.identity();
131
+ const c = Math.cos(angle),
132
+ s = Math.sin(angle);
133
+ const e = this.elements;
134
+ e[0] = c;
135
+ e[4] = -s;
136
+ e[1] = s;
137
+ e[5] = c;
138
+ return this;
139
+ }
140
+
141
+ makeScale(x, y, z) {
142
+ this.identity();
143
+ const e = this.elements;
144
+ e[0] = x;
145
+ e[5] = y;
146
+ e[10] = z;
147
+ return this;
148
+ }
149
+
150
+ /**
151
+ * Builds a transform from position, Euler rotation (XYZ order, radians)
152
+ * and scale: this = T * Rx * Ry * Rz * S
153
+ */
154
+ compose(position, rotation, scale) {
155
+ this.makeTranslation(position.x, position.y, position.z);
156
+ if (rotation.x !== 0) this.multiply(_tmp.makeRotationX(rotation.x));
157
+ if (rotation.y !== 0) this.multiply(_tmp.makeRotationY(rotation.y));
158
+ if (rotation.z !== 0) this.multiply(_tmp.makeRotationZ(rotation.z));
159
+ if (scale.x !== 1 || scale.y !== 1 || scale.z !== 1) {
160
+ this.multiply(_tmp.makeScale(scale.x, scale.y, scale.z));
161
+ }
162
+ return this;
163
+ }
164
+
165
+ /**
166
+ * Perspective projection mapping depth to the [0, 1] range used by WebGPU.
167
+ * @param {number} fovY vertical field of view in radians
168
+ */
169
+ perspective(fovY, aspect, near, far) {
170
+ const e = this.elements;
171
+ const f = 1 / Math.tan(fovY / 2);
172
+ e.fill(0);
173
+ e[0] = f / aspect;
174
+ e[5] = f;
175
+ e[10] = far / (near - far);
176
+ e[11] = -1;
177
+ e[14] = (far * near) / (near - far);
178
+ return this;
179
+ }
180
+
181
+ /**
182
+ * Orthographic projection mapping depth to the [0, 1] range used by WebGPU.
183
+ */
184
+ orthographic(left, right, bottom, top, near, far) {
185
+ const e = this.elements;
186
+ e.fill(0);
187
+ e[0] = 2 / (right - left);
188
+ e[5] = 2 / (top - bottom);
189
+ e[10] = 1 / (near - far);
190
+ e[12] = (left + right) / (left - right);
191
+ e[13] = (bottom + top) / (bottom - top);
192
+ e[14] = near / (near - far);
193
+ e[15] = 1;
194
+ return this;
195
+ }
196
+
197
+ /**
198
+ * Builds a world matrix positioned at `eye` and oriented to face `target`.
199
+ * Invert it to get a view matrix.
200
+ */
201
+ targetTo(eye, target, up) {
202
+ let zx = eye.x - target.x;
203
+ let zy = eye.y - target.y;
204
+ let zz = eye.z - target.z;
205
+ let len = Math.hypot(zx, zy, zz);
206
+ if (len > BASIS_EPSILON) {
207
+ zx /= len;
208
+ zy /= len;
209
+ zz /= len;
210
+ } else {
211
+ // Eye and target coincide, so retain a valid, neutral orientation.
212
+ zx = 0;
213
+ zy = 0;
214
+ zz = 1;
215
+ }
216
+
217
+ let xx = up.y * zz - up.z * zy;
218
+ let xy = up.z * zx - up.x * zz;
219
+ let xz = up.x * zy - up.y * zx;
220
+ len = Math.hypot(xx, xy, xz);
221
+ if (len <= BASIS_EPSILON) {
222
+ // `up` is parallel to the view direction (its magnitude is irrelevant).
223
+ // Pick a stable temporary up axis without changing the direction in
224
+ // which the camera is looking.
225
+ if (Math.abs(zy) < NEAR_VERTICAL_AXIS) {
226
+ xx = zz;
227
+ xy = 0;
228
+ xz = -zx;
229
+ } else {
230
+ xx = -zy;
231
+ xy = zx;
232
+ xz = 0;
233
+ }
234
+ len = Math.hypot(xx, xy, xz);
235
+ }
236
+ xx /= len;
237
+ xy /= len;
238
+ xz /= len;
239
+
240
+ const yx = zy * xz - zz * xy;
241
+ const yy = zz * xx - zx * xz;
242
+ const yz = zx * xy - zy * xx;
243
+
244
+ const e = this.elements;
245
+ e[0] = xx;
246
+ e[1] = xy;
247
+ e[2] = xz;
248
+ e[3] = 0;
249
+ e[4] = yx;
250
+ e[5] = yy;
251
+ e[6] = yz;
252
+ e[7] = 0;
253
+ e[8] = zx;
254
+ e[9] = zy;
255
+ e[10] = zz;
256
+ e[11] = 0;
257
+ e[12] = eye.x;
258
+ e[13] = eye.y;
259
+ e[14] = eye.z;
260
+ e[15] = 1;
261
+ return this;
262
+ }
263
+
264
+ /** Inverts this matrix, throwing when no inverse exists. */
265
+ invert() {
266
+ if (!this.tryInvert()) {
267
+ throw new RangeError('Cannot invert a singular Mat4');
268
+ }
269
+ return this;
270
+ }
271
+
272
+ /**
273
+ * Attempts to invert this matrix without changing it when it is singular.
274
+ * Returns whether the inverse was written.
275
+ */
276
+ tryInvert() {
277
+ const e = this.elements;
278
+ const a00 = e[0],
279
+ a01 = e[1],
280
+ a02 = e[2],
281
+ a03 = e[3];
282
+ const a10 = e[4],
283
+ a11 = e[5],
284
+ a12 = e[6],
285
+ a13 = e[7];
286
+ const a20 = e[8],
287
+ a21 = e[9],
288
+ a22 = e[10],
289
+ a23 = e[11];
290
+ const a30 = e[12],
291
+ a31 = e[13],
292
+ a32 = e[14],
293
+ a33 = e[15];
294
+
295
+ const b00 = a00 * a11 - a01 * a10;
296
+ const b01 = a00 * a12 - a02 * a10;
297
+ const b02 = a00 * a13 - a03 * a10;
298
+ const b03 = a01 * a12 - a02 * a11;
299
+ const b04 = a01 * a13 - a03 * a11;
300
+ const b05 = a02 * a13 - a03 * a12;
301
+ const b06 = a20 * a31 - a21 * a30;
302
+ const b07 = a20 * a32 - a22 * a30;
303
+ const b08 = a20 * a33 - a23 * a30;
304
+ const b09 = a21 * a32 - a22 * a31;
305
+ const b10 = a21 * a33 - a23 * a31;
306
+ const b11 = a22 * a33 - a23 * a32;
307
+
308
+ let det =
309
+ b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
310
+ if (det === 0 || !Number.isFinite(det)) return false;
311
+ det = 1 / det;
312
+
313
+ e[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
314
+ e[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
315
+ e[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
316
+ e[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
317
+ e[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
318
+ e[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
319
+ e[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
320
+ e[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
321
+ e[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
322
+ e[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
323
+ e[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
324
+ e[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
325
+ e[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
326
+ e[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
327
+ e[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
328
+ e[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
329
+ return true;
330
+ }
331
+
332
+ transpose() {
333
+ const e = this.elements;
334
+ let t;
335
+ t = e[1];
336
+ e[1] = e[4];
337
+ e[4] = t;
338
+ t = e[2];
339
+ e[2] = e[8];
340
+ e[8] = t;
341
+ t = e[3];
342
+ e[3] = e[12];
343
+ e[12] = t;
344
+ t = e[6];
345
+ e[6] = e[9];
346
+ e[9] = t;
347
+ t = e[7];
348
+ e[7] = e[13];
349
+ e[13] = t;
350
+ t = e[11];
351
+ e[11] = e[14];
352
+ e[14] = t;
353
+ return this;
354
+ }
355
+ }
356
+
357
+ const BASIS_EPSILON = 1e-12;
358
+ const NEAR_VERTICAL_AXIS = 1 - 1e-6;
359
+ const _tmp = new Mat4();
@@ -0,0 +1,72 @@
1
+ /**
2
+ * A 2-component vector. Used for positions and scales in the 2D engine.
3
+ */
4
+ export class Vec2 {
5
+ constructor(x = 0, y = 0) {
6
+ this.x = x;
7
+ this.y = y;
8
+ }
9
+
10
+ set(x, y) {
11
+ this.x = x;
12
+ this.y = y;
13
+ return this;
14
+ }
15
+
16
+ copy(v) {
17
+ this.x = v.x;
18
+ this.y = v.y;
19
+ return this;
20
+ }
21
+
22
+ clone() {
23
+ return new Vec2(this.x, this.y);
24
+ }
25
+
26
+ add(v) {
27
+ this.x += v.x;
28
+ this.y += v.y;
29
+ return this;
30
+ }
31
+
32
+ sub(v) {
33
+ this.x -= v.x;
34
+ this.y -= v.y;
35
+ return this;
36
+ }
37
+
38
+ subVectors(a, b) {
39
+ this.x = a.x - b.x;
40
+ this.y = a.y - b.y;
41
+ return this;
42
+ }
43
+
44
+ multiplyScalar(s) {
45
+ this.x *= s;
46
+ this.y *= s;
47
+ return this;
48
+ }
49
+
50
+ dot(v) {
51
+ return this.x * v.x + this.y * v.y;
52
+ }
53
+
54
+ /** Transforms this vector as a point by a Mat3 (affine, w = 1). */
55
+ applyMat3(m) {
56
+ const e = m.elements;
57
+ const { x, y } = this;
58
+ this.x = e[0] * x + e[4] * y + e[8];
59
+ this.y = e[1] * x + e[5] * y + e[9];
60
+ return this;
61
+ }
62
+
63
+ length() {
64
+ return Math.hypot(this.x, this.y);
65
+ }
66
+
67
+ normalize() {
68
+ const len = this.length();
69
+ if (len > 0) this.multiplyScalar(1 / len);
70
+ return this;
71
+ }
72
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * A 3-component vector. Used for positions, directions, scales and colors.
3
+ */
4
+ export class Vec3 {
5
+ constructor(x = 0, y = 0, z = 0) {
6
+ this.x = x;
7
+ this.y = y;
8
+ this.z = z;
9
+ }
10
+
11
+ set(x, y, z) {
12
+ this.x = x;
13
+ this.y = y;
14
+ this.z = z;
15
+ return this;
16
+ }
17
+
18
+ copy(v) {
19
+ this.x = v.x;
20
+ this.y = v.y;
21
+ this.z = v.z;
22
+ return this;
23
+ }
24
+
25
+ clone() {
26
+ return new Vec3(this.x, this.y, this.z);
27
+ }
28
+
29
+ add(v) {
30
+ this.x += v.x;
31
+ this.y += v.y;
32
+ this.z += v.z;
33
+ return this;
34
+ }
35
+
36
+ sub(v) {
37
+ this.x -= v.x;
38
+ this.y -= v.y;
39
+ this.z -= v.z;
40
+ return this;
41
+ }
42
+
43
+ subVectors(a, b) {
44
+ this.x = a.x - b.x;
45
+ this.y = a.y - b.y;
46
+ this.z = a.z - b.z;
47
+ return this;
48
+ }
49
+
50
+ multiplyScalar(s) {
51
+ this.x *= s;
52
+ this.y *= s;
53
+ this.z *= s;
54
+ return this;
55
+ }
56
+
57
+ dot(v) {
58
+ return this.x * v.x + this.y * v.y + this.z * v.z;
59
+ }
60
+
61
+ crossVectors(a, b) {
62
+ const ax = a.x,
63
+ ay = a.y,
64
+ az = a.z;
65
+ const bx = b.x,
66
+ by = b.y,
67
+ bz = b.z;
68
+ this.x = ay * bz - az * by;
69
+ this.y = az * bx - ax * bz;
70
+ this.z = ax * by - ay * bx;
71
+ return this;
72
+ }
73
+
74
+ /**
75
+ * Transforms this vector as a point by a Mat4, including the
76
+ * perspective divide (so it also works with projection matrices).
77
+ */
78
+ applyMat4(m) {
79
+ const e = m.elements;
80
+ const { x, y, z } = this;
81
+ const inverseW =
82
+ 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
83
+ this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * inverseW;
84
+ this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * inverseW;
85
+ this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * inverseW;
86
+ return this;
87
+ }
88
+
89
+ length() {
90
+ return Math.hypot(this.x, this.y, this.z);
91
+ }
92
+
93
+ normalize() {
94
+ const len = this.length();
95
+ if (len > 0) this.multiplyScalar(1 / len);
96
+ return this;
97
+ }
98
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * sRGB <-> linear conversion for a single color channel (the exact
3
+ * piecewise curves, matching what the GPU applies to '-srgb' texture
4
+ * formats).
5
+ *
6
+ * The engine's color convention: the colors you author — material,
7
+ * light and instance colors, 0..1 — are sRGB display values, the same
8
+ * values you would type into a CSS color. The renderer decodes them to
9
+ * linear before uploading, all shading happens in linear space, and
10
+ * the sRGB render attachment encodes the result for the swap chain after
11
+ * linear-space blending and multisample resolve.
12
+ */
13
+ export function srgbToLinear(c) {
14
+ return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
15
+ }
16
+
17
+ /** The inverse of srgbToLinear. */
18
+ export function linearToSrgb(c) {
19
+ return c <= 0.0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;
20
+ }