@zephyr3d/scene 0.9.6 → 0.9.7

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 (203) hide show
  1. package/dist/animation/joint_dynamics/controller.js +92 -32
  2. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  3. package/dist/animation/joint_dynamics/convex_collider.js +320 -0
  4. package/dist/animation/joint_dynamics/convex_collider.js.map +1 -0
  5. package/dist/animation/joint_dynamics/joint_dynamics_system.js +57 -19
  6. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  7. package/dist/animation/joint_dynamics/solver.js +71 -27
  8. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  9. package/dist/animation/joint_dynamics_modifier.js +21 -20
  10. package/dist/animation/joint_dynamics_modifier.js.map +1 -1
  11. package/dist/animation/skeleton.js +7 -10
  12. package/dist/animation/skeleton.js.map +1 -1
  13. package/dist/app/engine.js +134 -140
  14. package/dist/app/engine.js.map +1 -1
  15. package/dist/app/scriptregistry.js +47 -16
  16. package/dist/app/scriptregistry.js.map +1 -1
  17. package/dist/asset/assetmanager.js +3 -1
  18. package/dist/asset/assetmanager.js.map +1 -1
  19. package/dist/asset/model.js +346 -7
  20. package/dist/asset/model.js.map +1 -1
  21. package/dist/avatar/wardrobe.js +20 -16
  22. package/dist/avatar/wardrobe.js.map +1 -1
  23. package/dist/camera/camera.js +416 -210
  24. package/dist/camera/camera.js.map +1 -1
  25. package/dist/index.d.ts +1349 -621
  26. package/dist/index.js +6 -11
  27. package/dist/index.js.map +1 -1
  28. package/dist/material/blinn.js +1 -1
  29. package/dist/material/blinn.js.map +1 -1
  30. package/dist/material/lambert.js +1 -1
  31. package/dist/material/lambert.js.map +1 -1
  32. package/dist/material/material.js +23 -1
  33. package/dist/material/material.js.map +1 -1
  34. package/dist/material/meshmaterial.js +178 -23
  35. package/dist/material/meshmaterial.js.map +1 -1
  36. package/dist/material/mixins/albedocolor.js +4 -4
  37. package/dist/material/mixins/albedocolor.js.map +1 -1
  38. package/dist/material/mixins/lightmodel/blinnphong.js +2 -1
  39. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  40. package/dist/material/mixins/lightmodel/lambert.js +2 -1
  41. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  42. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +63 -16
  43. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  44. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +105 -32
  45. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  46. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +16 -6
  47. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  48. package/dist/material/mixins/lit.js +1 -1
  49. package/dist/material/mixins/lit.js.map +1 -1
  50. package/dist/material/mixins/pbr/common.js +276 -65
  51. package/dist/material/mixins/pbr/common.js.map +1 -1
  52. package/dist/material/mixins/texture.js +3 -3
  53. package/dist/material/mixins/texture.js.map +1 -1
  54. package/dist/material/mixins/vertexcolor.js +2 -2
  55. package/dist/material/mixins/vertexcolor.js.map +1 -1
  56. package/dist/material/mtoon.js +574 -0
  57. package/dist/material/mtoon.js.map +1 -0
  58. package/dist/material/pbrblueprint.js +499 -336
  59. package/dist/material/pbrblueprint.js.map +1 -1
  60. package/dist/material/pbrmr.js +118 -100
  61. package/dist/material/pbrmr.js.map +1 -1
  62. package/dist/material/pbrsg.js +1 -1
  63. package/dist/material/pbrsg.js.map +1 -1
  64. package/dist/material/shader/helper.js +324 -294
  65. package/dist/material/shader/helper.js.map +1 -1
  66. package/dist/material/subsurfaceprofile.js +812 -0
  67. package/dist/material/subsurfaceprofile.js.map +1 -0
  68. package/dist/material/unlit.js +1 -1
  69. package/dist/material/unlit.js.map +1 -1
  70. package/dist/posteffect/compositor.js +46 -11
  71. package/dist/posteffect/compositor.js.map +1 -1
  72. package/dist/posteffect/ssr.js +422 -96
  73. package/dist/posteffect/ssr.js.map +1 -1
  74. package/dist/posteffect/sss.js +1053 -0
  75. package/dist/posteffect/sss.js.map +1 -0
  76. package/dist/posteffect/taa.js +61 -60
  77. package/dist/posteffect/taa.js.map +1 -1
  78. package/dist/render/abuffer_oit.js +63 -12
  79. package/dist/render/abuffer_oit.js.map +1 -1
  80. package/dist/render/cluster_light.js +6 -5
  81. package/dist/render/cluster_light.js.map +1 -1
  82. package/dist/render/drawable.js +1 -5
  83. package/dist/render/drawable.js.map +1 -1
  84. package/dist/render/drawable_mixin.js +2 -1
  85. package/dist/render/drawable_mixin.js.map +1 -1
  86. package/dist/render/fbm_wavegenerator.js +2 -1
  87. package/dist/render/fbm_wavegenerator.js.map +1 -1
  88. package/dist/render/gerstner_wavegenerator.js +2 -1
  89. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  90. package/dist/render/globalbindgroup_allocator.js +2 -1
  91. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  92. package/dist/render/lightpass.js +110 -23
  93. package/dist/render/lightpass.js.map +1 -1
  94. package/dist/render/render_queue.js +51 -8
  95. package/dist/render/render_queue.js.map +1 -1
  96. package/dist/render/renderer.js +80 -66
  97. package/dist/render/renderer.js.map +1 -1
  98. package/dist/render/rendergraph/device_pool_allocator.js +8 -0
  99. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -1
  100. package/dist/render/rendergraph/forward_plus_builder.js +481 -95
  101. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  102. package/dist/render/rendergraph/history_resource_manager.js +55 -0
  103. package/dist/render/rendergraph/history_resource_manager.js.map +1 -1
  104. package/dist/render/rendergraph/history_resources.js +3 -1
  105. package/dist/render/rendergraph/history_resources.js.map +1 -1
  106. package/dist/render/rendergraph/types.js.map +1 -1
  107. package/dist/render/renderpass.js +10 -4
  108. package/dist/render/renderpass.js.map +1 -1
  109. package/dist/render/sky.js +31 -1
  110. package/dist/render/sky.js.map +1 -1
  111. package/dist/render/weightedblended_oit.js +23 -5
  112. package/dist/render/weightedblended_oit.js.map +1 -1
  113. package/dist/scene/basesprite.js +4 -2
  114. package/dist/scene/basesprite.js.map +1 -1
  115. package/dist/scene/batchgroup.js +3 -1
  116. package/dist/scene/batchgroup.js.map +1 -1
  117. package/dist/scene/environment.js +11 -1
  118. package/dist/scene/environment.js.map +1 -1
  119. package/dist/scene/light.js +21 -3
  120. package/dist/scene/light.js.map +1 -1
  121. package/dist/scene/mesh.js +29 -14
  122. package/dist/scene/mesh.js.map +1 -1
  123. package/dist/scene/meshdrawable.js +6 -0
  124. package/dist/scene/meshdrawable.js.map +1 -1
  125. package/dist/scene/msdftext.js +5 -2
  126. package/dist/scene/msdftext.js.map +1 -1
  127. package/dist/scene/msdftextsprite.js +5 -3
  128. package/dist/scene/msdftextsprite.js.map +1 -1
  129. package/dist/scene/particlesys.js +3 -1
  130. package/dist/scene/particlesys.js.map +1 -1
  131. package/dist/scene/scene.js +6 -5
  132. package/dist/scene/scene.js.map +1 -1
  133. package/dist/scene/terrain-cm/grass.js +4 -2
  134. package/dist/scene/terrain-cm/grass.js.map +1 -1
  135. package/dist/scene/terrain-cm/grassmaterial.js +2 -1
  136. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  137. package/dist/scene/terrain-cm/terrain-cm.js +4 -2
  138. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  139. package/dist/scene/water.js +4 -2
  140. package/dist/scene/water.js.map +1 -1
  141. package/dist/shaders/shadow.js +26 -393
  142. package/dist/shaders/shadow.js.map +1 -1
  143. package/dist/shadow/esm.js +112 -12
  144. package/dist/shadow/esm.js.map +1 -1
  145. package/dist/shadow/pcf_opt.js +2 -2
  146. package/dist/shadow/pcf_opt.js.map +1 -1
  147. package/dist/shadow/pcf_pd.js +19 -10
  148. package/dist/shadow/pcf_pd.js.map +1 -1
  149. package/dist/shadow/shader.js +58 -7
  150. package/dist/shadow/shader.js.map +1 -1
  151. package/dist/shadow/shadow_impl.js +6 -0
  152. package/dist/shadow/shadow_impl.js.map +1 -1
  153. package/dist/shadow/shadow_region.js +229 -0
  154. package/dist/shadow/shadow_region.js.map +1 -0
  155. package/dist/shadow/shadowmapper.js +67 -59
  156. package/dist/shadow/shadowmapper.js.map +1 -1
  157. package/dist/shadow/vsm.js +45 -19
  158. package/dist/shadow/vsm.js.map +1 -1
  159. package/dist/utility/blueprint/common/constants.js +8 -8
  160. package/dist/utility/blueprint/common/constants.js.map +1 -1
  161. package/dist/utility/blueprint/material/pbr.js +31 -4
  162. package/dist/utility/blueprint/material/pbr.js.map +1 -1
  163. package/dist/utility/blueprint/material/texture.js +1 -17
  164. package/dist/utility/blueprint/material/texture.js.map +1 -1
  165. package/dist/utility/serialization/manager.js +327 -359
  166. package/dist/utility/serialization/manager.js.map +1 -1
  167. package/dist/utility/serialization/scene/animation.js +5 -2
  168. package/dist/utility/serialization/scene/animation.js.map +1 -1
  169. package/dist/utility/serialization/scene/batch.js +4 -1
  170. package/dist/utility/serialization/scene/batch.js.map +1 -1
  171. package/dist/utility/serialization/scene/camera.js +249 -54
  172. package/dist/utility/serialization/scene/camera.js.map +1 -1
  173. package/dist/utility/serialization/scene/common.js +37 -1
  174. package/dist/utility/serialization/scene/common.js.map +1 -1
  175. package/dist/utility/serialization/scene/light.js +42 -3
  176. package/dist/utility/serialization/scene/light.js.map +1 -1
  177. package/dist/utility/serialization/scene/material.js +1112 -646
  178. package/dist/utility/serialization/scene/material.js.map +1 -1
  179. package/dist/utility/serialization/scene/mesh.js +7 -4
  180. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  181. package/dist/utility/serialization/scene/node.js +31 -12
  182. package/dist/utility/serialization/scene/node.js.map +1 -1
  183. package/dist/utility/serialization/scene/particle.js +4 -1
  184. package/dist/utility/serialization/scene/particle.js.map +1 -1
  185. package/dist/utility/serialization/scene/primitive.js +3 -1
  186. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  187. package/dist/utility/serialization/scene/scene.js +18 -0
  188. package/dist/utility/serialization/scene/scene.js.map +1 -1
  189. package/dist/utility/serialization/scene/sprite.js +6 -3
  190. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  191. package/dist/utility/serialization/scene/terrain.js +5 -2
  192. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  193. package/dist/utility/serialization/scene/text.js +3 -1
  194. package/dist/utility/serialization/scene/text.js.map +1 -1
  195. package/dist/utility/serialization/scene/water.js +4 -1
  196. package/dist/utility/serialization/scene/water.js.map +1 -1
  197. package/dist/utility/textures/ltcdata.js +6 -0
  198. package/dist/utility/textures/ltcdata.js.map +1 -0
  199. package/dist/utility/textures/ltclut.js +61 -0
  200. package/dist/utility/textures/ltclut.js.map +1 -0
  201. package/dist/values.js +9 -1
  202. package/dist/values.js.map +1 -1
  203. package/package.json +3 -3
