@woosh/meep-engine 2.131.14 → 2.131.17

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 (101) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/src/core/codegen/LineBuilder.d.ts +4 -2
  4. package/src/core/codegen/LineBuilder.d.ts.map +1 -1
  5. package/src/core/codegen/LineBuilder.js +5 -2
  6. package/src/core/color/YCbCr/YCbCr_to_rgb_uint24.d.ts +6 -5
  7. package/src/core/color/YCbCr/YCbCr_to_rgb_uint24.d.ts.map +1 -1
  8. package/src/core/color/YCbCr/YCbCr_to_rgb_uint24.js +19 -13
  9. package/src/core/color/YCbCr/rgb_to_YCbCr_uint24.d.ts +6 -5
  10. package/src/core/color/YCbCr/rgb_to_YCbCr_uint24.d.ts.map +1 -1
  11. package/src/core/color/YCbCr/rgb_to_YCbCr_uint24.js +18 -10
  12. package/src/core/color/illuminant/D65_spd_analytical.d.ts.map +1 -1
  13. package/src/core/color/illuminant/D65_spd_analytical.js +1 -25
  14. package/src/core/color/illuminant/planckian_radiance.d.ts +8 -0
  15. package/src/core/color/illuminant/planckian_radiance.d.ts.map +1 -0
  16. package/src/core/color/illuminant/planckian_radiance.js +41 -0
  17. package/src/core/color/kelvin/kelvin_to_rgb.d.ts +11 -4
  18. package/src/core/color/kelvin/kelvin_to_rgb.d.ts.map +1 -1
  19. package/src/core/color/kelvin/kelvin_to_rgb.js +134 -30
  20. package/src/core/color/kelvin/rgb_to_kelvin.d.ts +4 -1
  21. package/src/core/color/kelvin/rgb_to_kelvin.d.ts.map +1 -1
  22. package/src/core/color/kelvin/rgb_to_kelvin.js +34 -9
  23. package/src/core/color/rgb_to_luminance.d.ts +7 -4
  24. package/src/core/color/rgb_to_luminance.d.ts.map +1 -1
  25. package/src/core/color/rgb_to_luminance.js +8 -5
  26. package/src/core/color/sRGB/linear_to_sRGB.d.ts +6 -1
  27. package/src/core/color/sRGB/linear_to_sRGB.d.ts.map +1 -1
  28. package/src/core/color/sRGB/linear_to_sRGB.js +5 -0
  29. package/src/core/color/sRGB/sRGB_to_linear.d.ts +3 -2
  30. package/src/core/color/sRGB/sRGB_to_linear.d.ts.map +1 -1
  31. package/src/core/color/sRGB/sRGB_to_linear.js +2 -1
  32. package/src/core/color/xyz/xyz_cmf_tabulated.d.ts.map +1 -1
  33. package/src/core/color/xyz/xyz_cmf_tabulated.js +174 -175
  34. package/src/core/math/frexp.d.ts.map +1 -1
  35. package/src/core/math/frexp.js +1 -0
  36. package/src/core/model/node-graph/visual/NodeDescriptionVisualRegistry.d.ts.map +1 -1
  37. package/src/core/model/node-graph/visual/NodeDescriptionVisualRegistry.js +5 -7
  38. package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts.map +1 -1
  39. package/src/core/model/node-graph/visual/NodeGraphVisualData.js +10 -12
  40. package/src/core/model/node-graph/visual/NodeVisualData.d.ts.map +1 -1
  41. package/src/core/model/node-graph/visual/NodeVisualData.js +16 -17
  42. package/src/core/model/node-graph/visual/PortVisualData.d.ts.map +1 -1
  43. package/src/core/model/node-graph/visual/PortVisualData.js +7 -9
  44. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +2 -1
  45. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +1 -1
  46. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.js +14 -14
  47. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +1 -1
  48. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.js +21 -23
  49. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +1 -1
  50. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.js +10 -12
  51. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +1 -1
  52. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.js +10 -14
  53. package/src/engine/ecs/storage/BinaryBufferDeSerializer.js +1 -1
  54. package/src/engine/graphics/particles/node-based/codegen/CodeContext.d.ts.map +1 -1
  55. package/src/engine/graphics/particles/node-based/codegen/CodeContext.js +7 -10
  56. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModule.d.ts.map +1 -1
  57. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModule.js +30 -32
  58. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleReference.d.ts.map +1 -1
  59. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleReference.js +10 -12
  60. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleRegistry.d.ts.map +1 -1
  61. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionModuleRegistry.js +5 -8
  62. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionParameterSpecification.d.ts.map +1 -1
  63. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionParameterSpecification.js +10 -12
  64. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionSignature.d.ts.map +1 -1
  65. package/src/engine/graphics/particles/node-based/codegen/modules/FunctionSignature.js +11 -13
  66. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeBinding.d.ts.map +1 -1
  67. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeBinding.js +12 -12
  68. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.d.ts +8 -18
  69. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.d.ts.map +1 -1
  70. package/src/engine/graphics/particles/node-based/particle/ParticleAttributeSpecification.js +9 -11
  71. package/src/engine/graphics/particles/node-based/particle/ParticleSpecification.d.ts.map +1 -1
  72. package/src/engine/graphics/particles/node-based/particle/ParticleSpecification.js +34 -36
  73. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderCommand.d.ts.map +1 -1
  74. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderCommand.js +10 -12
  75. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderSpecification.d.ts.map +1 -1
  76. package/src/engine/graphics/particles/node-based/rendering/ParticleRenderSpecification.js +6 -8
  77. package/src/engine/graphics/particles/particular/engine/emitter/ParticleLayer.d.ts.map +1 -1
  78. package/src/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +123 -124
  79. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.d.ts.map +1 -1
  80. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +32 -30
  81. package/src/engine/graphics/particles/particular/engine/parameter/ParameterTrack.d.ts +7 -1
  82. package/src/engine/graphics/particles/particular/engine/parameter/ParameterTrack.d.ts.map +1 -1
  83. package/src/engine/graphics/particles/particular/engine/parameter/ParameterTrack.js +6 -6
  84. package/src/engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.d.ts.map +1 -1
  85. package/src/engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.js +5 -9
  86. package/src/engine/graphics/particles/particular/engine/parameter/ParticleParameter.d.ts +10 -10
  87. package/src/engine/graphics/particles/particular/engine/parameter/ParticleParameter.d.ts.map +1 -1
  88. package/src/engine/graphics/particles/particular/engine/parameter/ParticleParameter.js +36 -29
  89. package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.d.ts.map +1 -1
  90. package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.js +29 -33
  91. package/src/view/View.d.ts.map +1 -1
  92. package/src/view/View.js +4 -6
  93. package/src/engine/graphics/particles/particular/engine/emitter/ParticleRenderProfile.d.ts +0 -14
  94. package/src/engine/graphics/particles/particular/engine/emitter/ParticleRenderProfile.d.ts.map +0 -1
  95. package/src/engine/graphics/particles/particular/engine/emitter/ParticleRenderProfile.js +0 -18
  96. package/src/engine/graphics/particles/particular/engine/emitter/ParticleRendererType.d.ts +0 -8
  97. package/src/engine/graphics/particles/particular/engine/emitter/ParticleRendererType.d.ts.map +0 -1
  98. package/src/engine/graphics/particles/particular/engine/emitter/ParticleRendererType.js +0 -10
  99. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSheet.d.ts +0 -38
  100. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSheet.d.ts.map +0 -1
  101. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSheet.js +0 -278