@@ -0,0 +1,812 @@
1
+ import { Vector3 } from '@zephyr3d/base';
2
+
3
+ const SUBSURFACE_PROFILE_PRESET_ALIAS = {
4
+ skin: 'skin_default',
5
+ skin_thin: 'skin_thin',
6
+ skin_default: 'skin_default',
7
+ skin_heavy_makeup: 'skin_heavy_makeup',
8
+ wax: 'wax_backlit',
9
+ wax_backlit: 'wax_backlit',
10
+ wax_soft: 'wax_soft',
11
+ jade: 'jade_soft',
12
+ jade_backlit: 'jade_backlit',
13
+ jade_soft: 'jade_soft'
14
+ };
15
+ const SUBSURFACE_PROFILE_PRESET_INDEX = {
16
+ skin_thin: 0,
17
+ skin_default: 1,
18
+ skin_heavy_makeup: 2,
19
+ wax_backlit: 3,
20
+ wax_soft: 4,
21
+ jade_backlit: 5,
22
+ jade_soft: 6
23
+ };
24
+ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
25
+ skin_thin: {
26
+ meanFreePathColor: [
27
+ 1.0,
28
+ 0.37,
29
+ 0.11
30
+ ],
31
+ meanFreePathDistance: 0.7,
32
+ falloffColor: [
33
+ 1.0,
34
+ 0.32,
35
+ 0.2
36
+ ],
37
+ strength: 0.68,
38
+ scale: 0.82,
39
+ worldUnitScale: 0.88,
40
+ boundaryColorBleed: 0.13,
41
+ transmissionTintColor: [
42
+ 1,
43
+ 0.37,
44
+ 0.28
45
+ ],
46
+ extinctionScale: 1.24,
47
+ normalScale: 1.18,
48
+ scatteringDistribution: 0.56
49
+ },
50
+ skin_default: {
51
+ meanFreePathColor: [
52
+ 1.0,
53
+ 0.45,
54
+ 0.17
55
+ ],
56
+ meanFreePathDistance: 0.92,
57
+ falloffColor: [
58
+ 1.0,
59
+ 0.39,
60
+ 0.25
61
+ ],
62
+ strength: 0.82,
63
+ scale: 0.96,
64
+ worldUnitScale: 1,
65
+ boundaryColorBleed: 0.22,
66
+ transmissionTintColor: [
67
+ 1,
68
+ 0.46,
69
+ 0.34
70
+ ],
71
+ extinctionScale: 1.06,
72
+ normalScale: 1,
73
+ scatteringDistribution: 0.6
74
+ },
75
+ skin_heavy_makeup: {
76
+ meanFreePathColor: [
77
+ 1.0,
78
+ 0.33,
79
+ 0.11
80
+ ],
81
+ meanFreePathDistance: 0.68,
82
+ falloffColor: [
83
+ 1.0,
84
+ 0.26,
85
+ 0.16
86
+ ],
87
+ strength: 0.56,
88
+ scale: 0.76,
89
+ worldUnitScale: 0.84,
90
+ boundaryColorBleed: 0.08,
91
+ transmissionTintColor: [
92
+ 0.94,
93
+ 0.31,
94
+ 0.22
95
+ ],
96
+ extinctionScale: 1.4,
97
+ normalScale: 1.26,
98
+ scatteringDistribution: 0.5
99
+ },
100
+ wax_backlit: {
101
+ meanFreePathColor: [
102
+ 1.0,
103
+ 0.68,
104
+ 0.36
105
+ ],
106
+ meanFreePathDistance: 1.54,
107
+ falloffColor: [
108
+ 1.0,
109
+ 0.8,
110
+ 0.66
111
+ ],
112
+ strength: 1.12,
113
+ scale: 1.42,
114
+ worldUnitScale: 1.26,
115
+ boundaryColorBleed: 0.42,
116
+ transmissionTintColor: [
117
+ 1,
118
+ 0.82,
119
+ 0.7
120
+ ],
121
+ extinctionScale: 0.78,
122
+ normalScale: 0.92,
123
+ scatteringDistribution: 0.82
124
+ },
125
+ wax_soft: {
126
+ meanFreePathColor: [
127
+ 1.0,
128
+ 0.72,
129
+ 0.38
130
+ ],
131
+ meanFreePathDistance: 1.2,
132
+ falloffColor: [
133
+ 1.0,
134
+ 0.86,
135
+ 0.74
136
+ ],
137
+ strength: 1.02,
138
+ scale: 1.28,
139
+ worldUnitScale: 1.12,
140
+ boundaryColorBleed: 0.36,
141
+ transmissionTintColor: [
142
+ 1,
143
+ 0.86,
144
+ 0.74
145
+ ],
146
+ extinctionScale: 0.86,
147
+ normalScale: 0.98,
148
+ scatteringDistribution: 0.74
149
+ },
150
+ jade_backlit: {
151
+ meanFreePathColor: [
152
+ 0.74,
153
+ 1.0,
154
+ 0.88
155
+ ],
156
+ meanFreePathDistance: 0.92,
157
+ falloffColor: [
158
+ 0.66,
159
+ 0.94,
160
+ 0.88
161
+ ],
162
+ strength: 0.92,
163
+ scale: 1.14,
164
+ worldUnitScale: 1.06,
165
+ boundaryColorBleed: 0.26,
166
+ transmissionTintColor: [
167
+ 0.68,
168
+ 0.92,
169
+ 0.86
170
+ ],
171
+ extinctionScale: 0.92,
172
+ normalScale: 1.02,
173
+ scatteringDistribution: 0.7
174
+ },
175
+ jade_soft: {
176
+ meanFreePathColor: [
177
+ 0.68,
178
+ 1.0,
179
+ 0.84
180
+ ],
181
+ meanFreePathDistance: 0.8,
182
+ falloffColor: [
183
+ 0.72,
184
+ 0.94,
185
+ 0.86
186
+ ],
187
+ strength: 0.82,
188
+ scale: 1.02,
189
+ worldUnitScale: 0.98,
190
+ boundaryColorBleed: 0.22,
191
+ transmissionTintColor: [
192
+ 0.74,
193
+ 0.96,
194
+ 0.9
195
+ ],
196
+ extinctionScale: 1,
197
+ normalScale: 1.04,
198
+ scatteringDistribution: 0.66
199
+ }
200
+ };
201
+ const SUBSURFACE_PROFILE_PRESET_TINT_BIAS = {
202
+ skin_thin: [
203
+ 1,
204
+ 0.56,
205
+ 0.46
206
+ ],
207
+ skin_default: [
208
+ 1,
209
+ 0.62,
210
+ 0.5
211
+ ],
212
+ skin_heavy_makeup: [
213
+ 1,
214
+ 0.5,
215
+ 0.42
216
+ ],
217
+ wax_backlit: [
218
+ 1,
219
+ 0.8,
220
+ 0.7
221
+ ],
222
+ wax_soft: [
223
+ 1,
224
+ 0.86,
225
+ 0.78
226
+ ],
227
+ jade_backlit: [
228
+ 0.72,
229
+ 0.92,
230
+ 0.96
231
+ ],
232
+ jade_soft: [
233
+ 0.68,
234
+ 0.96,
235
+ 0.88
236
+ ]
237
+ };
238
+ const SUBSURFACE_PROFILE_PRESET_RESPONSE = {
239
+ skin_thin: [
240
+ 0.08,
241
+ 0.12,
242
+ 0.06,
243
+ 0.12
244
+ ],
245
+ skin_default: [
246
+ 0.1,
247
+ 0.14,
248
+ 0.08,
249
+ 0.16
250
+ ],
251
+ skin_heavy_makeup: [
252
+ 0.02,
253
+ 0.05,
254
+ -0.02,
255
+ 0.01
256
+ ],
257
+ wax_backlit: [
258
+ 0.12,
259
+ 0.2,
260
+ 0.26,
261
+ 0.24
262
+ ],
263
+ wax_soft: [
264
+ 0.2,
265
+ 0.3,
266
+ 0.34,
267
+ 0.1
268
+ ],
269
+ jade_backlit: [
270
+ 0.08,
271
+ 0.18,
272
+ 0.2,
273
+ 0.24
274
+ ],
275
+ jade_soft: [
276
+ 0.16,
277
+ 0.24,
278
+ 0.22,
279
+ 0.12
280
+ ]
281
+ };
282
+ /**
283
+ * Serializable subsurface scattering profile.
284
+ *
285
+ * @remarks
286
+ * The profile stores the channel-dependent scattering radius and falloff used
287
+ * by the screen-space SSS post effect. Materials can share a profile instance
288
+ * to emulate Unreal-style skin profile assets.
289
+ *
290
+ * @public
291
+ */ class SubsurfaceProfile {
292
+ static _maxProfiles = 255;
293
+ static _profiles = new Array(SubsurfaceProfile._maxProfiles + 1).fill(null);
294
+ static _version = 0;
295
+ static _defaultSkinProfile = null;
296
+ _scatterRadius;
297
+ _falloffColor;
298
+ _meanFreePathColor;
299
+ _transmissionTintColor;
300
+ _preset;
301
+ _meanFreePathDistance;
302
+ _strength;
303
+ _scale;
304
+ _worldUnitScale;
305
+ _boundaryColorBleed;
306
+ _extinctionScale;
307
+ _normalScale;
308
+ _scatteringDistribution;
309
+ _slot;
310
+ _changeListeners;
311
+ /**
312
+ * Creates a subsurface scattering profile initialized with the default skin preset.
313
+ *
314
+ * @public
315
+ */ constructor(){
316
+ this._scatterRadius = new Vector3(0, 0, 0);
317
+ this._falloffColor = new Vector3(0, 0, 0);
318
+ this._meanFreePathColor = new Vector3(0, 0, 0);
319
+ this._transmissionTintColor = new Vector3(0, 0, 0);
320
+ this._preset = 'skin_default';
321
+ this._meanFreePathDistance = 0;
322
+ this._strength = 0;
323
+ this._scale = 0;
324
+ this._worldUnitScale = 1;
325
+ this._boundaryColorBleed = 0;
326
+ this._extinctionScale = 1;
327
+ this._normalScale = 1;
328
+ this._scatteringDistribution = 0.65;
329
+ this._changeListeners = new Set();
330
+ this._slot = SubsurfaceProfile.allocateSlot(this);
331
+ this.applyPresetTemplate(this._preset, false);
332
+ }
333
+ /**
334
+ * Gets the global profile data version.
335
+ *
336
+ * @remarks
337
+ * The value is incremented whenever a profile slot is allocated or profile
338
+ * data changes, allowing render systems to refresh cached profile textures.
339
+ *
340
+ * @public
341
+ */ static get version() {
342
+ return this._version;
343
+ }
344
+ /**
345
+ * Gets the profile assigned to a packed profile slot.
346
+ *
347
+ * @param slot - The 1-based profile slot index.
348
+ * @returns The profile assigned to the slot, or `null` if the slot is invalid or unused.
349
+ *
350
+ * @public
351
+ */ static getProfileBySlot(slot) {
352
+ return slot > 0 && slot < this._profiles.length ? this._profiles[slot] : null;
353
+ }
354
+ /**
355
+ * Gets the shared default skin subsurface profile.
356
+ *
357
+ * @returns The lazily-created default skin profile.
358
+ *
359
+ * @public
360
+ */ static getDefaultSkinProfile() {
361
+ if (!this._defaultSkinProfile) {
362
+ this._defaultSkinProfile = new SubsurfaceProfile();
363
+ }
364
+ return this._defaultSkinProfile;
365
+ }
366
+ /**
367
+ * Gets the preset tint bias used by the screen-space transmission model.
368
+ *
369
+ * @param index - The packed canonical preset index.
370
+ * @returns The RGB tint bias for the preset, or white when the index is unknown.
371
+ *
372
+ * @public
373
+ */ static getPresetTintBiasByIndex(index) {
374
+ return SUBSURFACE_PROFILE_PRESET_TINT_BIAS[this.getPresetNameByIndex(index)] ?? [
375
+ 1,
376
+ 1,
377
+ 1
378
+ ];
379
+ }
380
+ /**
381
+ * Gets the preset transmission response used by the screen-space SSS pass.
382
+ *
383
+ * @param index - The packed canonical preset index.
384
+ * @returns The four-component transmission response for the preset.
385
+ *
386
+ * @public
387
+ */ static getPresetResponseByIndex(index) {
388
+ return SUBSURFACE_PROFILE_PRESET_RESPONSE[this.getPresetNameByIndex(index)] ?? [
389
+ 0,
390
+ 0,
391
+ 0,
392
+ 0
393
+ ];
394
+ }
395
+ /**
396
+ * Computes the effective tint bias from the preset and current profile settings.
397
+ *
398
+ * @returns The derived RGB tint bias used for transmission tinting.
399
+ *
400
+ * @public
401
+ */ getDerivedTintBias() {
402
+ const base = SUBSURFACE_PROFILE_PRESET_TINT_BIAS[this._preset] ?? [
403
+ 1,
404
+ 1,
405
+ 1
406
+ ];
407
+ const factors = this.getDerivedProfileFactors();
408
+ const derived = [
409
+ this.clamp01(0.78 + factors.warmBias * 0.26 - factors.coolBias * 0.16 + factors.boundaryNorm * 0.04),
410
+ this.clamp01(0.3 + factors.meanFreePathColor[1] * 0.24 + factors.transmissionTintColor[1] * 0.28 + factors.distanceNorm * 0.08 + factors.scaleNorm * 0.05 + factors.boundaryNorm * 0.08 + factors.coolBias * 0.06),
411
+ this.clamp01(0.14 + factors.meanFreePathColor[2] * 0.22 + factors.transmissionTintColor[2] * 0.32 + factors.distanceNorm * 0.06 + factors.boundaryNorm * 0.06 + factors.coolBias * 0.12 - factors.warmBias * 0.06)
412
+ ];
413
+ const blend = this.clampRange(0.26 + factors.radiusNorm * 0.16 + factors.scaleNorm * 0.1 + factors.strengthNorm * 0.08, 0.25, 0.88);
414
+ return [
415
+ this.mixNumber(base[0], derived[0], blend),
416
+ this.mixNumber(base[1], derived[1], blend),
417
+ this.mixNumber(base[2], derived[2], blend)
418
+ ];
419
+ }
420
+ /**
421
+ * Computes the effective transmission response from the preset and current profile settings.
422
+ *
423
+ * @returns The derived transmission response packed as four scalar channels.
424
+ *
425
+ * @public
426
+ */ getDerivedTransmissionResponse() {
427
+ const base = SUBSURFACE_PROFILE_PRESET_RESPONSE[this._preset] ?? [
428
+ 0,
429
+ 0,
430
+ 0,
431
+ 0
432
+ ];
433
+ const factors = this.getDerivedProfileFactors();
434
+ const blend = this.clampRange(0.32 + factors.distanceNorm * 0.18 + factors.scaleNorm * 0.12 + factors.strengthNorm * 0.1 + factors.boundaryNorm * 0.06, 0.28, 0.9);
435
+ const derived = [
436
+ this.clampRange(-0.06 + factors.radiusNorm * 0.08 + factors.distanceNorm * 0.08 + factors.strengthNorm * 0.05 + factors.distributionNorm * 0.04 + factors.boundaryNorm * 0.05 + factors.extinctionSoftness * 0.03, -0.25, 0.45),
437
+ this.clampRange(0.02 + factors.radiusNorm * 0.1 + factors.scaleNorm * 0.08 + factors.worldScaleNorm * 0.04 + factors.distributionNorm * 0.08 + factors.extinctionSoftness * 0.06, -0.25, 0.45),
438
+ this.clampRange(-0.08 + factors.strengthNorm * 0.12 + factors.scaleNorm * 0.08 + factors.extinctionSoftness * 0.12 + factors.boundaryNorm * 0.06 + factors.warmBias * 0.05 - factors.coolBias * 0.04, -0.25, 0.45),
439
+ this.clampRange(-0.02 + factors.radiusNorm * 0.12 + factors.scaleNorm * 0.08 + factors.strengthNorm * 0.06 + factors.boundaryNorm * 0.06 + factors.extinctionSoftness * 0.16 + factors.warmBias * 0.07 + factors.transmissionTintColor[0] * 0.04, -0.25, 0.5)
440
+ ];
441
+ return [
442
+ this.clampRange(this.mixNumber(base[0], derived[0], blend), -0.25, 0.45),
443
+ this.clampRange(this.mixNumber(base[1], derived[1], blend), -0.25, 0.45),
444
+ this.clampRange(this.mixNumber(base[2], derived[2], blend), -0.25, 0.45),
445
+ this.clampRange(this.mixNumber(base[3], derived[3], blend), -0.25, 0.5)
446
+ ];
447
+ }
448
+ /**
449
+ * Gets the 1-based profile slot used when encoding this profile into SSS buffers.
450
+ *
451
+ * @public
452
+ */ get slot() {
453
+ return this._slot;
454
+ }
455
+ /**
456
+ * Gets or sets the RGB scatter radius.
457
+ *
458
+ * @remarks
459
+ * Assigning a radius also updates the mean-free-path authoring controls.
460
+ *
461
+ * @public
462
+ */ get scatterRadius() {
463
+ return this._scatterRadius;
464
+ }
465
+ set scatterRadius(val) {
466
+ if (!val.equalsTo(this._scatterRadius)) {
467
+ this._scatterRadius.set(val);
468
+ this.syncMeanFreePathFromScatterRadius();
469
+ }
470
+ }
471
+ /**
472
+ * Gets or sets the channel falloff color used by the diffusion kernel.
473
+ *
474
+ * @public
475
+ */ get falloffColor() {
476
+ return this._falloffColor;
477
+ }
478
+ set falloffColor(val) {
479
+ if (!val.equalsTo(this._falloffColor)) {
480
+ this._falloffColor.set(val);
481
+ this.markDirty();
482
+ }
483
+ }
484
+ /**
485
+ * Mean free path color used to derive channel-dependent scatter radius.
486
+ *
487
+ * @remarks
488
+ * This is a more UE-like authoring control that keeps the existing radius-
489
+ * based implementation, while letting tools expose a color + distance pair.
490
+ *
491
+ * @public
492
+ */ get meanFreePathColor() {
493
+ return this._meanFreePathColor;
494
+ }
495
+ set meanFreePathColor(val) {
496
+ if (!val.equalsTo(this._meanFreePathColor)) {
497
+ this._meanFreePathColor.set(val);
498
+ this.syncScatterRadiusFromMeanFreePath();
499
+ }
500
+ }
501
+ /**
502
+ * Gets or sets the mean free path distance used to derive the absolute scatter radius.
503
+ *
504
+ * @public
505
+ */ get meanFreePathDistance() {
506
+ return this._meanFreePathDistance;
507
+ }
508
+ set meanFreePathDistance(val) {
509
+ const next = Math.max(0, val ?? 0);
510
+ if (next !== this._meanFreePathDistance) {
511
+ this._meanFreePathDistance = next;
512
+ this.syncScatterRadiusFromMeanFreePath();
513
+ }
514
+ }
515
+ /**
516
+ * Gets or sets the active subsurface profile preset.
517
+ *
518
+ * @remarks
519
+ * Assigning a preset applies its template values to the profile. Alias preset
520
+ * names are resolved to their canonical preset.
521
+ *
522
+ * @public
523
+ */ get preset() {
524
+ return this._preset;
525
+ }
526
+ set preset(val) {
527
+ const next = SubsurfaceProfile.resolvePreset(val);
528
+ if (next !== this._preset) {
529
+ this._preset = next;
530
+ this.applyPresetTemplate(next);
531
+ }
532
+ }
533
+ /**
534
+ * Gets the packed canonical preset index.
535
+ *
536
+ * @public
537
+ */ get presetIndex() {
538
+ return SUBSURFACE_PROFILE_PRESET_INDEX[this._preset] ?? 0;
539
+ }
540
+ /**
541
+ * Gets or sets the SSS strength multiplier.
542
+ *
543
+ * @public
544
+ */ get strength() {
545
+ return this._strength;
546
+ }
547
+ set strength(val) {
548
+ if (val !== this._strength) {
549
+ this._strength = val;
550
+ this.markDirty();
551
+ }
552
+ }
553
+ /**
554
+ * Gets or sets the screen-space scatter width scale.
555
+ *
556
+ * @public
557
+ */ get scale() {
558
+ return this._scale;
559
+ }
560
+ set scale(val) {
561
+ if (val !== this._scale) {
562
+ this._scale = val;
563
+ this.markDirty();
564
+ }
565
+ }
566
+ /**
567
+ * Gets or sets the world-unit scale used when converting profile radii.
568
+ *
569
+ * @public
570
+ */ get worldUnitScale() {
571
+ return this._worldUnitScale;
572
+ }
573
+ set worldUnitScale(val) {
574
+ const next = Math.max(0.05, val ?? 0.05);
575
+ if (next !== this._worldUnitScale) {
576
+ this._worldUnitScale = next;
577
+ this.markDirty();
578
+ }
579
+ }
580
+ /**
581
+ * Gets or sets the amount of color bleeding preserved near SSS boundaries.
582
+ *
583
+ * @remarks
584
+ * Values are clamped to the `[0, 1]` range.
585
+ *
586
+ * @public
587
+ */ get boundaryColorBleed() {
588
+ return this._boundaryColorBleed;
589
+ }
590
+ set boundaryColorBleed(val) {
591
+ const next = this.clamp01(val ?? 0);
592
+ if (next !== this._boundaryColorBleed) {
593
+ this._boundaryColorBleed = next;
594
+ this.markDirty();
595
+ }
596
+ }
597
+ /**
598
+ * Gets or sets the RGB tint applied to transmitted subsurface light.
599
+ *
600
+ * @public
601
+ */ get transmissionTintColor() {
602
+ return this._transmissionTintColor;
603
+ }
604
+ set transmissionTintColor(val) {
605
+ if (!val.equalsTo(this._transmissionTintColor)) {
606
+ this._transmissionTintColor.set(val);
607
+ this.markDirty();
608
+ }
609
+ }
610
+ /**
611
+ * Gets or sets the extinction multiplier used by transmission attenuation.
612
+ *
613
+ * @remarks
614
+ * Values are clamped to zero or greater.
615
+ *
616
+ * @public
617
+ */ get extinctionScale() {
618
+ return this._extinctionScale;
619
+ }
620
+ set extinctionScale(val) {
621
+ const next = Math.max(0, val ?? 0);
622
+ if (next !== this._extinctionScale) {
623
+ this._extinctionScale = next;
624
+ this.markDirty();
625
+ }
626
+ }
627
+ /**
628
+ * Gets or sets the normal sensitivity scale used by SSS filtering.
629
+ *
630
+ * @remarks
631
+ * Values are clamped to zero or greater.
632
+ *
633
+ * @public
634
+ */ get normalScale() {
635
+ return this._normalScale;
636
+ }
637
+ set normalScale(val) {
638
+ const next = Math.max(0, val ?? 0);
639
+ if (next !== this._normalScale) {
640
+ this._normalScale = next;
641
+ this.markDirty();
642
+ }
643
+ }
644
+ /**
645
+ * Gets or sets the scattering distribution blend.
646
+ *
647
+ * @remarks
648
+ * Values are clamped to the `[0, 1]` range.
649
+ *
650
+ * @public
651
+ */ get scatteringDistribution() {
652
+ return this._scatteringDistribution;
653
+ }
654
+ set scatteringDistribution(val) {
655
+ const next = this.clamp01(val ?? 0);
656
+ if (next !== this._scatteringDistribution) {
657
+ this._scatteringDistribution = next;
658
+ this.markDirty();
659
+ }
660
+ }
661
+ /**
662
+ * Adds a listener that is invoked whenever this profile changes.
663
+ *
664
+ * @param listener - The callback to invoke after profile data changes.
665
+ *
666
+ * @public
667
+ */ addChangeListener(listener) {
668
+ this._changeListeners.add(listener);
669
+ }
670
+ /**
671
+ * Removes a previously registered profile change listener.
672
+ *
673
+ * @param listener - The callback to remove.
674
+ *
675
+ * @public
676
+ */ removeChangeListener(listener) {
677
+ this._changeListeners.delete(listener);
678
+ }
679
+ static allocateSlot(profile) {
680
+ for(let i = 1; i < this._profiles.length; i++){
681
+ if (!this._profiles[i]) {
682
+ this._profiles[i] = profile;
683
+ this._version++;
684
+ return i;
685
+ }
686
+ }
687
+ throw new Error('SubsurfaceProfile limit exceeded');
688
+ }
689
+ markDirty() {
690
+ SubsurfaceProfile._version++;
691
+ this._changeListeners.forEach((listener)=>listener());
692
+ }
693
+ static resolvePreset(preset) {
694
+ return SUBSURFACE_PROFILE_PRESET_ALIAS[preset ?? 'skin_default'] ?? 'skin_default';
695
+ }
696
+ static getPresetNameByIndex(index) {
697
+ for (const [name, presetIndex] of Object.entries(SUBSURFACE_PROFILE_PRESET_INDEX)){
698
+ if (presetIndex === index) {
699
+ return name;
700
+ }
701
+ }
702
+ return 'skin_default';
703
+ }
704
+ applyPresetTemplate(preset, markDirty = true) {
705
+ const template = SUBSURFACE_PROFILE_PRESET_TEMPLATE[preset] ?? SUBSURFACE_PROFILE_PRESET_TEMPLATE.skin_default;
706
+ this._meanFreePathColor.setXYZ(template.meanFreePathColor[0], template.meanFreePathColor[1], template.meanFreePathColor[2]);
707
+ this._meanFreePathDistance = template.meanFreePathDistance;
708
+ this._strength = template.strength;
709
+ this._scale = template.scale;
710
+ this._worldUnitScale = template.worldUnitScale;
711
+ this._boundaryColorBleed = template.boundaryColorBleed;
712
+ this._transmissionTintColor.setXYZ(template.transmissionTintColor[0], template.transmissionTintColor[1], template.transmissionTintColor[2]);
713
+ this._extinctionScale = template.extinctionScale;
714
+ this._normalScale = template.normalScale;
715
+ this._scatteringDistribution = template.scatteringDistribution;
716
+ this.syncScatterRadiusFromMeanFreePath(false);
717
+ if (markDirty) {
718
+ this.markDirty();
719
+ }
720
+ }
721
+ syncMeanFreePathFromScatterRadius(markDirty = true) {
722
+ const maxRadius = Math.max(this._scatterRadius.x, this._scatterRadius.y, this._scatterRadius.z);
723
+ if (maxRadius > 1e-5) {
724
+ this._meanFreePathDistance = maxRadius;
725
+ this._meanFreePathColor.setXYZ(this._scatterRadius.x / maxRadius, this._scatterRadius.y / maxRadius, this._scatterRadius.z / maxRadius);
726
+ } else {
727
+ this._meanFreePathDistance = 0;
728
+ this._meanFreePathColor.setXYZ(0, 0, 0);
729
+ }
730
+ this.syncFalloffFromMeanFreePath(false);
731
+ if (markDirty) {
732
+ this.markDirty();
733
+ }
734
+ }
735
+ syncScatterRadiusFromMeanFreePath(markDirty = true) {
736
+ const distance = Math.max(0, this._meanFreePathDistance);
737
+ this._scatterRadius.setXYZ(Math.max(0, this._meanFreePathColor.x) * distance, Math.max(0, this._meanFreePathColor.y) * distance, Math.max(0, this._meanFreePathColor.z) * distance);
738
+ this.syncFalloffFromMeanFreePath(false);
739
+ if (markDirty) {
740
+ this.markDirty();
741
+ }
742
+ }
743
+ syncFalloffFromMeanFreePath(markDirty = true) {
744
+ const base = SUBSURFACE_PROFILE_PRESET_TEMPLATE[this._preset]?.falloffColor ?? SUBSURFACE_PROFILE_PRESET_TEMPLATE.skin_default.falloffColor;
745
+ const factors = this.getDerivedProfileFactors();
746
+ const derivedG = this.clamp01(0.12 + factors.meanFreePathColor[1] * 0.4 + factors.transmissionTintColor[1] * 0.12 + factors.distanceNorm * 0.05 + factors.scaleNorm * 0.05 + factors.distributionNorm * 0.05 - (1 - factors.extinctionSoftness) * 0.04);
747
+ const derivedB = this.clamp01(0.04 + factors.meanFreePathColor[2] * 0.32 + factors.transmissionTintColor[2] * 0.18 + factors.distanceNorm * 0.04 + factors.boundaryNorm * 0.05 + factors.coolBias * 0.08 - factors.warmBias * 0.04);
748
+ const blend = this.clampRange(0.24 + factors.distanceNorm * 0.16 + factors.scaleNorm * 0.12 + factors.strengthNorm * 0.08, 0.22, 0.82);
749
+ this._falloffColor.setXYZ(1, this.mixNumber(base[1], derivedG, blend), this.mixNumber(base[2], derivedB, blend));
750
+ if (markDirty) {
751
+ this.markDirty();
752
+ }
753
+ }
754
+ getNormalizedTransmissionTintColor() {
755
+ const maxChannel = Math.max(this._transmissionTintColor.x, this._transmissionTintColor.y, this._transmissionTintColor.z, 1e-5);
756
+ return [
757
+ Math.max(0, this._transmissionTintColor.x) / maxChannel,
758
+ Math.max(0, this._transmissionTintColor.y) / maxChannel,
759
+ Math.max(0, this._transmissionTintColor.z) / maxChannel
760
+ ];
761
+ }
762
+ getDerivedProfileFactors() {
763
+ const meanFreePathColor = this.getNormalizedMeanFreePathColor();
764
+ const transmissionTintColor = this.getNormalizedTransmissionTintColor();
765
+ const maxRadius = Math.max(this._scatterRadius.x, this._scatterRadius.y, this._scatterRadius.z);
766
+ const radiusNorm = this.clampRange(maxRadius / 1.35, 0, 1.5);
767
+ const distanceNorm = this.clampRange(this._meanFreePathDistance / 1.25, 0, 1.5);
768
+ const scaleNorm = this.clampRange(this._scale / 1.35, 0, 1.5);
769
+ const strengthNorm = this.clampRange(this._strength / 1.2, 0, 1.5);
770
+ const worldScaleNorm = this.clampRange(this._worldUnitScale / 1.25, 0, 1.5);
771
+ const boundaryNorm = this.clamp01(this._boundaryColorBleed);
772
+ const distributionNorm = this.clamp01(this._scatteringDistribution);
773
+ const extinctionWeight = this.clampRange(1 / Math.max(this._extinctionScale, 0.35), 0.25, 1.35);
774
+ const extinctionSoftness = this.clamp01((extinctionWeight - 0.25) / 1.1);
775
+ const warmBias = this.clamp01(0.5 + (meanFreePathColor[0] - Math.max(meanFreePathColor[1], meanFreePathColor[2]) * 0.72) * 0.95 + (transmissionTintColor[0] - Math.max(transmissionTintColor[1], transmissionTintColor[2]) * 0.78) * 0.7);
776
+ const coolBias = this.clamp01(0.32 + (transmissionTintColor[2] - transmissionTintColor[0] * 0.55) * 0.55 + (meanFreePathColor[2] - meanFreePathColor[0] * 0.65) * 0.45);
777
+ return {
778
+ meanFreePathColor,
779
+ transmissionTintColor,
780
+ radiusNorm,
781
+ distanceNorm,
782
+ scaleNorm,
783
+ strengthNorm,
784
+ worldScaleNorm,
785
+ boundaryNorm,
786
+ distributionNorm,
787
+ extinctionSoftness,
788
+ warmBias,
789
+ coolBias
790
+ };
791
+ }
792
+ getNormalizedMeanFreePathColor() {
793
+ const maxChannel = Math.max(this._meanFreePathColor.x, this._meanFreePathColor.y, this._meanFreePathColor.z, 1e-5);
794
+ return [
795
+ Math.max(0, this._meanFreePathColor.x) / maxChannel,
796
+ Math.max(0, this._meanFreePathColor.y) / maxChannel,
797
+ Math.max(0, this._meanFreePathColor.z) / maxChannel
798
+ ];
799
+ }
800
+ mixNumber(a, b, t) {
801
+ return a * (1 - t) + b * t;
802
+ }
803
+ clampRange(value, minValue, maxValue) {
804
+ return Math.max(minValue, Math.min(maxValue, value));
805
+ }
806
+ clamp01(value) {
807
+ return Math.max(0, Math.min(1, value));
808
+ }
809
+ }
810
+
811
+ export { SubsurfaceProfile };
812
+ //# sourceMappingURL=subsurfaceprofile.js.map