package/README.md CHANGED
@@ -14,13 +14,13 @@ To help get you started, various samples are provided under `/samples` folder. F
14
14
  ## Quality
15
15
 
16
16
  ### Testing
17
- Meep is covered by 2,801 handwritten unit tests, reaching 90%+ coverage in `core` and 40%+ coverage total.
17
+ Meep is covered by 2,944 handwritten unit tests, reaching 90%+ coverage in `core` and 40%+ coverage total.
18
18
 
19
19
  The aim is to [ensure quality](https://about.codecov.io/blog/the-case-against-100-code-coverage/). As a result, the tests are written to cover complex code first and to exhaustively validate critical algorithms.
20
20
  Most of the test code is significantly larger than the code that is being tested.
21
21
 
22
22
  ### Assertions
23
- Meep is covered by 3,162 asserts. [Assertions](https://en.wikipedia.org/wiki/Assertion_(software_development)) provide very extensive pre- and post-condition checks throughout the engine.
23
+ Meep is covered by 3,968 asserts. [Assertions](https://en.wikipedia.org/wiki/Assertion_(software_development)) provide very extensive pre- and post-condition checks throughout the engine.
24
24
  Asserts are intended primarily for development builds.
25
25
  To remove asserts in Vite builds, you can use `@rollup/plugin-strip` package like so:
26
26
 
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Pure JavaScript game engine. Fully featured and production ready.",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.131.14",
8
+ "version": "2.131.17",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -1,6 +1,7 @@
1
1
  export default LineBuilder;
2
2
  /**
3
3
  * Useful for generating formatted snippets of code.
4
+ *
4
5
  * @example
5
6
  * const b = new LineBuilder();
6
7
  * b.add("function hello(){");
@@ -38,9 +39,10 @@ declare class LineBuilder {
38
39
  */
39
40
  get count(): number;
40
41
  /**
41
- * Substring test of per-line basis. A match can only span a single line, so multi-line matches will not be found.
42
- * @return {boolean}
42
+ * Substring test on a per-line basis.
43
+ * A match can only span a single line, so multi-line matches will not be found.
43
44
  * @param {string} term
45
+ * @return {boolean} true if the term was found at least once, false otherwise
44
46
  */
45
47
  containsSubstring(term: string): boolean;
46
48
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"LineBuilder.d.ts","sourceRoot":"","sources":["../../../../src/core/codegen/LineBuilder.js"],"names":[],"mappings":";AAgCA;;;;;;;;;;;;;GAaG;AACH;IAkLI;;;;OAIG;IACH,sBAJW,MAAM,mBACN,MAAM,GACJ,WAAW,CAuBvB;IA9LD;;;;OAIG;IACH,0BAEC;IAED;;;;OAIG;IACH,qBAAqC;IAErC;;;OAGG;IACH,oBAEC;IAED;;;;OAIG;IACH,wBAFW,MAAM,GADL,OAAO,CAoBlB;IAED;;;OAGG;IACH,UAFa,WAAW,CAKvB;IAED;;;OAGG;IACH,UAFa,WAAW,CAQvB;IAED;;;;;OAKG;IACH,eAHW,MAAM,GACJ,WAAW,CASvB;IAED;;;;;;;;;;;OAWG;IACH,aATW,MAAM,GACJ,IAAI,CAmBhB;IAED;;;OAGG;IACH,gBAFW,WAAW,QAiBrB;IAED,cAGC;IAED;;;OAGG;IACH,SAFa,MAAM,CAyBlB;IA8BD,mBAEC;;CACJ"}
1
+ {"version":3,"file":"LineBuilder.d.ts","sourceRoot":"","sources":["../../../../src/core/codegen/LineBuilder.js"],"names":[],"mappings":";AAgCA;;;;;;;;;;;;;;GAcG;AACH;IAoLI;;;;OAIG;IACH,sBAJW,MAAM,mBACN,MAAM,GACJ,WAAW,CAuBvB;IAhMD;;;;OAIG;IACH,0BAEC;IAED;;;;OAIG;IACH,qBAAqC;IAErC;;;OAGG;IACH,oBAEC;IAED;;;;;OAKG;IACH,wBAHW,MAAM,GACL,OAAO,CAoBlB;IAED;;;OAGG;IACH,UAFa,WAAW,CAKvB;IAED;;;OAGG;IACH,UAFa,WAAW,CAQvB;IAED;;;;;OAKG;IACH,eAHW,MAAM,GACJ,WAAW,CASvB;IAED;;;;;;;;;;;OAWG;IACH,aATW,MAAM,GACJ,IAAI,CAmBhB;IAED;;;OAGG;IACH,gBAFW,WAAW,QAiBrB;IAED,cAGC;IAED;;;OAGG;IACH,SAFa,MAAM,CAyBlB;IA8BD,mBAEC;;CACJ"}
@@ -32,6 +32,7 @@ const DEFAULT_INDENT_SPACES = 4;
32
32
 
33
33
  /**
34
34
  * Useful for generating formatted snippets of code.
35
+ *
35
36
  * @example
36
37
  * const b = new LineBuilder();
37
38
  * b.add("function hello(){");
@@ -83,9 +84,10 @@ class LineBuilder {
83
84
  }
84
85
 
85
86
  /**
86
- * Substring test of per-line basis. A match can only span a single line, so multi-line matches will not be found.
87
- * @return {boolean}
87
+ * Substring test on a per-line basis.
88
+ * A match can only span a single line, so multi-line matches will not be found.
88
89
  * @param {string} term
90
+ * @return {boolean} true if the term was found at least once, false otherwise
89
91
  */
90
92
  containsSubstring(term) {
91
93
  assert.isString(term, 'term');
@@ -99,6 +101,7 @@ class LineBuilder {
99
101
  const termIndex = line.text.indexOf(term);
100
102
 
101
103
  if (termIndex !== -1) {
104
+ // match
102
105
  return true;
103
106
  }
104
107
  }
@@ -1,9 +1,10 @@
1
1
  /**
2
- * @see https://en.wikipedia.org/wiki/YUV
3
- * @param {number} Y in range 0...255
4
- * @param {number} Cb in range 0...255
5
- * @param {number} Cr in range 0...255
6
- * @returns {number}
2
+ * Converts YCbCr (Rec. 709) to RGB.
3
+ *
4
+ * @param {number} Y Luma (0-255)
5
+ * @param {number} Cb Blue Difference (0-255)
6
+ * @param {number} Cr Red Difference (0-255)
7
+ * @returns {number} packed 24-bit integer: 0xRRGGBB
7
8
  */
8
9
  export function YCbCr_to_rgb_uint24(Y: number, Cb: number, Cr: number): number;
9
10
  //# sourceMappingURL=YCbCr_to_rgb_uint24.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"YCbCr_to_rgb_uint24.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/YCbCr/YCbCr_to_rgb_uint24.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,uCALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAalB"}
1
+ {"version":3,"file":"YCbCr_to_rgb_uint24.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/YCbCr/YCbCr_to_rgb_uint24.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,uCALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAgBlB"}
@@ -1,19 +1,25 @@
1
+ import { clamp } from "../../math/clamp.js";
2
+
1
3
  /**
2
- * @see https://en.wikipedia.org/wiki/YUV
3
- * @param {number} Y in range 0...255
4
- * @param {number} Cb in range 0...255
5
- * @param {number} Cr in range 0...255
6
- * @returns {number}
4
+ * Converts YCbCr (Rec. 709) to RGB.
5
+ *
6
+ * @param {number} Y Luma (0-255)
7
+ * @param {number} Cb Blue Difference (0-255)
8
+ * @param {number} Cr Red Difference (0-255)
9
+ * @returns {number} packed 24-bit integer: 0xRRGGBB
7
10
  */
8
11
  export function YCbCr_to_rgb_uint24(Y, Cb, Cr) {
9
- const _Cr = Cr - 128;
10
- const _Cb = Cb - 128;
12
+ const C_red = Cr - 128;
13
+ const C_blue = Cb - 128;
14
+
15
+ // Rec. 709 Inverse Coefficients
16
+ // R = Y + 1.5748 * Cr
17
+ // G = Y - 0.1873 * Cb - 0.4681 * Cr
18
+ // B = Y + 1.8556 * Cb
11
19
 
12
- const r = Y + _Cr + (_Cr >> 2) + (_Cr >> 3) + (_Cr >> 5);
13
- const g = Y - ((_Cb >> 2) + (_Cb >> 4) + (_Cb >> 5)) - ((_Cr >> 1) + (_Cr >> 3) + (_Cr >> 4) + (_Cr >> 5));
14
- const b = Y + _Cb + (_Cb >> 1) + (_Cb >> 2) + (_Cb >> 6);
20
+ const r = clamp(Math.round(Y + 1.5748 * C_red), 0, 255);
21
+ const g = clamp(Math.round(Y - 0.1873 * C_blue - 0.4681 * C_red), 0, 255);
22
+ const b = clamp(Math.round(Y + 1.8556 * C_blue), 0, 255);
15
23
 
16
- return ((r << 16) & 0xFF0000)
17
- | ((g << 8) & 0xFF00)
18
- | (b & 0xFF);
24
+ return ((r << 16) | (g << 8) | b) >>> 0;
19
25
  }
@@ -1,9 +1,10 @@
1
1
  /**
2
+ * Converts RGB to YCbCr (Rec. 709 / HDTV Full Range).
2
3
  *
3
- * @param r in range 0...255
4
- * @param g in range 0...255
5
- * @param b in range 0...255
6
- * @return {number}
4
+ * @param {number} r Red (0-255)
5
+ * @param {number} g Green (0-255)
6
+ * @param {number} b Blue (0-255)
7
+ * @return {number} packed 24-bit integer: 0xYYCbCr
7
8
  */
8
- export function rgb_to_YCbCr_uint24(r: any, g: any, b: any): number;
9
+ export function rgb_to_YCbCr_uint24(r: number, g: number, b: number): number;
9
10
  //# sourceMappingURL=rgb_to_YCbCr_uint24.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rgb_to_YCbCr_uint24.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/YCbCr/rgb_to_YCbCr_uint24.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,6DAFY,MAAM,CAUjB"}
1
+ {"version":3,"file":"rgb_to_YCbCr_uint24.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/YCbCr/rgb_to_YCbCr_uint24.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,uCALW,MAAM,KACN,MAAM,KACN,MAAM,GACL,MAAM,CAcjB"}
@@ -1,16 +1,24 @@
1
+ import { clamp } from "../../math/clamp.js";
2
+ import { rgb_to_luminance } from "../rgb_to_luminance.js";
3
+
1
4
  /**
5
+ * Converts RGB to YCbCr (Rec. 709 / HDTV Full Range).
2
6
  *
3
- * @param r in range 0...255
4
- * @param g in range 0...255
5
- * @param b in range 0...255
6
- * @return {number}
7
+ * @param {number} r Red (0-255)
8
+ * @param {number} g Green (0-255)
9
+ * @param {number} b Blue (0-255)
10
+ * @return {number} packed 24-bit integer: 0xYYCbCr
7
11
  */
8
12
  export function rgb_to_YCbCr_uint24(r, g, b) {
9
- const Y = 0.299 * r + 0.587 * g + 0.114 * b;
10
- const Cb = -0.169 * r - 0.331 * g + 0.499 * b + 128;
11
- const Cr = 0.499 * g - 0.418 * g - 0.0813 * b + 128;
13
+ const Y = clamp(Math.round(rgb_to_luminance(r,g,b)), 0, 255);
14
+
15
+ // Rec. 709 Chroma Coefficients
16
+ // Derived from: 0.5 / (1 - Kb) and 0.5 / (1 - Kr)
17
+
18
+ const Cb = clamp(Math.round(-0.1146 * r - 0.3854 * g + 0.5000 * b + 128), 0, 255);
19
+ const Cr = clamp(Math.round(0.5000 * r - 0.4542 * g - 0.0458 * b + 128), 0, 255);
12
20
 
13
- return ((Y << 16) & 0xFF0000)
14
- | ((Cb << 8) & 0xFF00)
15
- | (Cr & 0xFF);
21
+ return (Y << 16)
22
+ | (Cb << 8)
23
+ | (Cr);
16
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"D65_spd_analytical.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/illuminant/D65_spd_analytical.js"],"names":[],"mappings":"AA+CA;;;;;;;;;GASG;AACH,kDAJW,MAAM,GACJ,MAAM,CAelB"}
1
+ {"version":3,"file":"D65_spd_analytical.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/illuminant/D65_spd_analytical.js"],"names":[],"mappings":"AAuBA;;;;;;;;;GASG;AACH,kDAJW,MAAM,GACJ,MAAM,CAelB"}
@@ -9,33 +9,9 @@
9
9
  * and is not a perfect blackbody. This function is the standard
10
10
  * *physical approximation*.
11
11
  */
12
+ import { planckian_radiance } from "./planckian_radiance.js";
12
13
 
13
14
  const D65_ANALYTIC_T = 6504.0; // CCT for D65 in Kelvin
14
- const D65_ANALYTIC_C2 = 1.438776877e-2; // Second radiation constant (m·K)
15
-
16
- /**
17
- * Calculates the un-normalized spectral power for a given wavelength.
18
- * @param {number} lambda_m Wavelength in meters
19
- * @param {number} T Temperature in Kelvin
20
- * @returns {number} Relative spectral power
21
- */
22
- function planckian_radiance(lambda_m, T) {
23
- const lambda_T = lambda_m * T;
24
- const exponent = D65_ANALYTIC_C2 / lambda_T;
25
-
26
- // Handle high exponents to prevent Math.exp from returning Infinity
27
- if (exponent > 80.0) {
28
- return 0.0;
29
- }
30
-
31
- const lambda_5 = Math.pow(lambda_m, 5);
32
-
33
- // This can be simplified to just (1/lambda_5) because the
34
- // rest of the numerator is a constant we are normalizing away.
35
- const radiance = (1.0 / lambda_5) / (Math.exp(exponent) - 1.0);
36
-
37
- return radiance;
38
- }
39
15
 
40
16
  // Pre-calculate the normalization factor:
41
17
  // This is the un-normalized value of the function at 560nm (560e-9 m),
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Calculates the spectral radiance power of a black body for a given wavelength.
3
+ * @param {number} lambda_m Wavelength in meters
4
+ * @param {number} T Temperature in Kelvin
5
+ * @returns {number} Relative spectral power
6
+ */
7
+ export function planckian_radiance(lambda_m: number, T: number): number;
8
+ //# sourceMappingURL=planckian_radiance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planckian_radiance.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/illuminant/planckian_radiance.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,6CAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAyBlB"}
@@ -0,0 +1,41 @@
1
+ import { assert } from "../../assert.js";
2
+
3
+ /**
4
+ * Second radiation constant (m·K)
5
+ *
6
+ * `c2 = (h*c) / (kb)`
7
+ *
8
+ * Value is meters Kelvin (m*K).
9
+ */
10
+ const PLANCK_C2 = 1.438776877e-2;
11
+
12
+ /**
13
+ * Calculates the spectral radiance power of a black body for a given wavelength.
14
+ * @param {number} lambda_m Wavelength in meters
15
+ * @param {number} T Temperature in Kelvin
16
+ * @returns {number} Relative spectral power
17
+ */
18
+ export function planckian_radiance(lambda_m, T) {
19
+ assert.isNumber(lambda_m, 'lambda_m');
20
+ assert.notNaN(lambda_m, 'lambda_m');
21
+
22
+ assert.isNumber(T, 'T');
23
+ assert.notNaN(T, 'T');
24
+
25
+ const lambda_T = lambda_m * T;
26
+ const exponent = PLANCK_C2 / lambda_T;
27
+
28
+ // Handle high exponents to prevent Math.exp from returning Infinity
29
+ if (exponent > 80.0) { // exp(80) = ~5.5e34
30
+ // this would pull denominator to extremely high values, effectively driving the result towards 0
31
+ return 0.0;
32
+ }
33
+
34
+ const lambda_5 = Math.pow(lambda_m, 5);
35
+
36
+ // This can be simplified to just (1/lambda_5) because the
37
+ // rest of the numerator is a constant we are normalizing away.
38
+ const radiance = (1.0 / lambda_5) / (Math.exp(exponent) - 1.0);
39
+
40
+ return radiance;
41
+ }
@@ -1,10 +1,17 @@
1
1
  /**
2
- * @see https://www.zombieprototypes.com/?p=210
3
- * @see https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
4
- * TODO: not sure if output is in linear or sRGB space, looking at the way colors look in Unity - it appears that colors are in sRGB and need to be shifted to linear before being used
5
- * @param {number[]} result RGB output
2
+ *
3
+ * Converts Kelvin temperature to RGB.
4
+ * Handles ranges 0K - 40000K
5
+ *
6
+ * Note: if you will need to covert the output to linear space ({@link sRGB_to_linear}) if you intend to perform any mixing on the color.
7
+ *
8
+ * @param {number[]} result result RGB output (sRGB Gamma Corrected)
6
9
  * @param {number} result_offset
7
10
  * @param {number} temperature in Kelvin
11
+ *
12
+ * @see https://www.zombieprototypes.com/?p=210
13
+ * @see https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
14
+ * @see sRGB_to_linear
8
15
  */
9
16
  export function kelvin_to_rgb(result: number[], result_offset: number, temperature: number): void;
10
17
  //# sourceMappingURL=kelvin_to_rgb.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kelvin_to_rgb.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/kelvin/kelvin_to_rgb.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,sCAJW,MAAM,EAAE,iBACR,MAAM,eACN,MAAM,QAkDhB"}
1
+ {"version":3,"file":"kelvin_to_rgb.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/kelvin/kelvin_to_rgb.js"],"names":[],"mappings":"AA6FA;;;;;;;;;;;;;;GAcG;AACH,sCARW,MAAM,EAAE,iBACR,MAAM,eACN,MAAM,QA6DhB"}
@@ -1,13 +1,110 @@
1
1
  import { assert } from "../../assert.js";
2
2
  import { clamp01 } from "../../math/clamp01.js";
3
+ import { inverseLerp } from "../../math/inverseLerp.js";
4
+ import { lerp } from "../../math/lerp.js";
5
+
3
6
 
4
7
  /**
5
- * @see https://www.zombieprototypes.com/?p=210
6
- * @see https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
7
- * TODO: not sure if output is in linear or sRGB space, looking at the way colors look in Unity - it appears that colors are in sRGB and need to be shifted to linear before being used
8
- * @param {number[]} result RGB output
8
+ * Red-dominant approximation
9
+ *
10
+ * Valid for < 6600K
11
+ *
12
+ * @param {number[]} out
13
+ * @param {number} t K/100
14
+ */
15
+ function approximate_regime_red(out, t) {
16
+
17
+ const r = 1;
18
+
19
+ const g = clamp01(
20
+ -0.6088425710866344 - 0.001748900018414868 * (t - 2) + 0.4097731842899564 * Math.log(t - 2)
21
+ );
22
+
23
+ const b = t <= 20 ? 0 : clamp01(
24
+ -0.9990954974165059 + 0.0032447435545127036 * (t - 10) + 0.453646839257496 * Math.log(t - 10)
25
+ );
26
+
27
+ out[0] = r;
28
+ out[1] = g;
29
+ out[2] = b;
30
+ }
31
+
32
+
33
+ /**
34
+ * Blue-dominant approximation
35
+ *
36
+ * Valid for > 6600K
37
+ *
38
+ * @param {number[]} out
39
+ * @param {number} t K/100
40
+ */
41
+ function approximate_regime_blue(out, t) {
42
+
43
+ const r = clamp01(
44
+ 1.3803015908551253 + 0.0004478684462124118 * (t - 55) - 0.15785750232675008 * Math.log(t - 55)
45
+ ); // in normalized scale
46
+
47
+ const g = clamp01(
48
+ 1.2762722061615583 + 0.0003115080994769546 * (t - 50) - 0.11013841706194392 * Math.log(t - 50)
49
+ );
50
+
51
+ const b = 1;
52
+
53
+ out[0] = r;
54
+ out[1] = g;
55
+ out[2] = b;
56
+ }
57
+
58
+ /**
59
+ * Black body
60
+ *
61
+ * Valid for < 1000K
62
+ *
63
+ * @param {number[]} out
64
+ * @param {number} t K/100
65
+ */
66
+ function approximate_regime_blackbody(out, t) {
67
+ // 1. Handle "Black Body" cooling (below 1000K)
68
+
69
+ // These are the values the algorithm produces at exactly 1000K (t=10).
70
+ // We lock the hue here and just fade the brightness to zero.
71
+ const k1000_r = 1;
72
+ const k1000_g = 0.22926561084500907;
73
+ const k1000_b = 0;
74
+
75
+ // The Draper point (approx 798K) is where objects begin to glow visible red.
76
+ const DRAPER_POINT = 7.98; // 798K
77
+
78
+ // Note: We are attenuating Gamma-corrected values here.
79
+ // Physically strictly incorrect (should be linear), but visually acceptable
80
+ // and faster for this specific "fade to black" effect.
81
+ const brightness = Math.max(0, inverseLerp(DRAPER_POINT, 10, t));
82
+
83
+ out[0] = k1000_r * brightness;
84
+ out[1] = k1000_g * brightness;
85
+ out[2] = k1000_b * brightness;
86
+ }
87
+
88
+ /**
89
+ * Avoid heap allocation in the main function
90
+ * @type {number[]}
91
+ */
92
+ const scratch_rgb = [0, 0, 0];
93
+
94
+ /**
95
+ *
96
+ * Converts Kelvin temperature to RGB.
97
+ * Handles ranges 0K - 40000K
98
+ *
99
+ * Note: if you will need to covert the output to linear space ({@link sRGB_to_linear}) if you intend to perform any mixing on the color.
100
+ *
101
+ * @param {number[]} result result RGB output (sRGB Gamma Corrected)
9
102
  * @param {number} result_offset
10
103
  * @param {number} temperature in Kelvin
104
+ *
105
+ * @see https://www.zombieprototypes.com/?p=210
106
+ * @see https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
107
+ * @see sRGB_to_linear
11
108
  */
12
109
  export function kelvin_to_rgb(
13
110
  result,
@@ -18,43 +115,50 @@ export function kelvin_to_rgb(
18
115
  assert.isNonNegativeInteger(result_offset, "result_offset");
19
116
  assert.isNumber(temperature, "temperature");
20
117
 
21
- let r;
22
- let g;
23
- let b;
24
-
25
118
  // Temperature divided by 100 for calculations
26
119
  const t = temperature / 100;
27
120
 
28
- if (t <= 66) {
29
- r = 1;
121
+ if (t < 10) {
30
122
 
31
- g = clamp01(
32
- -0.6088425710866344 - 0.001748900018414868 * (t - 2) + 0.4097731842899564 * Math.log(t - 2)
33
- );
123
+ approximate_regime_blackbody(scratch_rgb, t);
124
+
125
+ } else {
126
+
127
+ const BLEND_MIN = 65;
128
+ const BLEND_MAX = 67;
129
+
130
+ if (t < BLEND_MIN) {
131
+
132
+ approximate_regime_red(scratch_rgb, t);
133
+
134
+ } else if (t > BLEND_MAX) {
135
+
136
+ approximate_regime_blue(scratch_rgb, t);
34
137
 
35
- if (t <= 20) {
36
- b = 0;
37
138
  } else {
38
139
 
39
- b = clamp01(
40
- -0.9990954974165059 + 0.0032447435545127036 * (t - 10) + 0.453646839257496 * Math.log(t - 10)
41
- );
140
+ // blend the two regimes to avoid discontinuity
141
+ const alpha = inverseLerp(BLEND_MIN, BLEND_MAX, t);
42
142
 
43
- }
44
- } else {
143
+ approximate_regime_red(scratch_rgb, t);
144
+ const r0 = scratch_rgb[0];
145
+ const g0 = scratch_rgb[1];
146
+ const b0 = scratch_rgb[2];
45
147
 
46
- r = clamp01(
47
- 1.3803015908551253 + 0.0004478684462124118 * (t - 55) - 0.15785750232675008 * Math.log(t - 55)
48
- ); // in normalized scale
148
+ approximate_regime_blue(scratch_rgb, t);
149
+ const r1 = scratch_rgb[0];
150
+ const g1 = scratch_rgb[1];
151
+ const b1 = scratch_rgb[2];
49
152
 
50
- g = clamp01(
51
- 1.2762722061615583 + 0.0003115080994769546 * (t - 50) - 0.11013841706194392 * Math.log(t - 50)
52
- );
153
+ scratch_rgb[0] = lerp(r0, r1, alpha);
154
+ scratch_rgb[1] = lerp(g0, g1, alpha);
155
+ scratch_rgb[2] = lerp(b0, b1, alpha);
156
+
157
+ }
53
158
 
54
- b = 1;
55
159
  }
56
160
 
57
- result[result_offset + 0] = r;
58
- result[result_offset + 1] = g;
59
- result[result_offset + 2] = b;
161
+ result[result_offset + 0] = scratch_rgb[0];
162
+ result[result_offset + 1] = scratch_rgb[1];
163
+ result[result_offset + 2] = scratch_rgb[2];
60
164
  }
@@ -1,8 +1,11 @@
1
1
  /**
2
+ * Estimates the Color Temperature (Kelvin) from an RGB input.
2
3
  *
3
- * @see https://www.zombieprototypes.com/?p=210
4
4
  * @param {number[]|ArrayLike<number>|{0:number,1:number,2:number}} input input array
5
5
  * @param {number} [input_offset=0] offset into input array
6
+ * @returns {number} Temperature in Kelvin (approx 1000 to 40000)
7
+ *
8
+ * @see https://www.zombieprototypes.com/?p=210
6
9
  */
7
10
  export function rgb_to_kelvin(input: number[] | ArrayLike<number> | {
8
11
  0: number;
@@ -1 +1 @@
1
- {"version":3,"file":"rgb_to_kelvin.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/kelvin/rgb_to_kelvin.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,qCAHW,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,GAAC;IAAC,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAA;CAAC,iBACvD,MAAM,UAwChB"}
1
+ {"version":3,"file":"rgb_to_kelvin.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/kelvin/rgb_to_kelvin.js"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,qCANW,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,GAAC;IAAC,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAA;CAAC,iBACvD,MAAM,GACJ,MAAM,CA4DlB"}
@@ -1,13 +1,20 @@
1
1
  import { assert } from "../../assert.js";
2
2
  import { kelvin_to_rgb } from "./kelvin_to_rgb.js";
3
3
 
4
+ /**
5
+ * Save allocation with re-usable scratch
6
+ * @type {number[]}
7
+ */
4
8
  const scratch_rgb = [];
5
9
 
6
10
  /**
11
+ * Estimates the Color Temperature (Kelvin) from an RGB input.
7
12
  *
8
- * @see https://www.zombieprototypes.com/?p=210
9
13
  * @param {number[]|ArrayLike<number>|{0:number,1:number,2:number}} input input array
10
14
  * @param {number} [input_offset=0] offset into input array
15
+ * @returns {number} Temperature in Kelvin (approx 1000 to 40000)
16
+ *
17
+ * @see https://www.zombieprototypes.com/?p=210
11
18
  */
12
19
  export function rgb_to_kelvin(
13
20
  input,
@@ -17,32 +24,50 @@ export function rgb_to_kelvin(
17
24
  assert.isNonNegativeInteger(input_offset, "input_offset");
18
25
 
19
26
  const r = input[input_offset];
20
- const g = input[input_offset + 1];
21
27
  const b = input[input_offset + 2];
22
28
 
23
- const blue_red_ratio = b / r;
29
+ let minTemperature = 1000;
30
+ let maxTemperature = 40000;
31
+
32
+ if (r + b === 0) {
33
+ // black, effectively 0 Kelvin
34
+ return 0;
35
+ }
36
+
37
+ if (r === 0) {
38
+ // blue dominance, produce maximum
39
+ // also, avoid division by 0
40
+ return maxTemperature;
41
+ }
42
+
43
+ const expected_blue_red_ratio = b / r;
24
44
 
25
45
  // use solver to reverse function, slow but hey - it works
26
- let temperature;
46
+ let temperature = 0;
27
47
 
28
48
  const epsilon = 0.4;
29
49
 
30
- let minTemperature = 1000;
31
- let maxTemperature = 40000;
32
-
50
+ // binary search
33
51
  while (maxTemperature - minTemperature > epsilon) {
34
52
 
35
53
  temperature = (maxTemperature + minTemperature) * 0.5;
36
54
 
37
55
  kelvin_to_rgb(scratch_rgb, 0, temperature);
38
56
 
39
- const br = scratch_rgb[2] / scratch_rgb[0];
57
+ const actual_b = scratch_rgb[2];
58
+ const actual_r = scratch_rgb[0];
59
+
60
+ // prevent division by 0
61
+ const safe_r = Math.max(1e-7, actual_r);
40
62
 
41
- if (br >= blue_red_ratio) {
63
+ const br = actual_b / safe_r;
64
+
65
+ if (br >= expected_blue_red_ratio) {
42
66
  maxTemperature = temperature;
43
67
  } else {
44
68
  minTemperature = temperature;
45
69
  }
70
+
46
71
  }
47
72
 
48
73
  return Math.round(temperature);
@@ -1,9 +1,12 @@
1
1
  /**
2
+ * Calculates Luminance (perceived brightness) using modern Rec.709 coefficients.
2
3
  *
3
- * @param {number} r
4
- * @param {number} g
5
- * @param {number} b
6
- * @return {number}
4
+ * Matches sRGB and HDTV standards.
5
+ *
6
+ * @param {number} r Red component (linear or gamma-corrected)
7
+ * @param {number} g Green component (linear or gamma-corrected)
8
+ * @param {number} b Blue component (linear or gamma-corrected)
9
+ * @return {number} The calculated luma value
7
10
  */
8
11
  export function rgb_to_luminance(r: number, g: number, b: number): number;
9
12
  //# sourceMappingURL=rgb_to_luminance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rgb_to_luminance.d.ts","sourceRoot":"","sources":["../../../../src/core/color/rgb_to_luminance.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,oCALW,MAAM,KACN,MAAM,KACN,MAAM,GACL,MAAM,CAIjB"}
1
+ {"version":3,"file":"rgb_to_luminance.d.ts","sourceRoot":"","sources":["../../../../src/core/color/rgb_to_luminance.js"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,oCALW,MAAM,KACN,MAAM,KACN,MAAM,GACL,MAAM,CAIjB"}