@zephyr3d/scene 0.9.25 → 0.9.26

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 (262) hide show
  1. package/dist/animation/hair/gpu_hair_simulation.js +1090 -0
  2. package/dist/animation/hair/gpu_hair_simulation.js.map +1 -0
  3. package/dist/animation/joint_dynamics/controller.js +7 -5
  4. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  5. package/dist/animation/joint_dynamics/joint_dynamics_system.js +81 -5
  6. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  7. package/dist/animation/morphtrack.js +3 -4
  8. package/dist/animation/morphtrack.js.map +1 -1
  9. package/dist/animation/skeleton.js +58 -24
  10. package/dist/animation/skeleton.js.map +1 -1
  11. package/dist/animation/spring/multi_chain_spring_system.js +577 -179
  12. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  13. package/dist/animation/spring/spring_collider.js +4 -3
  14. package/dist/animation/spring/spring_collider.js.map +1 -1
  15. package/dist/animation/spring/spring_node_pose_tracker.js +40 -0
  16. package/dist/animation/spring/spring_node_pose_tracker.js.map +1 -0
  17. package/dist/animation/spring/spring_particle.js +2 -0
  18. package/dist/animation/spring/spring_particle.js.map +1 -1
  19. package/dist/animation/spring/spring_system.js +11 -3
  20. package/dist/animation/spring/spring_system.js.map +1 -1
  21. package/dist/animation/spring_modifier.js +10 -0
  22. package/dist/animation/spring_modifier.js.map +1 -1
  23. package/dist/app/engine.js +53 -43
  24. package/dist/app/engine.js.map +1 -1
  25. package/dist/app/scriptingsystem.js +119 -6
  26. package/dist/app/scriptingsystem.js.map +1 -1
  27. package/dist/app/scriptregistry.js +3 -2
  28. package/dist/app/scriptregistry.js.map +1 -1
  29. package/dist/asset/assetmanager.js +284 -67
  30. package/dist/asset/assetmanager.js.map +1 -1
  31. package/dist/asset/loaders/zhair/zhair_format.js +288 -0
  32. package/dist/asset/loaders/zhair/zhair_format.js.map +1 -0
  33. package/dist/asset/loaders/zhair/zhair_loader.js +221 -0
  34. package/dist/asset/loaders/zhair/zhair_loader.js.map +1 -0
  35. package/dist/asset/model.js +178 -67
  36. package/dist/asset/model.js.map +1 -1
  37. package/dist/camera/camera.js +193 -21
  38. package/dist/camera/camera.js.map +1 -1
  39. package/dist/camera/perspectivecamera.js +3 -1
  40. package/dist/camera/perspectivecamera.js.map +1 -1
  41. package/dist/index.d.ts +4019 -1278
  42. package/dist/index.js +15 -5
  43. package/dist/index.js.map +1 -1
  44. package/dist/material/eye.js +932 -0
  45. package/dist/material/eye.js.map +1 -0
  46. package/dist/material/hair.js +917 -0
  47. package/dist/material/hair.js.map +1 -0
  48. package/dist/material/hairstrand.js +842 -0
  49. package/dist/material/hairstrand.js.map +1 -0
  50. package/dist/material/hairstrand_data.js +162 -0
  51. package/dist/material/hairstrand_data.js.map +1 -0
  52. package/dist/material/lambert.js +5 -2
  53. package/dist/material/lambert.js.map +1 -1
  54. package/dist/material/material.js +338 -300
  55. package/dist/material/material.js.map +1 -1
  56. package/dist/material/meshmaterial.js +120 -19
  57. package/dist/material/meshmaterial.js.map +1 -1
  58. package/dist/material/mixins/albedocolor.js +1 -1
  59. package/dist/material/mixins/albedocolor.js.map +1 -1
  60. package/dist/material/mixins/lightmodel/blinnphong.js +5 -3
  61. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  62. package/dist/material/mixins/lightmodel/lambert.js +5 -4
  63. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  64. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +3 -3
  65. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  66. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +5 -5
  67. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  68. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +3 -3
  69. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  70. package/dist/material/mixins/lit.js +73 -18
  71. package/dist/material/mixins/lit.js.map +1 -1
  72. package/dist/material/mixins/pbr/common.js +4 -4
  73. package/dist/material/mixins/pbr/common.js.map +1 -1
  74. package/dist/material/mixins/texture.js +48 -11
  75. package/dist/material/mixins/texture.js.map +1 -1
  76. package/dist/material/mtoon.js +6 -5
  77. package/dist/material/mtoon.js.map +1 -1
  78. package/dist/material/pbrblueprint.js +146 -28
  79. package/dist/material/pbrblueprint.js.map +1 -1
  80. package/dist/material/pbrblueprint_instance.js +501 -0
  81. package/dist/material/pbrblueprint_instance.js.map +1 -0
  82. package/dist/material/pbrmr.js +15 -16
  83. package/dist/material/pbrmr.js.map +1 -1
  84. package/dist/material/shader/helper.js +330 -20
  85. package/dist/material/shader/helper.js.map +1 -1
  86. package/dist/material/shader/terrain_blend.js +55 -0
  87. package/dist/material/shader/terrain_blend.js.map +1 -0
  88. package/dist/material/skin.js +192 -32
  89. package/dist/material/skin.js.map +1 -1
  90. package/dist/material/spriteblueprint.js +16 -1
  91. package/dist/material/spriteblueprint.js.map +1 -1
  92. package/dist/material/subsurfaceprofile.js +86 -23
  93. package/dist/material/subsurfaceprofile.js.map +1 -1
  94. package/dist/material/water.js +3 -1
  95. package/dist/material/water.js.map +1 -1
  96. package/dist/posteffect/bloom.js +167 -7
  97. package/dist/posteffect/bloom.js.map +1 -1
  98. package/dist/posteffect/coloradjust.js +2 -1
  99. package/dist/posteffect/coloradjust.js.map +1 -1
  100. package/dist/posteffect/compositor.js.map +1 -1
  101. package/dist/posteffect/fxaa.js +2 -1
  102. package/dist/posteffect/fxaa.js.map +1 -1
  103. package/dist/posteffect/grayscale.js +3 -1
  104. package/dist/posteffect/grayscale.js.map +1 -1
  105. package/dist/posteffect/motionblur.js +4 -1
  106. package/dist/posteffect/motionblur.js.map +1 -1
  107. package/dist/posteffect/posteffect.js.map +1 -1
  108. package/dist/posteffect/skinsss.js +368 -69
  109. package/dist/posteffect/skinsss.js.map +1 -1
  110. package/dist/posteffect/ssgi.js +16 -9
  111. package/dist/posteffect/ssgi.js.map +1 -1
  112. package/dist/posteffect/ssr.js +3 -0
  113. package/dist/posteffect/ssr.js.map +1 -1
  114. package/dist/posteffect/sss.js +91 -34
  115. package/dist/posteffect/sss.js.map +1 -1
  116. package/dist/posteffect/taa.js.map +1 -1
  117. package/dist/posteffect/tonemap.js +44 -1
  118. package/dist/posteffect/tonemap.js.map +1 -1
  119. package/dist/render/abuffer_oit.js +45 -39
  120. package/dist/render/abuffer_oit.js.map +1 -1
  121. package/dist/render/cull_visitor.js +19 -0
  122. package/dist/render/cull_visitor.js.map +1 -1
  123. package/dist/render/depthpass.js +36 -2
  124. package/dist/render/depthpass.js.map +1 -1
  125. package/dist/render/drawable_mixin.js +26 -1
  126. package/dist/render/drawable_mixin.js.map +1 -1
  127. package/dist/render/dualdepthpeeling_oit.js +52 -51
  128. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  129. package/dist/render/envlight.js +1 -1
  130. package/dist/render/envlight.js.map +1 -1
  131. package/dist/render/fbm_wavegenerator.js +3 -0
  132. package/dist/render/fbm_wavegenerator.js.map +1 -1
  133. package/dist/render/gerstner_wavegenerator.js +3 -0
  134. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  135. package/dist/render/globalbindgroup_allocator.js +3 -0
  136. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  137. package/dist/render/oit.js +29 -0
  138. package/dist/render/oit.js.map +1 -0
  139. package/dist/render/render_queue.js +3 -0
  140. package/dist/render/render_queue.js.map +1 -1
  141. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -1
  142. package/dist/render/rendergraph/executor.js +2 -0
  143. package/dist/render/rendergraph/executor.js.map +1 -1
  144. package/dist/render/rendergraph/forward_plus_builder.js +61 -1
  145. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  146. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  147. package/dist/render/rendergraph/texture_affinity_cache.js +1 -1
  148. package/dist/render/rendergraph/texture_affinity_cache.js.map +1 -1
  149. package/dist/render/rendergraph/types.js.map +1 -1
  150. package/dist/render/shadow_mask_pass.js +73 -8
  151. package/dist/render/shadow_mask_pass.js.map +1 -1
  152. package/dist/render/sky.js +166 -126
  153. package/dist/render/sky.js.map +1 -1
  154. package/dist/render/weightedblended_oit.js +36 -35
  155. package/dist/render/weightedblended_oit.js.map +1 -1
  156. package/dist/scene/basesprite.js +8 -0
  157. package/dist/scene/basesprite.js.map +1 -1
  158. package/dist/scene/batchgroup.js +3 -0
  159. package/dist/scene/batchgroup.js.map +1 -1
  160. package/dist/scene/environment.js +4 -1
  161. package/dist/scene/environment.js.map +1 -1
  162. package/dist/scene/hair.js +963 -0
  163. package/dist/scene/hair.js.map +1 -0
  164. package/dist/scene/light.js +5 -1
  165. package/dist/scene/light.js.map +1 -1
  166. package/dist/scene/mesh.js +481 -47
  167. package/dist/scene/mesh.js.map +1 -1
  168. package/dist/scene/meshdrawable.js +6 -0
  169. package/dist/scene/meshdrawable.js.map +1 -1
  170. package/dist/scene/msdftext.js +3 -0
  171. package/dist/scene/msdftext.js.map +1 -1
  172. package/dist/scene/msdftextsprite.js +3 -0
  173. package/dist/scene/msdftextsprite.js.map +1 -1
  174. package/dist/scene/particlesys.js +6 -0
  175. package/dist/scene/particlesys.js.map +1 -1
  176. package/dist/scene/scene.js +3 -0
  177. package/dist/scene/scene.js.map +1 -1
  178. package/dist/scene/scene_node.js +6 -1
  179. package/dist/scene/scene_node.js.map +1 -1
  180. package/dist/scene/terrain-cm/grass.js +3 -0
  181. package/dist/scene/terrain-cm/grass.js.map +1 -1
  182. package/dist/scene/terrain-cm/grassmaterial.js +3 -0
  183. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  184. package/dist/scene/terrain-cm/terrain-cm.js +6 -0
  185. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  186. package/dist/scene/terrain-cm/texture_cache.js +309 -0
  187. package/dist/scene/terrain-cm/texture_cache.js.map +1 -0
  188. package/dist/scene/water.js +6 -0
  189. package/dist/scene/water.js.map +1 -1
  190. package/dist/shaders/atmosphere.js.map +1 -1
  191. package/dist/shaders/diffusion.js +54 -0
  192. package/dist/shaders/diffusion.js.map +1 -0
  193. package/dist/shaders/shadow.js +33 -21
  194. package/dist/shaders/shadow.js.map +1 -1
  195. package/dist/shaders/temporal.js +71 -33
  196. package/dist/shaders/temporal.js.map +1 -1
  197. package/dist/shadow/dom.js +546 -0
  198. package/dist/shadow/dom.js.map +1 -0
  199. package/dist/shadow/pcf_opt.js +3 -5
  200. package/dist/shadow/pcf_opt.js.map +1 -1
  201. package/dist/shadow/pcf_pd.js +1 -1
  202. package/dist/shadow/pcf_pd.js.map +1 -1
  203. package/dist/shadow/receiver_bias.js +41 -0
  204. package/dist/shadow/receiver_bias.js.map +1 -0
  205. package/dist/shadow/shader.js +20 -60
  206. package/dist/shadow/shader.js.map +1 -1
  207. package/dist/shadow/shadow_impl.js +89 -0
  208. package/dist/shadow/shadow_impl.js.map +1 -1
  209. package/dist/shadow/shadow_region.js +50 -50
  210. package/dist/shadow/shadow_region.js.map +1 -1
  211. package/dist/shadow/shadowmapper.js +150 -37
  212. package/dist/shadow/shadowmapper.js.map +1 -1
  213. package/dist/shapes/shape.js +11 -2
  214. package/dist/shapes/shape.js.map +1 -1
  215. package/dist/shapes/sphere.js +50 -9
  216. package/dist/shapes/sphere.js.map +1 -1
  217. package/dist/utility/blueprint/common/constants.js +112 -2
  218. package/dist/utility/blueprint/common/constants.js.map +1 -1
  219. package/dist/utility/blueprint/material/func.js +142 -49
  220. package/dist/utility/blueprint/material/func.js.map +1 -1
  221. package/dist/utility/blueprint/material/ir.js +490 -25
  222. package/dist/utility/blueprint/material/ir.js.map +1 -1
  223. package/dist/utility/blueprint/material/texture.js +898 -4
  224. package/dist/utility/blueprint/material/texture.js.map +1 -1
  225. package/dist/utility/serialization/manager.js +431 -100
  226. package/dist/utility/serialization/manager.js.map +1 -1
  227. package/dist/utility/serialization/scene/animation.js +370 -3
  228. package/dist/utility/serialization/scene/animation.js.map +1 -1
  229. package/dist/utility/serialization/scene/batch.js +4 -0
  230. package/dist/utility/serialization/scene/batch.js.map +1 -1
  231. package/dist/utility/serialization/scene/camera.js +133 -1
  232. package/dist/utility/serialization/scene/camera.js.map +1 -1
  233. package/dist/utility/serialization/scene/common.js +26 -5
  234. package/dist/utility/serialization/scene/common.js.map +1 -1
  235. package/dist/utility/serialization/scene/hair.js +1141 -0
  236. package/dist/utility/serialization/scene/hair.js.map +1 -0
  237. package/dist/utility/serialization/scene/light.js +84 -4
  238. package/dist/utility/serialization/scene/light.js.map +1 -1
  239. package/dist/utility/serialization/scene/material.js +1867 -166
  240. package/dist/utility/serialization/scene/material.js.map +1 -1
  241. package/dist/utility/serialization/scene/mesh.js +231 -14
  242. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  243. package/dist/utility/serialization/scene/node.js +141 -7
  244. package/dist/utility/serialization/scene/node.js.map +1 -1
  245. package/dist/utility/serialization/scene/particle.js +4 -0
  246. package/dist/utility/serialization/scene/particle.js.map +1 -1
  247. package/dist/utility/serialization/scene/primitive.js +18 -0
  248. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  249. package/dist/utility/serialization/scene/sprite.js +4 -0
  250. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  251. package/dist/utility/serialization/scene/terrain.js +4 -0
  252. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  253. package/dist/utility/serialization/scene/text.js +4 -0
  254. package/dist/utility/serialization/scene/text.js.map +1 -1
  255. package/dist/utility/serialization/scene/water.js +4 -0
  256. package/dist/utility/serialization/scene/water.js.map +1 -1
  257. package/dist/utility/serialization/types.js.map +1 -1
  258. package/dist/utility/shprojector.js +96 -95
  259. package/dist/utility/shprojector.js.map +1 -1
  260. package/dist/values.js +49 -2
  261. package/dist/values.js.map +1 -1
  262. package/package.json +3 -3
@@ -1,6 +1,7 @@
1
1
  import { DRef, Vector4 } from '@zephyr3d/base';
2
2
  import { SpriteBlockNode } from '../utility/blueprint/material/pbr.js';
3
3
  import { MaterialBlueprintIR } from '../utility/blueprint/material/ir.js';
4
+ import { getDefaultTexture2D } from '../utility/blueprint/material/texture.js';
4
5
  import { SpriteMaterial } from './sprite.js';
5
6
 
6
7
  /**
@@ -89,6 +90,7 @@ import { SpriteMaterial } from './sprite.js';
89
90
  val = val ?? [];
90
91
  if (val !== this._uniformTextures) {
91
92
  const newUniforms = val.map((v)=>({
93
+ exposed: v.exposed ?? true,
92
94
  finalTexture: new DRef(v.finalTexture.get()),
93
95
  finalSampler: v.finalSampler,
94
96
  name: v.name,
@@ -145,7 +147,7 @@ import { SpriteMaterial } from './sprite.js';
145
147
  bindGroup.setValue(u.name, u.finalValue);
146
148
  }
147
149
  for (const u of this._uniformTextures){
148
- bindGroup.setTexture(u.name, u.finalTexture.get(), u.finalSampler);
150
+ bindGroup.setTexture(u.name, u.finalTexture?.get() ?? getDefaultTexture2D(), u.finalSampler);
149
151
  }
150
152
  }
151
153
  }
@@ -165,6 +167,19 @@ import { SpriteMaterial } from './sprite.js';
165
167
  * @returns A shader expression representing the final fragment color.
166
168
  */ calcFragmentColor(scope) {
167
169
  const pb = scope.$builder;
170
+ for (const u of this._uniformTextures){
171
+ if (!pb.getGlobalScope()[u.name]) {
172
+ // @ts-ignore dynamic shader type constructor
173
+ const exp = pb[u.type]().uniform(2).withSampler({
174
+ addressU: u.wrapS,
175
+ addressV: u.wrapT,
176
+ minFilter: u.minFilter,
177
+ magFilter: u.magFilter,
178
+ mipFilter: u.mipFilter
179
+ });
180
+ pb.getGlobalScope()[u.name] = exp;
181
+ }
182
+ }
168
183
  const that = this;
169
184
  pb.func('zCalcSpriteColor', [
170
185
  pb.vec3('zWorldPos'),
@@ -1 +1 @@
1
- {"version":3,"file":"spriteblueprint.js","sources":["../../src/material/spriteblueprint.ts"],"sourcesContent":["import { DRef, Vector4 } from '@zephyr3d/base';\r\nimport { type BluePrintUniformTexture, type BluePrintUniformValue } from '../utility/blueprint/material/ir';\r\nimport { SpriteBlockNode } from '../utility/blueprint/material/pbr';\r\nimport { MaterialBlueprintIR } from '../utility/blueprint/material/ir';\r\nimport { SpriteMaterial } from './sprite';\r\nimport type { BindGroup, PBInsideFunctionScope, PBShaderExp } from '@zephyr3d/device';\r\nimport type { DrawContext } from '../render';\r\n\r\n/**\r\n * Sprite material driven by a blueprint graph.\r\n *\r\n * @remarks\r\n * This material extends {@link SpriteMaterial} and uses a\r\n * {@link MaterialBlueprintIR} fragment graph to compute the final\r\n * sprite color. All fragment shading logic is defined in the\r\n * blueprint instead of being hard-coded in the material.\r\n *\r\n * @public\r\n */\r\nexport class SpriteBlueprintMaterial extends SpriteMaterial {\r\n /** @internal */\r\n private _irFrag: MaterialBlueprintIR;\r\n /** @internal */\r\n private _uniformValues: BluePrintUniformValue[];\r\n /** @internal */\r\n private _uniformTextures: BluePrintUniformTexture[];\r\n /**\r\n * Creates a new {@link SpriteBlueprintMaterial} instance.\r\n *\r\n * @param irFrag - Optional fragment blueprint IR. If omitted, a default\r\n * IR containing a single {@link SpriteBlockNode} is created.\r\n * @param uniformValues - Optional initial list of uniform value descriptors.\r\n * @param uniformTextures - Optional initial list of texture uniform descriptors.\r\n */\r\n constructor(\r\n irFrag?: MaterialBlueprintIR,\r\n uniformValues?: BluePrintUniformValue[],\r\n uniformTextures?: BluePrintUniformTexture[]\r\n ) {\r\n super();\r\n this._irFrag =\r\n irFrag ??\r\n new MaterialBlueprintIR(\r\n {\r\n nodeMap: { '1': new SpriteBlockNode() },\r\n roots: [1],\r\n order: [1],\r\n graph: { incoming: {}, outgoing: {} }\r\n },\r\n '',\r\n {\r\n nodes: [{ id: 1, title: '', locked: true, node: { ClassName: 'SpriteBlockNode', Object: '' } }],\r\n links: []\r\n }\r\n );\r\n this._uniformValues = uniformValues ?? [];\r\n this._uniformTextures = uniformTextures ?? [];\r\n }\r\n /**\r\n * Gets the fragment blueprint IR used to generate the fragment shader.\r\n */\r\n get fragmentIR() {\r\n return this._irFrag;\r\n }\r\n set fragmentIR(ir: MaterialBlueprintIR) {\r\n if (ir && ir !== this._irFrag) {\r\n this._irFrag = ir;\r\n this.clearCache();\r\n this.optionChanged(true);\r\n }\r\n }\r\n /**\r\n * Gets the list of uniform value descriptors used by the blueprint.\r\n */\r\n get uniformValues() {\r\n return this._uniformValues;\r\n }\r\n set uniformValues(val: BluePrintUniformValue[]) {\r\n this._uniformValues = (val ?? []).map((v) => ({ ...v }));\r\n this.uniformChanged();\r\n }\r\n /**\r\n * Gets the list of texture uniform descriptors used by the blueprint.\r\n */\r\n get uniformTextures() {\r\n return this._uniformTextures;\r\n }\r\n set uniformTextures(val: BluePrintUniformTexture[]) {\r\n val = val ?? [];\r\n if (val !== this._uniformTextures) {\r\n const newUniforms = val.map((v) => ({\r\n finalTexture: new DRef(v.finalTexture!.get()),\r\n finalSampler: v.finalSampler,\r\n name: v.name,\r\n params: v.params?.clone() ?? Vector4.zero(),\r\n texture: v.texture,\r\n type: v.type,\r\n sRGB: v.sRGB,\r\n wrapS: v.wrapS,\r\n wrapT: v.wrapT,\r\n inFragmentShader: v.inFragmentShader,\r\n inVertexShader: v.inVertexShader,\r\n minFilter: v.minFilter,\r\n magFilter: v.magFilter,\r\n mipFilter: v.mipFilter\r\n }));\r\n for (const u of this._uniformTextures) {\r\n u.finalTexture!.dispose();\r\n }\r\n this._uniformTextures = newUniforms;\r\n this.uniformChanged();\r\n }\r\n }\r\n /**\r\n * Creates a deep copy of this blueprint material.\r\n *\r\n * @remarks\r\n * The clone shares the same fragment IR reference and copies the\r\n * current uniform descriptors, then calls {@link SpriteMaterial.copyFrom}\r\n * to copy base-class state.\r\n *\r\n * @returns A new {@link SpriteBlueprintMaterial} instance.\r\n */\r\n clone() {\r\n const other = new SpriteBlueprintMaterial(this._irFrag, this._uniformValues, this._uniformTextures);\r\n other.copyFrom(this);\r\n return other;\r\n }\r\n /**\r\n * Applies runtime uniform values and textures to the given bind group.\r\n *\r\n * @remarks\r\n * - Calls the base implementation to bind sprite-related uniforms first.\r\n * - If fragment color is needed for the current context, all blueprint\r\n * uniform values and textures are then bound by name:\r\n * - `uniformValues` via `bindGroup.setValue`.\r\n * - `uniformTextures` via `bindGroup.setTexture`.\r\n *\r\n * @param bindGroup - The bind group to bind material resources to.\r\n * @param ctx - The current draw context.\r\n * @param pass - Index of the active render pass.\r\n */\r\n applyUniformValues(bindGroup: BindGroup, ctx: DrawContext, pass: number) {\r\n super.applyUniformValues(bindGroup, ctx, pass);\r\n if (this.needFragmentColor(ctx)) {\r\n for (const u of this._uniformValues) {\r\n bindGroup.setValue(u.name, u.finalValue!);\r\n }\r\n for (const u of this._uniformTextures) {\r\n bindGroup.setTexture(u.name, u.finalTexture!.get()!, u.finalSampler);\r\n }\r\n }\r\n }\r\n /**\r\n * Computes the fragment color by invoking the blueprint-generated function.\r\n *\r\n * @remarks\r\n * - A helper function `zCalcSpriteColor(zWorldPos, zVertexUV)` is declared\r\n * on the shader builder using the current fragment IR.\r\n * - The blueprint IR is asked to create its node network via\r\n * {@link MaterialBlueprintIR.create}, and the output named `\"Color\"`\r\n * is used as the return value.\r\n * - The resulting function is invoked with the current world position and\r\n * UV coordinates for each fragment.\r\n *\r\n * @param scope - The current fragment shader function scope.\r\n * @returns A shader expression representing the final fragment color.\r\n */\r\n protected calcFragmentColor(scope: PBInsideFunctionScope) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n pb.func('zCalcSpriteColor', [pb.vec3('zWorldPos'), pb.vec2('zVertexUV')], function () {\r\n const outputs = that._irFrag.create(pb)!;\r\n this.$return(that.getOutput(outputs, 'Color') as PBShaderExp);\r\n });\r\n return scope.zCalcSpriteColor(scope.$inputs.zWorldPos, scope.$inputs.zVertexUV) as PBShaderExp;\r\n }\r\n /**\r\n * Creates a unique hash string used for program caching.\r\n *\r\n * @remarks\r\n * The hash includes the base {@link SpriteMaterial} hash and the\r\n * fragment IR hash, so that different blueprints will produce\r\n * different shader programs.\r\n *\r\n * @returns A hash string that identifies this material configuration.\r\n */\r\n protected _createHash() {\r\n return `${super._createHash()}:${this._irFrag.hash}`;\r\n }\r\n /**\r\n * Creates the GPU program for this material.\r\n *\r\n * @remarks\r\n * This simply delegates to the base implementation and returns its result.\r\n * Commented-out logging lines are available for debugging the generated\r\n * vertex and fragment shader sources.\r\n *\r\n * @param ctx - The current draw context.\r\n * @param pass - Index of the active material pass.\r\n * @returns The created GPU program.\r\n */\r\n protected createProgram(ctx: DrawContext, pass: number) {\r\n const program = super.createProgram(ctx, pass);\r\n //console.log(program.getShaderSource('vertex'));\r\n //console.log(program.getShaderSource('fragment'));\r\n return program;\r\n }\r\n /**\r\n * Disposes resources associated with this material.\r\n *\r\n * @remarks\r\n * - Calls the base `onDispose` to clean up inherited resources.\r\n * - Disposes all `finalTexture` references from the blueprint texture\r\n * uniform descriptors.\r\n *\r\n * This method is intended to be called by the engine's resource management\r\n * system rather than directly from user code.\r\n */\r\n protected onDispose() {\r\n super.onDispose();\r\n for (const u of this._uniformTextures) {\r\n u.finalTexture!.dispose();\r\n }\r\n }\r\n /**\r\n * Retrieves a named output expression from a blueprint output list.\r\n *\r\n * @param outputs - List of outputs generated by the blueprint graph.\r\n * @param name - Name of the output to look for (e.g. `\"Color\"`).\r\n * @returns The matching output expression, or `undefined` if not found.\r\n */\r\n private getOutput(\r\n outputs: {\r\n name: string;\r\n exp: number | boolean | PBShaderExp;\r\n }[],\r\n name: string\r\n ) {\r\n return outputs.find((output) => output.name === name)?.exp;\r\n }\r\n}\r\n"],"names":["SpriteBlueprintMaterial","SpriteMaterial","irFrag","uniformValues","uniformTextures","_irFrag","MaterialBlueprintIR","nodeMap","SpriteBlockNode","roots","order","graph","incoming","outgoing","nodes","id","title","locked","node","ClassName","Object","links","_uniformValues","_uniformTextures","fragmentIR","ir","clearCache","optionChanged","val","map","v","uniformChanged","newUniforms","finalTexture","DRef","get","finalSampler","name","params","clone","Vector4","zero","texture","type","sRGB","wrapS","wrapT","inFragmentShader","inVertexShader","minFilter","magFilter","mipFilter","u","dispose","other","copyFrom","applyUniformValues","bindGroup","ctx","pass","needFragmentColor","setValue","finalValue","setTexture","calcFragmentColor","scope","pb","$builder","that","func","vec3","vec2","outputs","create","$return","getOutput","zCalcSpriteColor","$inputs","zWorldPos","zVertexUV","_createHash","hash","createProgram","program","onDispose","find","output","exp"],"mappings":"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"}
1
+ {"version":3,"file":"spriteblueprint.js","sources":["../../src/material/spriteblueprint.ts"],"sourcesContent":["import { DRef, Vector4 } from '@zephyr3d/base';\r\nimport { type BluePrintUniformTexture, type BluePrintUniformValue } from '../utility/blueprint/material/ir';\r\nimport { SpriteBlockNode } from '../utility/blueprint/material/pbr';\r\nimport { MaterialBlueprintIR } from '../utility/blueprint/material/ir';\r\nimport { getDefaultTexture2D } from '../utility/blueprint/material/texture';\r\nimport { SpriteMaterial } from './sprite';\r\nimport type { BindGroup, PBInsideFunctionScope, PBShaderExp } from '@zephyr3d/device';\r\nimport type { DrawContext } from '../render';\r\n\r\n/**\r\n * Sprite material driven by a blueprint graph.\r\n *\r\n * @remarks\r\n * This material extends {@link SpriteMaterial} and uses a\r\n * {@link MaterialBlueprintIR} fragment graph to compute the final\r\n * sprite color. All fragment shading logic is defined in the\r\n * blueprint instead of being hard-coded in the material.\r\n *\r\n * @public\r\n */\r\nexport class SpriteBlueprintMaterial extends SpriteMaterial {\r\n /** @internal */\r\n private _irFrag: MaterialBlueprintIR;\r\n /** @internal */\r\n private _uniformValues: BluePrintUniformValue[];\r\n /** @internal */\r\n private _uniformTextures: BluePrintUniformTexture[];\r\n /**\r\n * Creates a new {@link SpriteBlueprintMaterial} instance.\r\n *\r\n * @param irFrag - Optional fragment blueprint IR. If omitted, a default\r\n * IR containing a single {@link SpriteBlockNode} is created.\r\n * @param uniformValues - Optional initial list of uniform value descriptors.\r\n * @param uniformTextures - Optional initial list of texture uniform descriptors.\r\n */\r\n constructor(\r\n irFrag?: MaterialBlueprintIR,\r\n uniformValues?: BluePrintUniformValue[],\r\n uniformTextures?: BluePrintUniformTexture[]\r\n ) {\r\n super();\r\n this._irFrag =\r\n irFrag ??\r\n new MaterialBlueprintIR(\r\n {\r\n nodeMap: { '1': new SpriteBlockNode() },\r\n roots: [1],\r\n order: [1],\r\n graph: { incoming: {}, outgoing: {} }\r\n },\r\n '',\r\n {\r\n nodes: [{ id: 1, title: '', locked: true, node: { ClassName: 'SpriteBlockNode', Object: '' } }],\r\n links: []\r\n }\r\n );\r\n this._uniformValues = uniformValues ?? [];\r\n this._uniformTextures = uniformTextures ?? [];\r\n }\r\n /**\r\n * Gets the fragment blueprint IR used to generate the fragment shader.\r\n */\r\n get fragmentIR() {\r\n return this._irFrag;\r\n }\r\n set fragmentIR(ir: MaterialBlueprintIR) {\r\n if (ir && ir !== this._irFrag) {\r\n this._irFrag = ir;\r\n this.clearCache();\r\n this.optionChanged(true);\r\n }\r\n }\r\n /**\r\n * Gets the list of uniform value descriptors used by the blueprint.\r\n */\r\n get uniformValues() {\r\n return this._uniformValues;\r\n }\r\n set uniformValues(val: BluePrintUniformValue[]) {\r\n this._uniformValues = (val ?? []).map((v) => ({ ...v }));\r\n this.uniformChanged();\r\n }\r\n /**\r\n * Gets the list of texture uniform descriptors used by the blueprint.\r\n */\r\n get uniformTextures() {\r\n return this._uniformTextures;\r\n }\r\n set uniformTextures(val: BluePrintUniformTexture[]) {\r\n val = val ?? [];\r\n if (val !== this._uniformTextures) {\r\n const newUniforms = val.map((v) => ({\r\n exposed: v.exposed ?? true,\r\n finalTexture: new DRef(v.finalTexture!.get()),\r\n finalSampler: v.finalSampler,\r\n name: v.name,\r\n params: v.params?.clone() ?? Vector4.zero(),\r\n texture: v.texture,\r\n type: v.type,\r\n sRGB: v.sRGB,\r\n wrapS: v.wrapS,\r\n wrapT: v.wrapT,\r\n inFragmentShader: v.inFragmentShader,\r\n inVertexShader: v.inVertexShader,\r\n minFilter: v.minFilter,\r\n magFilter: v.magFilter,\r\n mipFilter: v.mipFilter\r\n }));\r\n for (const u of this._uniformTextures) {\r\n u.finalTexture!.dispose();\r\n }\r\n this._uniformTextures = newUniforms;\r\n this.uniformChanged();\r\n }\r\n }\r\n /**\r\n * Creates a deep copy of this blueprint material.\r\n *\r\n * @remarks\r\n * The clone shares the same fragment IR reference and copies the\r\n * current uniform descriptors, then calls {@link SpriteMaterial.copyFrom}\r\n * to copy base-class state.\r\n *\r\n * @returns A new {@link SpriteBlueprintMaterial} instance.\r\n */\r\n clone() {\r\n const other = new SpriteBlueprintMaterial(this._irFrag, this._uniformValues, this._uniformTextures);\r\n other.copyFrom(this);\r\n return other;\r\n }\r\n /**\r\n * Applies runtime uniform values and textures to the given bind group.\r\n *\r\n * @remarks\r\n * - Calls the base implementation to bind sprite-related uniforms first.\r\n * - If fragment color is needed for the current context, all blueprint\r\n * uniform values and textures are then bound by name:\r\n * - `uniformValues` via `bindGroup.setValue`.\r\n * - `uniformTextures` via `bindGroup.setTexture`.\r\n *\r\n * @param bindGroup - The bind group to bind material resources to.\r\n * @param ctx - The current draw context.\r\n * @param pass - Index of the active render pass.\r\n */\r\n applyUniformValues(bindGroup: BindGroup, ctx: DrawContext, pass: number) {\r\n super.applyUniformValues(bindGroup, ctx, pass);\r\n if (this.needFragmentColor(ctx)) {\r\n for (const u of this._uniformValues) {\r\n bindGroup.setValue(u.name, u.finalValue!);\r\n }\r\n for (const u of this._uniformTextures) {\r\n bindGroup.setTexture(u.name, u.finalTexture?.get() ?? getDefaultTexture2D(), u.finalSampler);\r\n }\r\n }\r\n }\r\n /**\r\n * Computes the fragment color by invoking the blueprint-generated function.\r\n *\r\n * @remarks\r\n * - A helper function `zCalcSpriteColor(zWorldPos, zVertexUV)` is declared\r\n * on the shader builder using the current fragment IR.\r\n * - The blueprint IR is asked to create its node network via\r\n * {@link MaterialBlueprintIR.create}, and the output named `\"Color\"`\r\n * is used as the return value.\r\n * - The resulting function is invoked with the current world position and\r\n * UV coordinates for each fragment.\r\n *\r\n * @param scope - The current fragment shader function scope.\r\n * @returns A shader expression representing the final fragment color.\r\n */\r\n protected calcFragmentColor(scope: PBInsideFunctionScope) {\r\n const pb = scope.$builder;\r\n for (const u of this._uniformTextures) {\r\n if (!pb.getGlobalScope()[u.name]) {\r\n // @ts-ignore dynamic shader type constructor\r\n const exp = (pb[u.type]() as PBShaderExp).uniform(2).withSampler({\r\n addressU: u.wrapS as any,\r\n addressV: u.wrapT as any,\r\n minFilter: u.minFilter as any,\r\n magFilter: u.magFilter as any,\r\n mipFilter: u.mipFilter as any\r\n });\r\n pb.getGlobalScope()[u.name] = exp;\r\n }\r\n }\r\n const that = this;\r\n pb.func('zCalcSpriteColor', [pb.vec3('zWorldPos'), pb.vec2('zVertexUV')], function () {\r\n const outputs = that._irFrag.create(pb)!;\r\n this.$return(that.getOutput(outputs, 'Color') as PBShaderExp);\r\n });\r\n return scope.zCalcSpriteColor(scope.$inputs.zWorldPos, scope.$inputs.zVertexUV) as PBShaderExp;\r\n }\r\n /**\r\n * Creates a unique hash string used for program caching.\r\n *\r\n * @remarks\r\n * The hash includes the base {@link SpriteMaterial} hash and the\r\n * fragment IR hash, so that different blueprints will produce\r\n * different shader programs.\r\n *\r\n * @returns A hash string that identifies this material configuration.\r\n */\r\n protected _createHash() {\r\n return `${super._createHash()}:${this._irFrag.hash}`;\r\n }\r\n /**\r\n * Creates the GPU program for this material.\r\n *\r\n * @remarks\r\n * This simply delegates to the base implementation and returns its result.\r\n * Commented-out logging lines are available for debugging the generated\r\n * vertex and fragment shader sources.\r\n *\r\n * @param ctx - The current draw context.\r\n * @param pass - Index of the active material pass.\r\n * @returns The created GPU program.\r\n */\r\n protected createProgram(ctx: DrawContext, pass: number) {\r\n const program = super.createProgram(ctx, pass);\r\n //console.log(program.getShaderSource('vertex'));\r\n //console.log(program.getShaderSource('fragment'));\r\n return program;\r\n }\r\n /**\r\n * Disposes resources associated with this material.\r\n *\r\n * @remarks\r\n * - Calls the base `onDispose` to clean up inherited resources.\r\n * - Disposes all `finalTexture` references from the blueprint texture\r\n * uniform descriptors.\r\n *\r\n * This method is intended to be called by the engine's resource management\r\n * system rather than directly from user code.\r\n */\r\n protected onDispose() {\r\n super.onDispose();\r\n for (const u of this._uniformTextures) {\r\n u.finalTexture!.dispose();\r\n }\r\n }\r\n /**\r\n * Retrieves a named output expression from a blueprint output list.\r\n *\r\n * @param outputs - List of outputs generated by the blueprint graph.\r\n * @param name - Name of the output to look for (e.g. `\"Color\"`).\r\n * @returns The matching output expression, or `undefined` if not found.\r\n */\r\n private getOutput(\r\n outputs: {\r\n name: string;\r\n exp: number | boolean | PBShaderExp;\r\n }[],\r\n name: string\r\n ) {\r\n return outputs.find((output) => output.name === name)?.exp;\r\n }\r\n}\r\n"],"names":["SpriteBlueprintMaterial","SpriteMaterial","irFrag","uniformValues","uniformTextures","_irFrag","MaterialBlueprintIR","nodeMap","SpriteBlockNode","roots","order","graph","incoming","outgoing","nodes","id","title","locked","node","ClassName","Object","links","_uniformValues","_uniformTextures","fragmentIR","ir","clearCache","optionChanged","val","map","v","uniformChanged","newUniforms","exposed","finalTexture","DRef","get","finalSampler","name","params","clone","Vector4","zero","texture","type","sRGB","wrapS","wrapT","inFragmentShader","inVertexShader","minFilter","magFilter","mipFilter","u","dispose","other","copyFrom","applyUniformValues","bindGroup","ctx","pass","needFragmentColor","setValue","finalValue","setTexture","getDefaultTexture2D","calcFragmentColor","scope","pb","$builder","getGlobalScope","exp","uniform","withSampler","addressU","addressV","that","func","vec3","vec2","outputs","create","$return","getOutput","zCalcSpriteColor","$inputs","zWorldPos","zVertexUV","_createHash","hash","createProgram","program","onDispose","find","output"],"mappings":"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"}
@@ -45,7 +45,9 @@ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
45
45
  ],
46
46
  extinctionScale: 1.24,
47
47
  normalScale: 1.18,
48
- scatteringDistribution: 0.56
48
+ scatteringDistribution: 0.56,
49
+ specularDetailSoftness: 0.66,
50
+ specularDetailRadius: 1.35
49
51
  },
50
52
  skin_default: {
51
53
  meanFreePathColor: [
@@ -70,7 +72,9 @@ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
70
72
  ],
71
73
  extinctionScale: 1.06,
72
74
  normalScale: 1,
73
- scatteringDistribution: 0.6
75
+ scatteringDistribution: 0.6,
76
+ specularDetailSoftness: 0.78,
77
+ specularDetailRadius: 1.8
74
78
  },
75
79
  skin_heavy_makeup: {
76
80
  meanFreePathColor: [
@@ -95,7 +99,9 @@ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
95
99
  ],
96
100
  extinctionScale: 1.4,
97
101
  normalScale: 1.26,
98
- scatteringDistribution: 0.5
102
+ scatteringDistribution: 0.5,
103
+ specularDetailSoftness: 0.86,
104
+ specularDetailRadius: 2.1
99
105
  },
100
106
  wax_backlit: {
101
107
  meanFreePathColor: [
@@ -120,7 +126,9 @@ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
120
126
  ],
121
127
  extinctionScale: 0.78,
122
128
  normalScale: 0.92,
123
- scatteringDistribution: 0.82
129
+ scatteringDistribution: 0.82,
130
+ specularDetailSoftness: 0.88,
131
+ specularDetailRadius: 2.35
124
132
  },
125
133
  wax_soft: {
126
134
  meanFreePathColor: [
@@ -145,7 +153,9 @@ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
145
153
  ],
146
154
  extinctionScale: 0.86,
147
155
  normalScale: 0.98,
148
- scatteringDistribution: 0.74
156
+ scatteringDistribution: 0.74,
157
+ specularDetailSoftness: 0.94,
158
+ specularDetailRadius: 2.65
149
159
  },
150
160
  jade_backlit: {
151
161
  meanFreePathColor: [
@@ -170,7 +180,9 @@ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
170
180
  ],
171
181
  extinctionScale: 0.92,
172
182
  normalScale: 1.02,
173
- scatteringDistribution: 0.7
183
+ scatteringDistribution: 0.7,
184
+ specularDetailSoftness: 0.42,
185
+ specularDetailRadius: 1.2
174
186
  },
175
187
  jade_soft: {
176
188
  meanFreePathColor: [
@@ -195,7 +207,9 @@ const SUBSURFACE_PROFILE_PRESET_TEMPLATE = {
195
207
  ],
196
208
  extinctionScale: 1,
197
209
  normalScale: 1.04,
198
- scatteringDistribution: 0.66
210
+ scatteringDistribution: 0.66,
211
+ specularDetailSoftness: 0.5,
212
+ specularDetailRadius: 1.4
199
213
  }
200
214
  };
201
215
  const SUBSURFACE_PROFILE_PRESET_TINT_BIAS = {
@@ -306,8 +320,11 @@ const SUBSURFACE_PROFILE_PRESET_RESPONSE = {
306
320
  _extinctionScale;
307
321
  _normalScale;
308
322
  _scatteringDistribution;
323
+ _specularDetailSoftness;
324
+ _specularDetailRadius;
309
325
  _slot;
310
326
  _changeListeners;
327
+ _disposed;
311
328
  /**
312
329
  * Creates a subsurface scattering profile initialized with the default skin preset.
313
330
  *
@@ -326,19 +343,43 @@ const SUBSURFACE_PROFILE_PRESET_RESPONSE = {
326
343
  this._extinctionScale = 1;
327
344
  this._normalScale = 1;
328
345
  this._scatteringDistribution = 0.65;
346
+ this._specularDetailSoftness = 0.78;
347
+ this._specularDetailRadius = 1.8;
329
348
  this._changeListeners = new Set();
349
+ this._disposed = false;
330
350
  this._slot = SubsurfaceProfile.allocateSlot(this);
331
351
  this.applyPresetTemplate(this._preset, false);
332
352
  }
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() {
353
+ clone() {
354
+ const other = new SubsurfaceProfile();
355
+ other.copyFrom(this);
356
+ return other;
357
+ }
358
+ copyFrom(other) {
359
+ this.preset = other.preset;
360
+ this.meanFreePathColor = other.meanFreePathColor;
361
+ this.meanFreePathDistance = other.meanFreePathDistance;
362
+ this.strength = other.strength;
363
+ this.scale = other.scale;
364
+ this.worldUnitScale = other.worldUnitScale;
365
+ this.boundaryColorBleed = other.boundaryColorBleed;
366
+ this.transmissionTintColor = other.transmissionTintColor;
367
+ this.extinctionScale = other.extinctionScale;
368
+ this.normalScale = other.normalScale;
369
+ this.scatteringDistribution = other.scatteringDistribution;
370
+ this.specularDetailSoftness = other.specularDetailSoftness;
371
+ this.specularDetailRadius = other.specularDetailRadius;
372
+ this.falloffColor = other.falloffColor;
373
+ }
374
+ dispose() {
375
+ if (this._disposed) {
376
+ return;
377
+ }
378
+ this._disposed = true;
379
+ this._changeListeners.clear();
380
+ SubsurfaceProfile.releaseSlot(this._slot, this);
381
+ }
382
+ static get version() {
342
383
  return this._version;
343
384
  }
344
385
  /**
@@ -658,13 +699,27 @@ const SUBSURFACE_PROFILE_PRESET_RESPONSE = {
658
699
  this.markDirty();
659
700
  }
660
701
  }
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) {
702
+ /** Strength of the screen-space filter applied to normal-driven specular detail. */ get specularDetailSoftness() {
703
+ return this._specularDetailSoftness;
704
+ }
705
+ set specularDetailSoftness(val) {
706
+ const next = this.clamp01(val ?? 0);
707
+ if (next !== this._specularDetailSoftness) {
708
+ this._specularDetailSoftness = next;
709
+ this.markDirty();
710
+ }
711
+ }
712
+ /** Radius in screen pixels used to soften normal-driven specular detail. */ get specularDetailRadius() {
713
+ return this._specularDetailRadius;
714
+ }
715
+ set specularDetailRadius(val) {
716
+ const next = this.clampRange(val ?? 0, 0, 4);
717
+ if (next !== this._specularDetailRadius) {
718
+ this._specularDetailRadius = next;
719
+ this.markDirty();
720
+ }
721
+ }
722
+ addChangeListener(listener) {
668
723
  this._changeListeners.add(listener);
669
724
  }
670
725
  /**
@@ -686,6 +741,12 @@ const SUBSURFACE_PROFILE_PRESET_RESPONSE = {
686
741
  }
687
742
  throw new Error('SubsurfaceProfile limit exceeded');
688
743
  }
744
+ static releaseSlot(slot, profile) {
745
+ if (slot > 0 && slot < this._profiles.length && this._profiles[slot] === profile) {
746
+ this._profiles[slot] = null;
747
+ this._version++;
748
+ }
749
+ }
689
750
  markDirty() {
690
751
  SubsurfaceProfile._version++;
691
752
  this._changeListeners.forEach((listener)=>listener());
@@ -713,6 +774,8 @@ const SUBSURFACE_PROFILE_PRESET_RESPONSE = {
713
774
  this._extinctionScale = template.extinctionScale;
714
775
  this._normalScale = template.normalScale;
715
776
  this._scatteringDistribution = template.scatteringDistribution;
777
+ this._specularDetailSoftness = template.specularDetailSoftness;
778
+ this._specularDetailRadius = template.specularDetailRadius;
716
779
  this.syncScatterRadiusFromMeanFreePath(false);
717
780
  if (markDirty) {
718
781
  this.markDirty();
@@ -1 +1 @@
1
- {"version":3,"file":"subsurfaceprofile.js","sources":["../../src/material/subsurfaceprofile.ts"],"sourcesContent":["import { Vector3, type Immutable } from '@zephyr3d/base';\r\n\r\n/**\r\n * Built-in subsurface scattering profile preset names.\r\n *\r\n * @remarks\r\n * The short aliases (`skin`, `wax`, and `jade`) resolve to their default\r\n * canonical profiles.\r\n *\r\n * @public\r\n */\r\nexport type SubsurfaceProfilePreset =\r\n | 'skin'\r\n | 'skin_thin'\r\n | 'skin_default'\r\n | 'skin_heavy_makeup'\r\n | 'wax'\r\n | 'wax_backlit'\r\n | 'wax_soft'\r\n | 'jade'\r\n | 'jade_backlit'\r\n | 'jade_soft';\r\n\r\ntype CanonicalSubsurfaceProfilePreset =\r\n | 'skin_thin'\r\n | 'skin_default'\r\n | 'skin_heavy_makeup'\r\n | 'wax_backlit'\r\n | 'wax_soft'\r\n | 'jade_backlit'\r\n | 'jade_soft';\r\n\r\ntype SubsurfaceProfilePresetTemplate = {\r\n meanFreePathColor: [number, number, number];\r\n meanFreePathDistance: number;\r\n falloffColor: [number, number, number];\r\n strength: number;\r\n scale: number;\r\n worldUnitScale: number;\r\n boundaryColorBleed: number;\r\n transmissionTintColor: [number, number, number];\r\n extinctionScale: number;\r\n normalScale: number;\r\n scatteringDistribution: number;\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_ALIAS: Record<SubsurfaceProfilePreset, CanonicalSubsurfaceProfilePreset> = {\r\n skin: 'skin_default',\r\n skin_thin: 'skin_thin',\r\n skin_default: 'skin_default',\r\n skin_heavy_makeup: 'skin_heavy_makeup',\r\n wax: 'wax_backlit',\r\n wax_backlit: 'wax_backlit',\r\n wax_soft: 'wax_soft',\r\n jade: 'jade_soft',\r\n jade_backlit: 'jade_backlit',\r\n jade_soft: 'jade_soft'\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_INDEX: Record<CanonicalSubsurfaceProfilePreset, number> = {\r\n skin_thin: 0,\r\n skin_default: 1,\r\n skin_heavy_makeup: 2,\r\n wax_backlit: 3,\r\n wax_soft: 4,\r\n jade_backlit: 5,\r\n jade_soft: 6\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_TEMPLATE: Record<\r\n CanonicalSubsurfaceProfilePreset,\r\n SubsurfaceProfilePresetTemplate\r\n> = {\r\n skin_thin: {\r\n meanFreePathColor: [1.0, 0.37, 0.11],\r\n meanFreePathDistance: 0.7,\r\n falloffColor: [1.0, 0.32, 0.2],\r\n strength: 0.68,\r\n scale: 0.82,\r\n worldUnitScale: 0.88,\r\n boundaryColorBleed: 0.13,\r\n transmissionTintColor: [1, 0.37, 0.28],\r\n extinctionScale: 1.24,\r\n normalScale: 1.18,\r\n scatteringDistribution: 0.56\r\n },\r\n skin_default: {\r\n meanFreePathColor: [1.0, 0.45, 0.17],\r\n meanFreePathDistance: 0.92,\r\n falloffColor: [1.0, 0.39, 0.25],\r\n strength: 0.82,\r\n scale: 0.96,\r\n worldUnitScale: 1,\r\n boundaryColorBleed: 0.22,\r\n transmissionTintColor: [1, 0.46, 0.34],\r\n extinctionScale: 1.06,\r\n normalScale: 1,\r\n scatteringDistribution: 0.6\r\n },\r\n skin_heavy_makeup: {\r\n meanFreePathColor: [1.0, 0.33, 0.11],\r\n meanFreePathDistance: 0.68,\r\n falloffColor: [1.0, 0.26, 0.16],\r\n strength: 0.56,\r\n scale: 0.76,\r\n worldUnitScale: 0.84,\r\n boundaryColorBleed: 0.08,\r\n transmissionTintColor: [0.94, 0.31, 0.22],\r\n extinctionScale: 1.4,\r\n normalScale: 1.26,\r\n scatteringDistribution: 0.5\r\n },\r\n wax_backlit: {\r\n meanFreePathColor: [1.0, 0.68, 0.36],\r\n meanFreePathDistance: 1.54,\r\n falloffColor: [1.0, 0.8, 0.66],\r\n strength: 1.12,\r\n scale: 1.42,\r\n worldUnitScale: 1.26,\r\n boundaryColorBleed: 0.42,\r\n transmissionTintColor: [1, 0.82, 0.7],\r\n extinctionScale: 0.78,\r\n normalScale: 0.92,\r\n scatteringDistribution: 0.82\r\n },\r\n wax_soft: {\r\n meanFreePathColor: [1.0, 0.72, 0.38],\r\n meanFreePathDistance: 1.2,\r\n falloffColor: [1.0, 0.86, 0.74],\r\n strength: 1.02,\r\n scale: 1.28,\r\n worldUnitScale: 1.12,\r\n boundaryColorBleed: 0.36,\r\n transmissionTintColor: [1, 0.86, 0.74],\r\n extinctionScale: 0.86,\r\n normalScale: 0.98,\r\n scatteringDistribution: 0.74\r\n },\r\n jade_backlit: {\r\n meanFreePathColor: [0.74, 1.0, 0.88],\r\n meanFreePathDistance: 0.92,\r\n falloffColor: [0.66, 0.94, 0.88],\r\n strength: 0.92,\r\n scale: 1.14,\r\n worldUnitScale: 1.06,\r\n boundaryColorBleed: 0.26,\r\n transmissionTintColor: [0.68, 0.92, 0.86],\r\n extinctionScale: 0.92,\r\n normalScale: 1.02,\r\n scatteringDistribution: 0.7\r\n },\r\n jade_soft: {\r\n meanFreePathColor: [0.68, 1.0, 0.84],\r\n meanFreePathDistance: 0.8,\r\n falloffColor: [0.72, 0.94, 0.86],\r\n strength: 0.82,\r\n scale: 1.02,\r\n worldUnitScale: 0.98,\r\n boundaryColorBleed: 0.22,\r\n transmissionTintColor: [0.74, 0.96, 0.9],\r\n extinctionScale: 1,\r\n normalScale: 1.04,\r\n scatteringDistribution: 0.66\r\n }\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_TINT_BIAS: Record<\r\n CanonicalSubsurfaceProfilePreset,\r\n [number, number, number]\r\n> = {\r\n skin_thin: [1, 0.56, 0.46],\r\n skin_default: [1, 0.62, 0.5],\r\n skin_heavy_makeup: [1, 0.5, 0.42],\r\n wax_backlit: [1, 0.8, 0.7],\r\n wax_soft: [1, 0.86, 0.78],\r\n jade_backlit: [0.72, 0.92, 0.96],\r\n jade_soft: [0.68, 0.96, 0.88]\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_RESPONSE: Record<\r\n CanonicalSubsurfaceProfilePreset,\r\n [number, number, number, number]\r\n> = {\r\n skin_thin: [0.08, 0.12, 0.06, 0.12],\r\n skin_default: [0.1, 0.14, 0.08, 0.16],\r\n skin_heavy_makeup: [0.02, 0.05, -0.02, 0.01],\r\n wax_backlit: [0.12, 0.2, 0.26, 0.24],\r\n wax_soft: [0.2, 0.3, 0.34, 0.1],\r\n jade_backlit: [0.08, 0.18, 0.2, 0.24],\r\n jade_soft: [0.16, 0.24, 0.22, 0.12]\r\n};\r\n\r\n/**\r\n * Serializable subsurface scattering profile.\r\n *\r\n * @remarks\r\n * The profile stores the channel-dependent scattering radius and falloff used\r\n * by the screen-space SSS post effect. Materials can share a profile instance\r\n * to emulate Unreal-style skin profile assets.\r\n *\r\n * @public\r\n */\r\nexport class SubsurfaceProfile {\r\n private static readonly _maxProfiles = 255;\r\n private static readonly _profiles: Array<SubsurfaceProfile | null> = new Array(\r\n SubsurfaceProfile._maxProfiles + 1\r\n ).fill(null);\r\n private static _version = 0;\r\n private static _defaultSkinProfile: SubsurfaceProfile | null = null;\r\n private readonly _scatterRadius: Vector3;\r\n private readonly _falloffColor: Vector3;\r\n private readonly _meanFreePathColor: Vector3;\r\n private readonly _transmissionTintColor: Vector3;\r\n private _preset: CanonicalSubsurfaceProfilePreset;\r\n private _meanFreePathDistance: number;\r\n private _strength: number;\r\n private _scale: number;\r\n private _worldUnitScale: number;\r\n private _boundaryColorBleed: number;\r\n private _extinctionScale: number;\r\n private _normalScale: number;\r\n private _scatteringDistribution: number;\r\n private readonly _slot: number;\r\n private readonly _changeListeners: Set<() => void>;\r\n\r\n /**\r\n * Creates a subsurface scattering profile initialized with the default skin preset.\r\n *\r\n * @public\r\n */\r\n constructor() {\r\n this._scatterRadius = new Vector3(0, 0, 0);\r\n this._falloffColor = new Vector3(0, 0, 0);\r\n this._meanFreePathColor = new Vector3(0, 0, 0);\r\n this._transmissionTintColor = new Vector3(0, 0, 0);\r\n this._preset = 'skin_default';\r\n this._meanFreePathDistance = 0;\r\n this._strength = 0;\r\n this._scale = 0;\r\n this._worldUnitScale = 1;\r\n this._boundaryColorBleed = 0;\r\n this._extinctionScale = 1;\r\n this._normalScale = 1;\r\n this._scatteringDistribution = 0.65;\r\n this._changeListeners = new Set();\r\n this._slot = SubsurfaceProfile.allocateSlot(this);\r\n this.applyPresetTemplate(this._preset, false);\r\n }\r\n\r\n /**\r\n * Gets the global profile data version.\r\n *\r\n * @remarks\r\n * The value is incremented whenever a profile slot is allocated or profile\r\n * data changes, allowing render systems to refresh cached profile textures.\r\n *\r\n * @public\r\n */\r\n static get version() {\r\n return this._version;\r\n }\r\n\r\n /**\r\n * Gets the profile assigned to a packed profile slot.\r\n *\r\n * @param slot - The 1-based profile slot index.\r\n * @returns The profile assigned to the slot, or `null` if the slot is invalid or unused.\r\n *\r\n * @public\r\n */\r\n static getProfileBySlot(slot: number) {\r\n return slot > 0 && slot < this._profiles.length ? this._profiles[slot] : null;\r\n }\r\n\r\n /**\r\n * Gets the shared default skin subsurface profile.\r\n *\r\n * @returns The lazily-created default skin profile.\r\n *\r\n * @public\r\n */\r\n static getDefaultSkinProfile() {\r\n if (!this._defaultSkinProfile) {\r\n this._defaultSkinProfile = new SubsurfaceProfile();\r\n }\r\n return this._defaultSkinProfile;\r\n }\r\n\r\n /**\r\n * Gets the preset tint bias used by the screen-space transmission model.\r\n *\r\n * @param index - The packed canonical preset index.\r\n * @returns The RGB tint bias for the preset, or white when the index is unknown.\r\n *\r\n * @public\r\n */\r\n static getPresetTintBiasByIndex(index: number) {\r\n return SUBSURFACE_PROFILE_PRESET_TINT_BIAS[this.getPresetNameByIndex(index)] ?? [1, 1, 1];\r\n }\r\n\r\n /**\r\n * Gets the preset transmission response used by the screen-space SSS pass.\r\n *\r\n * @param index - The packed canonical preset index.\r\n * @returns The four-component transmission response for the preset.\r\n *\r\n * @public\r\n */\r\n static getPresetResponseByIndex(index: number) {\r\n return SUBSURFACE_PROFILE_PRESET_RESPONSE[this.getPresetNameByIndex(index)] ?? [0, 0, 0, 0];\r\n }\r\n\r\n /**\r\n * Computes the effective tint bias from the preset and current profile settings.\r\n *\r\n * @returns The derived RGB tint bias used for transmission tinting.\r\n *\r\n * @public\r\n */\r\n getDerivedTintBias(): [number, number, number] {\r\n const base = SUBSURFACE_PROFILE_PRESET_TINT_BIAS[this._preset] ?? [1, 1, 1];\r\n const factors = this.getDerivedProfileFactors();\r\n const derived: [number, number, number] = [\r\n this.clamp01(0.78 + factors.warmBias * 0.26 - factors.coolBias * 0.16 + factors.boundaryNorm * 0.04),\r\n this.clamp01(\r\n 0.3 +\r\n factors.meanFreePathColor[1] * 0.24 +\r\n factors.transmissionTintColor[1] * 0.28 +\r\n factors.distanceNorm * 0.08 +\r\n factors.scaleNorm * 0.05 +\r\n factors.boundaryNorm * 0.08 +\r\n factors.coolBias * 0.06\r\n ),\r\n this.clamp01(\r\n 0.14 +\r\n factors.meanFreePathColor[2] * 0.22 +\r\n factors.transmissionTintColor[2] * 0.32 +\r\n factors.distanceNorm * 0.06 +\r\n factors.boundaryNorm * 0.06 +\r\n factors.coolBias * 0.12 -\r\n factors.warmBias * 0.06\r\n )\r\n ];\r\n const blend = this.clampRange(\r\n 0.26 + factors.radiusNorm * 0.16 + factors.scaleNorm * 0.1 + factors.strengthNorm * 0.08,\r\n 0.25,\r\n 0.88\r\n );\r\n return [\r\n this.mixNumber(base[0], derived[0], blend),\r\n this.mixNumber(base[1], derived[1], blend),\r\n this.mixNumber(base[2], derived[2], blend)\r\n ];\r\n }\r\n\r\n /**\r\n * Computes the effective transmission response from the preset and current profile settings.\r\n *\r\n * @returns The derived transmission response packed as four scalar channels.\r\n *\r\n * @public\r\n */\r\n getDerivedTransmissionResponse(): [number, number, number, number] {\r\n const base = SUBSURFACE_PROFILE_PRESET_RESPONSE[this._preset] ?? [0, 0, 0, 0];\r\n const factors = this.getDerivedProfileFactors();\r\n const blend = this.clampRange(\r\n 0.32 +\r\n factors.distanceNorm * 0.18 +\r\n factors.scaleNorm * 0.12 +\r\n factors.strengthNorm * 0.1 +\r\n factors.boundaryNorm * 0.06,\r\n 0.28,\r\n 0.9\r\n );\r\n const derived: [number, number, number, number] = [\r\n this.clampRange(\r\n -0.06 +\r\n factors.radiusNorm * 0.08 +\r\n factors.distanceNorm * 0.08 +\r\n factors.strengthNorm * 0.05 +\r\n factors.distributionNorm * 0.04 +\r\n factors.boundaryNorm * 0.05 +\r\n factors.extinctionSoftness * 0.03,\r\n -0.25,\r\n 0.45\r\n ),\r\n this.clampRange(\r\n 0.02 +\r\n factors.radiusNorm * 0.1 +\r\n factors.scaleNorm * 0.08 +\r\n factors.worldScaleNorm * 0.04 +\r\n factors.distributionNorm * 0.08 +\r\n factors.extinctionSoftness * 0.06,\r\n -0.25,\r\n 0.45\r\n ),\r\n this.clampRange(\r\n -0.08 +\r\n factors.strengthNorm * 0.12 +\r\n factors.scaleNorm * 0.08 +\r\n factors.extinctionSoftness * 0.12 +\r\n factors.boundaryNorm * 0.06 +\r\n factors.warmBias * 0.05 -\r\n factors.coolBias * 0.04,\r\n -0.25,\r\n 0.45\r\n ),\r\n this.clampRange(\r\n -0.02 +\r\n factors.radiusNorm * 0.12 +\r\n factors.scaleNorm * 0.08 +\r\n factors.strengthNorm * 0.06 +\r\n factors.boundaryNorm * 0.06 +\r\n factors.extinctionSoftness * 0.16 +\r\n factors.warmBias * 0.07 +\r\n factors.transmissionTintColor[0] * 0.04,\r\n -0.25,\r\n 0.5\r\n )\r\n ];\r\n return [\r\n this.clampRange(this.mixNumber(base[0], derived[0], blend), -0.25, 0.45),\r\n this.clampRange(this.mixNumber(base[1], derived[1], blend), -0.25, 0.45),\r\n this.clampRange(this.mixNumber(base[2], derived[2], blend), -0.25, 0.45),\r\n this.clampRange(this.mixNumber(base[3], derived[3], blend), -0.25, 0.5)\r\n ];\r\n }\r\n\r\n /**\r\n * Gets the 1-based profile slot used when encoding this profile into SSS buffers.\r\n *\r\n * @public\r\n */\r\n get slot() {\r\n return this._slot;\r\n }\r\n\r\n /**\r\n * Gets or sets the RGB scatter radius.\r\n *\r\n * @remarks\r\n * Assigning a radius also updates the mean-free-path authoring controls.\r\n *\r\n * @public\r\n */\r\n get scatterRadius(): Immutable<Vector3> {\r\n return this._scatterRadius;\r\n }\r\n\r\n set scatterRadius(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._scatterRadius)) {\r\n this._scatterRadius.set(val);\r\n this.syncMeanFreePathFromScatterRadius();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the channel falloff color used by the diffusion kernel.\r\n *\r\n * @public\r\n */\r\n get falloffColor(): Immutable<Vector3> {\r\n return this._falloffColor;\r\n }\r\n\r\n set falloffColor(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._falloffColor)) {\r\n this._falloffColor.set(val);\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Mean free path color used to derive channel-dependent scatter radius.\r\n *\r\n * @remarks\r\n * This is a more UE-like authoring control that keeps the existing radius-\r\n * based implementation, while letting tools expose a color + distance pair.\r\n *\r\n * @public\r\n */\r\n get meanFreePathColor(): Immutable<Vector3> {\r\n return this._meanFreePathColor;\r\n }\r\n\r\n set meanFreePathColor(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._meanFreePathColor)) {\r\n this._meanFreePathColor.set(val);\r\n this.syncScatterRadiusFromMeanFreePath();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the mean free path distance used to derive the absolute scatter radius.\r\n *\r\n * @public\r\n */\r\n get meanFreePathDistance() {\r\n return this._meanFreePathDistance;\r\n }\r\n\r\n set meanFreePathDistance(val: number) {\r\n const next = Math.max(0, val ?? 0);\r\n if (next !== this._meanFreePathDistance) {\r\n this._meanFreePathDistance = next;\r\n this.syncScatterRadiusFromMeanFreePath();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the active subsurface profile preset.\r\n *\r\n * @remarks\r\n * Assigning a preset applies its template values to the profile. Alias preset\r\n * names are resolved to their canonical preset.\r\n *\r\n * @public\r\n */\r\n get preset() {\r\n return this._preset;\r\n }\r\n\r\n set preset(val: SubsurfaceProfilePreset) {\r\n const next = SubsurfaceProfile.resolvePreset(val);\r\n if (next !== this._preset) {\r\n this._preset = next;\r\n this.applyPresetTemplate(next);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the packed canonical preset index.\r\n *\r\n * @public\r\n */\r\n get presetIndex() {\r\n return SUBSURFACE_PROFILE_PRESET_INDEX[this._preset] ?? 0;\r\n }\r\n\r\n /**\r\n * Gets or sets the SSS strength multiplier.\r\n *\r\n * @public\r\n */\r\n get strength() {\r\n return this._strength;\r\n }\r\n\r\n set strength(val: number) {\r\n if (val !== this._strength) {\r\n this._strength = val;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the screen-space scatter width scale.\r\n *\r\n * @public\r\n */\r\n get scale() {\r\n return this._scale;\r\n }\r\n\r\n set scale(val: number) {\r\n if (val !== this._scale) {\r\n this._scale = val;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the world-unit scale used when converting profile radii.\r\n *\r\n * @public\r\n */\r\n get worldUnitScale() {\r\n return this._worldUnitScale;\r\n }\r\n\r\n set worldUnitScale(val: number) {\r\n const next = Math.max(0.05, val ?? 0.05);\r\n if (next !== this._worldUnitScale) {\r\n this._worldUnitScale = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the amount of color bleeding preserved near SSS boundaries.\r\n *\r\n * @remarks\r\n * Values are clamped to the `[0, 1]` range.\r\n *\r\n * @public\r\n */\r\n get boundaryColorBleed() {\r\n return this._boundaryColorBleed;\r\n }\r\n\r\n set boundaryColorBleed(val: number) {\r\n const next = this.clamp01(val ?? 0);\r\n if (next !== this._boundaryColorBleed) {\r\n this._boundaryColorBleed = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the RGB tint applied to transmitted subsurface light.\r\n *\r\n * @public\r\n */\r\n get transmissionTintColor(): Immutable<Vector3> {\r\n return this._transmissionTintColor;\r\n }\r\n\r\n set transmissionTintColor(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._transmissionTintColor)) {\r\n this._transmissionTintColor.set(val);\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the extinction multiplier used by transmission attenuation.\r\n *\r\n * @remarks\r\n * Values are clamped to zero or greater.\r\n *\r\n * @public\r\n */\r\n get extinctionScale() {\r\n return this._extinctionScale;\r\n }\r\n\r\n set extinctionScale(val: number) {\r\n const next = Math.max(0, val ?? 0);\r\n if (next !== this._extinctionScale) {\r\n this._extinctionScale = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the normal sensitivity scale used by SSS filtering.\r\n *\r\n * @remarks\r\n * Values are clamped to zero or greater.\r\n *\r\n * @public\r\n */\r\n get normalScale() {\r\n return this._normalScale;\r\n }\r\n\r\n set normalScale(val: number) {\r\n const next = Math.max(0, val ?? 0);\r\n if (next !== this._normalScale) {\r\n this._normalScale = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the scattering distribution blend.\r\n *\r\n * @remarks\r\n * Values are clamped to the `[0, 1]` range.\r\n *\r\n * @public\r\n */\r\n get scatteringDistribution() {\r\n return this._scatteringDistribution;\r\n }\r\n\r\n set scatteringDistribution(val: number) {\r\n const next = this.clamp01(val ?? 0);\r\n if (next !== this._scatteringDistribution) {\r\n this._scatteringDistribution = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Adds a listener that is invoked whenever this profile changes.\r\n *\r\n * @param listener - The callback to invoke after profile data changes.\r\n *\r\n * @public\r\n */\r\n addChangeListener(listener: () => void) {\r\n this._changeListeners.add(listener);\r\n }\r\n\r\n /**\r\n * Removes a previously registered profile change listener.\r\n *\r\n * @param listener - The callback to remove.\r\n *\r\n * @public\r\n */\r\n removeChangeListener(listener: () => void) {\r\n this._changeListeners.delete(listener);\r\n }\r\n\r\n private static allocateSlot(profile: SubsurfaceProfile) {\r\n for (let i = 1; i < this._profiles.length; i++) {\r\n if (!this._profiles[i]) {\r\n this._profiles[i] = profile;\r\n this._version++;\r\n return i;\r\n }\r\n }\r\n throw new Error('SubsurfaceProfile limit exceeded');\r\n }\r\n\r\n private markDirty() {\r\n SubsurfaceProfile._version++;\r\n this._changeListeners.forEach((listener) => listener());\r\n }\r\n\r\n private static resolvePreset(preset: SubsurfaceProfilePreset | null | undefined) {\r\n return SUBSURFACE_PROFILE_PRESET_ALIAS[preset ?? 'skin_default'] ?? 'skin_default';\r\n }\r\n\r\n private static getPresetNameByIndex(index: number): CanonicalSubsurfaceProfilePreset {\r\n for (const [name, presetIndex] of Object.entries(SUBSURFACE_PROFILE_PRESET_INDEX) as Array<\r\n [CanonicalSubsurfaceProfilePreset, number]\r\n >) {\r\n if (presetIndex === index) {\r\n return name;\r\n }\r\n }\r\n return 'skin_default';\r\n }\r\n\r\n private applyPresetTemplate(preset: CanonicalSubsurfaceProfilePreset, markDirty = true) {\r\n const template =\r\n SUBSURFACE_PROFILE_PRESET_TEMPLATE[preset] ?? SUBSURFACE_PROFILE_PRESET_TEMPLATE.skin_default;\r\n this._meanFreePathColor.setXYZ(\r\n template.meanFreePathColor[0],\r\n template.meanFreePathColor[1],\r\n template.meanFreePathColor[2]\r\n );\r\n this._meanFreePathDistance = template.meanFreePathDistance;\r\n this._strength = template.strength;\r\n this._scale = template.scale;\r\n this._worldUnitScale = template.worldUnitScale;\r\n this._boundaryColorBleed = template.boundaryColorBleed;\r\n this._transmissionTintColor.setXYZ(\r\n template.transmissionTintColor[0],\r\n template.transmissionTintColor[1],\r\n template.transmissionTintColor[2]\r\n );\r\n this._extinctionScale = template.extinctionScale;\r\n this._normalScale = template.normalScale;\r\n this._scatteringDistribution = template.scatteringDistribution;\r\n this.syncScatterRadiusFromMeanFreePath(false);\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private syncMeanFreePathFromScatterRadius(markDirty = true) {\r\n const maxRadius = Math.max(this._scatterRadius.x, this._scatterRadius.y, this._scatterRadius.z);\r\n if (maxRadius > 1e-5) {\r\n this._meanFreePathDistance = maxRadius;\r\n this._meanFreePathColor.setXYZ(\r\n this._scatterRadius.x / maxRadius,\r\n this._scatterRadius.y / maxRadius,\r\n this._scatterRadius.z / maxRadius\r\n );\r\n } else {\r\n this._meanFreePathDistance = 0;\r\n this._meanFreePathColor.setXYZ(0, 0, 0);\r\n }\r\n this.syncFalloffFromMeanFreePath(false);\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private syncScatterRadiusFromMeanFreePath(markDirty = true) {\r\n const distance = Math.max(0, this._meanFreePathDistance);\r\n this._scatterRadius.setXYZ(\r\n Math.max(0, this._meanFreePathColor.x) * distance,\r\n Math.max(0, this._meanFreePathColor.y) * distance,\r\n Math.max(0, this._meanFreePathColor.z) * distance\r\n );\r\n this.syncFalloffFromMeanFreePath(false);\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private syncFalloffFromMeanFreePath(markDirty = true) {\r\n const base =\r\n SUBSURFACE_PROFILE_PRESET_TEMPLATE[this._preset]?.falloffColor ??\r\n SUBSURFACE_PROFILE_PRESET_TEMPLATE.skin_default.falloffColor;\r\n const factors = this.getDerivedProfileFactors();\r\n const derivedG = this.clamp01(\r\n 0.12 +\r\n factors.meanFreePathColor[1] * 0.4 +\r\n factors.transmissionTintColor[1] * 0.12 +\r\n factors.distanceNorm * 0.05 +\r\n factors.scaleNorm * 0.05 +\r\n factors.distributionNorm * 0.05 -\r\n (1 - factors.extinctionSoftness) * 0.04\r\n );\r\n const derivedB = this.clamp01(\r\n 0.04 +\r\n factors.meanFreePathColor[2] * 0.32 +\r\n factors.transmissionTintColor[2] * 0.18 +\r\n factors.distanceNorm * 0.04 +\r\n factors.boundaryNorm * 0.05 +\r\n factors.coolBias * 0.08 -\r\n factors.warmBias * 0.04\r\n );\r\n const blend = this.clampRange(\r\n 0.24 + factors.distanceNorm * 0.16 + factors.scaleNorm * 0.12 + factors.strengthNorm * 0.08,\r\n 0.22,\r\n 0.82\r\n );\r\n this._falloffColor.setXYZ(\r\n 1,\r\n this.mixNumber(base[1], derivedG, blend),\r\n this.mixNumber(base[2], derivedB, blend)\r\n );\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private getNormalizedTransmissionTintColor(): [number, number, number] {\r\n const maxChannel = Math.max(\r\n this._transmissionTintColor.x,\r\n this._transmissionTintColor.y,\r\n this._transmissionTintColor.z,\r\n 1e-5\r\n );\r\n return [\r\n Math.max(0, this._transmissionTintColor.x) / maxChannel,\r\n Math.max(0, this._transmissionTintColor.y) / maxChannel,\r\n Math.max(0, this._transmissionTintColor.z) / maxChannel\r\n ];\r\n }\r\n\r\n private getDerivedProfileFactors() {\r\n const meanFreePathColor = this.getNormalizedMeanFreePathColor();\r\n const transmissionTintColor = this.getNormalizedTransmissionTintColor();\r\n const maxRadius = Math.max(this._scatterRadius.x, this._scatterRadius.y, this._scatterRadius.z);\r\n const radiusNorm = this.clampRange(maxRadius / 1.35, 0, 1.5);\r\n const distanceNorm = this.clampRange(this._meanFreePathDistance / 1.25, 0, 1.5);\r\n const scaleNorm = this.clampRange(this._scale / 1.35, 0, 1.5);\r\n const strengthNorm = this.clampRange(this._strength / 1.2, 0, 1.5);\r\n const worldScaleNorm = this.clampRange(this._worldUnitScale / 1.25, 0, 1.5);\r\n const boundaryNorm = this.clamp01(this._boundaryColorBleed);\r\n const distributionNorm = this.clamp01(this._scatteringDistribution);\r\n const extinctionWeight = this.clampRange(1 / Math.max(this._extinctionScale, 0.35), 0.25, 1.35);\r\n const extinctionSoftness = this.clamp01((extinctionWeight - 0.25) / 1.1);\r\n const warmBias = this.clamp01(\r\n 0.5 +\r\n (meanFreePathColor[0] - Math.max(meanFreePathColor[1], meanFreePathColor[2]) * 0.72) * 0.95 +\r\n (transmissionTintColor[0] - Math.max(transmissionTintColor[1], transmissionTintColor[2]) * 0.78) * 0.7\r\n );\r\n const coolBias = this.clamp01(\r\n 0.32 +\r\n (transmissionTintColor[2] - transmissionTintColor[0] * 0.55) * 0.55 +\r\n (meanFreePathColor[2] - meanFreePathColor[0] * 0.65) * 0.45\r\n );\r\n return {\r\n meanFreePathColor,\r\n transmissionTintColor,\r\n radiusNorm,\r\n distanceNorm,\r\n scaleNorm,\r\n strengthNorm,\r\n worldScaleNorm,\r\n boundaryNorm,\r\n distributionNorm,\r\n extinctionSoftness,\r\n warmBias,\r\n coolBias\r\n };\r\n }\r\n\r\n private getNormalizedMeanFreePathColor(): [number, number, number] {\r\n const maxChannel = Math.max(\r\n this._meanFreePathColor.x,\r\n this._meanFreePathColor.y,\r\n this._meanFreePathColor.z,\r\n 1e-5\r\n );\r\n return [\r\n Math.max(0, this._meanFreePathColor.x) / maxChannel,\r\n Math.max(0, this._meanFreePathColor.y) / maxChannel,\r\n Math.max(0, this._meanFreePathColor.z) / maxChannel\r\n ];\r\n }\r\n\r\n private mixNumber(a: number, b: number, t: number) {\r\n return a * (1 - t) + b * t;\r\n }\r\n\r\n private clampRange(value: number, minValue: number, maxValue: number) {\r\n return Math.max(minValue, Math.min(maxValue, value));\r\n }\r\n\r\n private clamp01(value: number) {\r\n return Math.max(0, Math.min(1, value));\r\n }\r\n}\r\n"],"names":["SUBSURFACE_PROFILE_PRESET_ALIAS","skin","skin_thin","skin_default","skin_heavy_makeup","wax","wax_backlit","wax_soft","jade","jade_backlit","jade_soft","SUBSURFACE_PROFILE_PRESET_INDEX","SUBSURFACE_PROFILE_PRESET_TEMPLATE","meanFreePathColor","meanFreePathDistance","falloffColor","strength","scale","worldUnitScale","boundaryColorBleed","transmissionTintColor","extinctionScale","normalScale","scatteringDistribution","SUBSURFACE_PROFILE_PRESET_TINT_BIAS","SUBSURFACE_PROFILE_PRESET_RESPONSE","SubsurfaceProfile","_maxProfiles","_profiles","Array","fill","_version","_defaultSkinProfile","_scatterRadius","_falloffColor","_meanFreePathColor","_transmissionTintColor","_preset","_meanFreePathDistance","_strength","_scale","_worldUnitScale","_boundaryColorBleed","_extinctionScale","_normalScale","_scatteringDistribution","_slot","_changeListeners","Vector3","Set","allocateSlot","applyPresetTemplate","version","getProfileBySlot","slot","length","getDefaultSkinProfile","getPresetTintBiasByIndex","index","getPresetNameByIndex","getPresetResponseByIndex","getDerivedTintBias","base","factors","getDerivedProfileFactors","derived","clamp01","warmBias","coolBias","boundaryNorm","distanceNorm","scaleNorm","blend","clampRange","radiusNorm","strengthNorm","mixNumber","getDerivedTransmissionResponse","distributionNorm","extinctionSoftness","worldScaleNorm","scatterRadius","val","equalsTo","set","syncMeanFreePathFromScatterRadius","markDirty","syncScatterRadiusFromMeanFreePath","next","Math","max","preset","resolvePreset","presetIndex","addChangeListener","listener","add","removeChangeListener","delete","profile","i","Error","forEach","name","Object","entries","template","setXYZ","maxRadius","x","y","z","syncFalloffFromMeanFreePath","distance","derivedG","derivedB","getNormalizedTransmissionTintColor","maxChannel","getNormalizedMeanFreePathColor","extinctionWeight","a","b","t","value","minValue","maxValue","min"],"mappings":";;AA8CA,MAAMA,+BAAqG,GAAA;IACzGC,IAAM,EAAA,cAAA;IACNC,SAAW,EAAA,WAAA;IACXC,YAAc,EAAA,cAAA;IACdC,iBAAmB,EAAA,mBAAA;IACnBC,GAAK,EAAA,aAAA;IACLC,WAAa,EAAA,aAAA;IACbC,QAAU,EAAA,UAAA;IACVC,IAAM,EAAA,WAAA;IACNC,YAAc,EAAA,cAAA;IACdC,SAAW,EAAA;AACb,CAAA;AAEA,MAAMC,+BAAoF,GAAA;IACxFT,SAAW,EAAA,CAAA;IACXC,YAAc,EAAA,CAAA;IACdC,iBAAmB,EAAA,CAAA;IACnBE,WAAa,EAAA,CAAA;IACbC,QAAU,EAAA,CAAA;IACVE,YAAc,EAAA,CAAA;IACdC,SAAW,EAAA;AACb,CAAA;AAEA,MAAME,kCAGF,GAAA;IACFV,SAAW,EAAA;QACTW,iBAAmB,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACpCC,oBAAsB,EAAA,GAAA;QACtBC,YAAc,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAI,SAAA;QAC9BC,QAAU,EAAA,IAAA;QACVC,KAAO,EAAA,IAAA;QACPC,cAAgB,EAAA,IAAA;QAChBC,kBAAoB,EAAA,IAAA;QACpBC,qBAAuB,EAAA;AAAC,YAAA,CAAA;AAAG,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACtCC,eAAiB,EAAA,IAAA;QACjBC,WAAa,EAAA,IAAA;QACbC,sBAAwB,EAAA;AAC1B,KAAA;IACApB,YAAc,EAAA;QACZU,iBAAmB,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACpCC,oBAAsB,EAAA,IAAA;QACtBC,YAAc,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QAC/BC,QAAU,EAAA,IAAA;QACVC,KAAO,EAAA,IAAA;QACPC,cAAgB,EAAA,CAAA;QAChBC,kBAAoB,EAAA,IAAA;QACpBC,qBAAuB,EAAA;AAAC,YAAA,CAAA;AAAG,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACtCC,eAAiB,EAAA,IAAA;QACjBC,WAAa,EAAA,CAAA;QACbC,sBAAwB,EAAA;AAC1B,KAAA;IACAnB,iBAAmB,EAAA;QACjBS,iBAAmB,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACpCC,oBAAsB,EAAA,IAAA;QACtBC,YAAc,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QAC/BC,QAAU,EAAA,IAAA;QACVC,KAAO,EAAA,IAAA;QACPC,cAAgB,EAAA,IAAA;QAChBC,kBAAoB,EAAA,IAAA;QACpBC,qBAAuB,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACzCC,eAAiB,EAAA,GAAA;QACjBC,WAAa,EAAA,IAAA;QACbC,sBAAwB,EAAA;AAC1B,KAAA;IACAjB,WAAa,EAAA;QACXO,iBAAmB,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACpCC,oBAAsB,EAAA,IAAA;QACtBC,YAAc,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,GAAA;AAAK,YAAA;AAAK,SAAA;QAC9BC,QAAU,EAAA,IAAA;QACVC,KAAO,EAAA,IAAA;QACPC,cAAgB,EAAA,IAAA;QAChBC,kBAAoB,EAAA,IAAA;QACpBC,qBAAuB,EAAA;AAAC,YAAA,CAAA;AAAG,YAAA,IAAA;AAAM,YAAA;AAAI,SAAA;QACrCC,eAAiB,EAAA,IAAA;QACjBC,WAAa,EAAA,IAAA;QACbC,sBAAwB,EAAA;AAC1B,KAAA;IACAhB,QAAU,EAAA;QACRM,iBAAmB,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACpCC,oBAAsB,EAAA,GAAA;QACtBC,YAAc,EAAA;AAAC,YAAA,GAAA;AAAK,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QAC/BC,QAAU,EAAA,IAAA;QACVC,KAAO,EAAA,IAAA;QACPC,cAAgB,EAAA,IAAA;QAChBC,kBAAoB,EAAA,IAAA;QACpBC,qBAAuB,EAAA;AAAC,YAAA,CAAA;AAAG,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACtCC,eAAiB,EAAA,IAAA;QACjBC,WAAa,EAAA,IAAA;QACbC,sBAAwB,EAAA;AAC1B,KAAA;IACAd,YAAc,EAAA;QACZI,iBAAmB,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA,GAAA;AAAK,YAAA;AAAK,SAAA;QACpCC,oBAAsB,EAAA,IAAA;QACtBC,YAAc,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QAChCC,QAAU,EAAA,IAAA;QACVC,KAAO,EAAA,IAAA;QACPC,cAAgB,EAAA,IAAA;QAChBC,kBAAoB,EAAA,IAAA;QACpBC,qBAAuB,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QACzCC,eAAiB,EAAA,IAAA;QACjBC,WAAa,EAAA,IAAA;QACbC,sBAAwB,EAAA;AAC1B,KAAA;IACAb,SAAW,EAAA;QACTG,iBAAmB,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA,GAAA;AAAK,YAAA;AAAK,SAAA;QACpCC,oBAAsB,EAAA,GAAA;QACtBC,YAAc,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA,IAAA;AAAM,YAAA;AAAK,SAAA;QAChCC,QAAU,EAAA,IAAA;QACVC,KAAO,EAAA,IAAA;QACPC,cAAgB,EAAA,IAAA;QAChBC,kBAAoB,EAAA,IAAA;QACpBC,qBAAuB,EAAA;AAAC,YAAA,IAAA;AAAM,YAAA,IAAA;AAAM,YAAA;AAAI,SAAA;QACxCC,eAAiB,EAAA,CAAA;QACjBC,WAAa,EAAA,IAAA;QACbC,sBAAwB,EAAA;AAC1B;AACF,CAAA;AAEA,MAAMC,mCAGF,GAAA;IACFtB,SAAW,EAAA;AAAC,QAAA,CAAA;AAAG,QAAA,IAAA;AAAM,QAAA;AAAK,KAAA;IAC1BC,YAAc,EAAA;AAAC,QAAA,CAAA;AAAG,QAAA,IAAA;AAAM,QAAA;AAAI,KAAA;IAC5BC,iBAAmB,EAAA;AAAC,QAAA,CAAA;AAAG,QAAA,GAAA;AAAK,QAAA;AAAK,KAAA;IACjCE,WAAa,EAAA;AAAC,QAAA,CAAA;AAAG,QAAA,GAAA;AAAK,QAAA;AAAI,KAAA;IAC1BC,QAAU,EAAA;AAAC,QAAA,CAAA;AAAG,QAAA,IAAA;AAAM,QAAA;AAAK,KAAA;IACzBE,YAAc,EAAA;AAAC,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA;AAAK,KAAA;IAChCC,SAAW,EAAA;AAAC,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA;AAAK;AAC/B,CAAA;AAEA,MAAMe,kCAGF,GAAA;IACFvB,SAAW,EAAA;AAAC,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA;AAAK,KAAA;IACnCC,YAAc,EAAA;AAAC,QAAA,GAAA;AAAK,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA;AAAK,KAAA;IACrCC,iBAAmB,EAAA;AAAC,QAAA,IAAA;AAAM,QAAA,IAAA;QAAM,KAAC;AAAM,QAAA;AAAK,KAAA;IAC5CE,WAAa,EAAA;AAAC,QAAA,IAAA;AAAM,QAAA,GAAA;AAAK,QAAA,IAAA;AAAM,QAAA;AAAK,KAAA;IACpCC,QAAU,EAAA;AAAC,QAAA,GAAA;AAAK,QAAA,GAAA;AAAK,QAAA,IAAA;AAAM,QAAA;AAAI,KAAA;IAC/BE,YAAc,EAAA;AAAC,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA,GAAA;AAAK,QAAA;AAAK,KAAA;IACrCC,SAAW,EAAA;AAAC,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA,IAAA;AAAM,QAAA;AAAK;AACrC,CAAA;AAEA;;;;;;;;;AASC,IACM,MAAMgB,iBAAAA,CAAAA;AACX,IAAA,OAAwBC,eAAe,GAAI;IAC3C,OAAwBC,SAAAA,GAA6C,IAAIC,KACvEH,CAAAA,iBAAAA,CAAkBC,YAAY,GAAG,CAAA,CAAA,CACjCG,IAAI,CAAC,IAAM,CAAA;AACb,IAAA,OAAeC,WAAW,CAAE;AAC5B,IAAA,OAAeC,sBAAgD,IAAK;IACnDC,cAAwB;IACxBC,aAAuB;IACvBC,kBAA4B;IAC5BC,sBAAgC;IACzCC,OAA0C;IAC1CC,qBAA8B;IAC9BC,SAAkB;IAClBC,MAAe;IACfC,eAAwB;IACxBC,mBAA4B;IAC5BC,gBAAyB;IACzBC,YAAqB;IACrBC,uBAAgC;IACvBC,KAAc;IACdC,gBAAkC;AAEnD;;;;AAIC,MACD,WAAc,EAAA;AACZ,QAAA,IAAI,CAACd,cAAc,GAAG,IAAIe,OAAAA,CAAQ,GAAG,CAAG,EAAA,CAAA,CAAA;AACxC,QAAA,IAAI,CAACd,aAAa,GAAG,IAAIc,OAAAA,CAAQ,GAAG,CAAG,EAAA,CAAA,CAAA;AACvC,QAAA,IAAI,CAACb,kBAAkB,GAAG,IAAIa,OAAAA,CAAQ,GAAG,CAAG,EAAA,CAAA,CAAA;AAC5C,QAAA,IAAI,CAACZ,sBAAsB,GAAG,IAAIY,OAAAA,CAAQ,GAAG,CAAG,EAAA,CAAA,CAAA;QAChD,IAAI,CAACX,OAAO,GAAG,cAAA;QACf,IAAI,CAACC,qBAAqB,GAAG,CAAA;QAC7B,IAAI,CAACC,SAAS,GAAG,CAAA;QACjB,IAAI,CAACC,MAAM,GAAG,CAAA;QACd,IAAI,CAACC,eAAe,GAAG,CAAA;QACvB,IAAI,CAACC,mBAAmB,GAAG,CAAA;QAC3B,IAAI,CAACC,gBAAgB,GAAG,CAAA;QACxB,IAAI,CAACC,YAAY,GAAG,CAAA;QACpB,IAAI,CAACC,uBAAuB,GAAG,IAAA;QAC/B,IAAI,CAACE,gBAAgB,GAAG,IAAIE,GAAAA,EAAAA;AAC5B,QAAA,IAAI,CAACH,KAAK,GAAGpB,iBAAkBwB,CAAAA,YAAY,CAAC,IAAI,CAAA;AAChD,QAAA,IAAI,CAACC,mBAAmB,CAAC,IAAI,CAACd,OAAO,EAAE,KAAA,CAAA;AACzC;AAEA;;;;;;;;AAQC,MACD,WAAWe,OAAU,GAAA;QACnB,OAAO,IAAI,CAACrB,QAAQ;AACtB;AAEA;;;;;;;MAQA,OAAOsB,gBAAiBC,CAAAA,IAAY,EAAE;AACpC,QAAA,OAAOA,IAAO,GAAA,CAAA,IAAKA,IAAO,GAAA,IAAI,CAAC1B,SAAS,CAAC2B,MAAM,GAAG,IAAI,CAAC3B,SAAS,CAAC0B,KAAK,GAAG,IAAA;AAC3E;AAEA;;;;;;AAMC,MACD,OAAOE,qBAAwB,GAAA;AAC7B,QAAA,IAAI,CAAC,IAAI,CAACxB,mBAAmB,EAAE;YAC7B,IAAI,CAACA,mBAAmB,GAAG,IAAIN,iBAAAA,EAAAA;AACjC;QACA,OAAO,IAAI,CAACM,mBAAmB;AACjC;AAEA;;;;;;;MAQA,OAAOyB,wBAAyBC,CAAAA,KAAa,EAAE;AAC7C,QAAA,OAAOlC,mCAAmC,CAAC,IAAI,CAACmC,oBAAoB,CAACD,OAAO,IAAI;AAAC,YAAA,CAAA;AAAG,YAAA,CAAA;AAAG,YAAA;AAAE,SAAA;AAC3F;AAEA;;;;;;;MAQA,OAAOE,wBAAyBF,CAAAA,KAAa,EAAE;AAC7C,QAAA,OAAOjC,kCAAkC,CAAC,IAAI,CAACkC,oBAAoB,CAACD,OAAO,IAAI;AAAC,YAAA,CAAA;AAAG,YAAA,CAAA;AAAG,YAAA,CAAA;AAAG,YAAA;AAAE,SAAA;AAC7F;AAEA;;;;;;AAMC,MACDG,kBAA+C,GAAA;AAC7C,QAAA,MAAMC,OAAOtC,mCAAmC,CAAC,IAAI,CAACa,OAAO,CAAC,IAAI;AAAC,YAAA,CAAA;AAAG,YAAA,CAAA;AAAG,YAAA;AAAE,SAAA;QAC3E,MAAM0B,OAAAA,GAAU,IAAI,CAACC,wBAAwB,EAAA;AAC7C,QAAA,MAAMC,OAAoC,GAAA;AACxC,YAAA,IAAI,CAACC,OAAO,CAAC,IAAA,GAAOH,QAAQI,QAAQ,GAAG,IAAOJ,GAAAA,OAAAA,CAAQK,QAAQ,GAAG,IAAOL,GAAAA,OAAAA,CAAQM,YAAY,GAAG,IAAA,CAAA;AAC/F,YAAA,IAAI,CAACH,OAAO,CACV,GAAA,GACEH,OAAQlD,CAAAA,iBAAiB,CAAC,CAAA,CAAE,GAAG,IAAA,GAC/BkD,OAAQ3C,CAAAA,qBAAqB,CAAC,CAAE,CAAA,GAAG,IACnC2C,GAAAA,OAAAA,CAAQO,YAAY,GAAG,IACvBP,GAAAA,OAAAA,CAAQQ,SAAS,GAAG,IACpBR,GAAAA,OAAAA,CAAQM,YAAY,GAAG,IACvBN,GAAAA,OAAAA,CAAQK,QAAQ,GAAG,IAAA,CAAA;AAEvB,YAAA,IAAI,CAACF,OAAO,CACV,IAAA,GACEH,OAAQlD,CAAAA,iBAAiB,CAAC,CAAA,CAAE,GAAG,IAAA,GAC/BkD,OAAQ3C,CAAAA,qBAAqB,CAAC,CAAE,CAAA,GAAG,IACnC2C,GAAAA,OAAAA,CAAQO,YAAY,GAAG,IACvBP,GAAAA,OAAAA,CAAQM,YAAY,GAAG,IACvBN,GAAAA,OAAAA,CAAQK,QAAQ,GAAG,IACnBL,GAAAA,OAAAA,CAAQI,QAAQ,GAAG,IAAA;AAExB,SAAA;AACD,QAAA,MAAMK,QAAQ,IAAI,CAACC,UAAU,CAC3B,IAAA,GAAOV,QAAQW,UAAU,GAAG,IAAOX,GAAAA,OAAAA,CAAQQ,SAAS,GAAG,GAAA,GAAMR,QAAQY,YAAY,GAAG,MACpF,IACA,EAAA,IAAA,CAAA;QAEF,OAAO;YACL,IAAI,CAACC,SAAS,CAACd,IAAI,CAAC,EAAE,EAAEG,OAAO,CAAC,CAAA,CAAE,EAAEO,KAAAA,CAAAA;YACpC,IAAI,CAACI,SAAS,CAACd,IAAI,CAAC,EAAE,EAAEG,OAAO,CAAC,CAAA,CAAE,EAAEO,KAAAA,CAAAA;YACpC,IAAI,CAACI,SAAS,CAACd,IAAI,CAAC,EAAE,EAAEG,OAAO,CAAC,CAAA,CAAE,EAAEO,KAAAA;AACrC,SAAA;AACH;AAEA;;;;;;AAMC,MACDK,8BAAmE,GAAA;AACjE,QAAA,MAAMf,OAAOrC,kCAAkC,CAAC,IAAI,CAACY,OAAO,CAAC,IAAI;AAAC,YAAA,CAAA;AAAG,YAAA,CAAA;AAAG,YAAA,CAAA;AAAG,YAAA;AAAE,SAAA;QAC7E,MAAM0B,OAAAA,GAAU,IAAI,CAACC,wBAAwB,EAAA;QAC7C,MAAMQ,KAAAA,GAAQ,IAAI,CAACC,UAAU,CAC3B,IACEV,GAAAA,OAAAA,CAAQO,YAAY,GAAG,IACvBP,GAAAA,OAAAA,CAAQQ,SAAS,GAAG,IAAA,GACpBR,QAAQY,YAAY,GAAG,MACvBZ,OAAQM,CAAAA,YAAY,GAAG,IAAA,EACzB,IACA,EAAA,GAAA,CAAA;AAEF,QAAA,MAAMJ,OAA4C,GAAA;AAChD,YAAA,IAAI,CAACQ,UAAU,CACb,KACEV,GAAAA,OAAAA,CAAQW,UAAU,GAAG,IACrBX,GAAAA,OAAAA,CAAQO,YAAY,GAAG,OACvBP,OAAQY,CAAAA,YAAY,GAAG,IAAA,GACvBZ,OAAQe,CAAAA,gBAAgB,GAAG,IAAA,GAC3Bf,OAAQM,CAAAA,YAAY,GAAG,IAAA,GACvBN,OAAQgB,CAAAA,kBAAkB,GAAG,IAAA,EAC/B,KACA,EAAA,IAAA,CAAA;YAEF,IAAI,CAACN,UAAU,CACb,IACEV,GAAAA,OAAAA,CAAQW,UAAU,GAAG,GAAA,GACrBX,OAAQQ,CAAAA,SAAS,GAAG,IAAA,GACpBR,QAAQiB,cAAc,GAAG,IACzBjB,GAAAA,OAAAA,CAAQe,gBAAgB,GAAG,IAC3Bf,GAAAA,OAAAA,CAAQgB,kBAAkB,GAAG,IAC/B,EAAA,KACA,EAAA,IAAA,CAAA;AAEF,YAAA,IAAI,CAACN,UAAU,CACb,KACEV,GAAAA,OAAAA,CAAQY,YAAY,GAAG,IACvBZ,GAAAA,OAAAA,CAAQQ,SAAS,GAAG,OACpBR,OAAQgB,CAAAA,kBAAkB,GAAG,IAAA,GAC7BhB,OAAQM,CAAAA,YAAY,GAAG,IAAA,GACvBN,OAAQI,CAAAA,QAAQ,GAAG,IAAA,GACnBJ,OAAQK,CAAAA,QAAQ,GAAG,IAAA,EACrB,KACA,EAAA,IAAA,CAAA;AAEF,YAAA,IAAI,CAACK,UAAU,CACb,KAAC,GACCV,QAAQW,UAAU,GAAG,IACrBX,GAAAA,OAAAA,CAAQQ,SAAS,GAAG,IAAA,GACpBR,OAAQY,CAAAA,YAAY,GAAG,IACvBZ,GAAAA,OAAAA,CAAQM,YAAY,GAAG,OACvBN,OAAQgB,CAAAA,kBAAkB,GAAG,IAAA,GAC7BhB,QAAQI,QAAQ,GAAG,IACnBJ,GAAAA,OAAAA,CAAQ3C,qBAAqB,CAAC,CAAA,CAAE,GAAG,IAAA,EACrC,KACA,EAAA,GAAA;AAEH,SAAA;QACD,OAAO;AACL,YAAA,IAAI,CAACqD,UAAU,CAAC,IAAI,CAACG,SAAS,CAACd,IAAI,CAAC,CAAA,CAAE,EAAEG,OAAO,CAAC,EAAE,EAAEO,KAAAA,CAAAA,EAAQ,KAAO,EAAA,IAAA,CAAA;AACnE,YAAA,IAAI,CAACC,UAAU,CAAC,IAAI,CAACG,SAAS,CAACd,IAAI,CAAC,CAAA,CAAE,EAAEG,OAAO,CAAC,EAAE,EAAEO,KAAAA,CAAAA,EAAQ,KAAO,EAAA,IAAA,CAAA;AACnE,YAAA,IAAI,CAACC,UAAU,CAAC,IAAI,CAACG,SAAS,CAACd,IAAI,CAAC,CAAA,CAAE,EAAEG,OAAO,CAAC,EAAE,EAAEO,KAAAA,CAAAA,EAAQ,KAAO,EAAA,IAAA,CAAA;AACnE,YAAA,IAAI,CAACC,UAAU,CAAC,IAAI,CAACG,SAAS,CAACd,IAAI,CAAC,CAAA,CAAE,EAAEG,OAAO,CAAC,EAAE,EAAEO,KAAAA,CAAAA,EAAQ,KAAO,EAAA,GAAA;AACpE,SAAA;AACH;AAEA;;;;AAIC,MACD,IAAIlB,IAAO,GAAA;QACT,OAAO,IAAI,CAACR,KAAK;AACnB;AAEA;;;;;;;AAOC,MACD,IAAImC,aAAoC,GAAA;QACtC,OAAO,IAAI,CAAChD,cAAc;AAC5B;IAEA,IAAIgD,aAAAA,CAAcC,GAAuB,EAAE;AACzC,QAAA,IAAI,CAACA,GAAIC,CAAAA,QAAQ,CAAC,IAAI,CAAClD,cAAc,CAAG,EAAA;AACtC,YAAA,IAAI,CAACA,cAAc,CAACmD,GAAG,CAACF,GAAAA,CAAAA;AACxB,YAAA,IAAI,CAACG,iCAAiC,EAAA;AACxC;AACF;AAEA;;;;AAIC,MACD,IAAItE,YAAmC,GAAA;QACrC,OAAO,IAAI,CAACmB,aAAa;AAC3B;IAEA,IAAInB,YAAAA,CAAamE,GAAuB,EAAE;AACxC,QAAA,IAAI,CAACA,GAAIC,CAAAA,QAAQ,CAAC,IAAI,CAACjD,aAAa,CAAG,EAAA;AACrC,YAAA,IAAI,CAACA,aAAa,CAACkD,GAAG,CAACF,GAAAA,CAAAA;AACvB,YAAA,IAAI,CAACI,SAAS,EAAA;AAChB;AACF;AAEA;;;;;;;;AAQC,MACD,IAAIzE,iBAAwC,GAAA;QAC1C,OAAO,IAAI,CAACsB,kBAAkB;AAChC;IAEA,IAAItB,iBAAAA,CAAkBqE,GAAuB,EAAE;AAC7C,QAAA,IAAI,CAACA,GAAIC,CAAAA,QAAQ,CAAC,IAAI,CAAChD,kBAAkB,CAAG,EAAA;AAC1C,YAAA,IAAI,CAACA,kBAAkB,CAACiD,GAAG,CAACF,GAAAA,CAAAA;AAC5B,YAAA,IAAI,CAACK,iCAAiC,EAAA;AACxC;AACF;AAEA;;;;AAIC,MACD,IAAIzE,oBAAuB,GAAA;QACzB,OAAO,IAAI,CAACwB,qBAAqB;AACnC;IAEA,IAAIxB,oBAAAA,CAAqBoE,GAAW,EAAE;AACpC,QAAA,MAAMM,IAAOC,GAAAA,IAAAA,CAAKC,GAAG,CAAC,GAAGR,GAAO,IAAA,CAAA,CAAA;AAChC,QAAA,IAAIM,IAAS,KAAA,IAAI,CAAClD,qBAAqB,EAAE;YACvC,IAAI,CAACA,qBAAqB,GAAGkD,IAAAA;AAC7B,YAAA,IAAI,CAACD,iCAAiC,EAAA;AACxC;AACF;AAEA;;;;;;;;AAQC,MACD,IAAII,MAAS,GAAA;QACX,OAAO,IAAI,CAACtD,OAAO;AACrB;IAEA,IAAIsD,MAAAA,CAAOT,GAA4B,EAAE;QACvC,MAAMM,IAAAA,GAAO9D,iBAAkBkE,CAAAA,aAAa,CAACV,GAAAA,CAAAA;AAC7C,QAAA,IAAIM,IAAS,KAAA,IAAI,CAACnD,OAAO,EAAE;YACzB,IAAI,CAACA,OAAO,GAAGmD,IAAAA;YACf,IAAI,CAACrC,mBAAmB,CAACqC,IAAAA,CAAAA;AAC3B;AACF;AAEA;;;;AAIC,MACD,IAAIK,WAAc,GAAA;AAChB,QAAA,OAAOlF,+BAA+B,CAAC,IAAI,CAAC0B,OAAO,CAAC,IAAI,CAAA;AAC1D;AAEA;;;;AAIC,MACD,IAAIrB,QAAW,GAAA;QACb,OAAO,IAAI,CAACuB,SAAS;AACvB;IAEA,IAAIvB,QAAAA,CAASkE,GAAW,EAAE;AACxB,QAAA,IAAIA,GAAQ,KAAA,IAAI,CAAC3C,SAAS,EAAE;YAC1B,IAAI,CAACA,SAAS,GAAG2C,GAAAA;AACjB,YAAA,IAAI,CAACI,SAAS,EAAA;AAChB;AACF;AAEA;;;;AAIC,MACD,IAAIrE,KAAQ,GAAA;QACV,OAAO,IAAI,CAACuB,MAAM;AACpB;IAEA,IAAIvB,KAAAA,CAAMiE,GAAW,EAAE;AACrB,QAAA,IAAIA,GAAQ,KAAA,IAAI,CAAC1C,MAAM,EAAE;YACvB,IAAI,CAACA,MAAM,GAAG0C,GAAAA;AACd,YAAA,IAAI,CAACI,SAAS,EAAA;AAChB;AACF;AAEA;;;;AAIC,MACD,IAAIpE,cAAiB,GAAA;QACnB,OAAO,IAAI,CAACuB,eAAe;AAC7B;IAEA,IAAIvB,cAAAA,CAAegE,GAAW,EAAE;AAC9B,QAAA,MAAMM,IAAOC,GAAAA,IAAAA,CAAKC,GAAG,CAAC,MAAMR,GAAO,IAAA,IAAA,CAAA;AACnC,QAAA,IAAIM,IAAS,KAAA,IAAI,CAAC/C,eAAe,EAAE;YACjC,IAAI,CAACA,eAAe,GAAG+C,IAAAA;AACvB,YAAA,IAAI,CAACF,SAAS,EAAA;AAChB;AACF;AAEA;;;;;;;AAOC,MACD,IAAInE,kBAAqB,GAAA;QACvB,OAAO,IAAI,CAACuB,mBAAmB;AACjC;IAEA,IAAIvB,kBAAAA,CAAmB+D,GAAW,EAAE;AAClC,QAAA,MAAMM,IAAO,GAAA,IAAI,CAACtB,OAAO,CAACgB,GAAO,IAAA,CAAA,CAAA;AACjC,QAAA,IAAIM,IAAS,KAAA,IAAI,CAAC9C,mBAAmB,EAAE;YACrC,IAAI,CAACA,mBAAmB,GAAG8C,IAAAA;AAC3B,YAAA,IAAI,CAACF,SAAS,EAAA;AAChB;AACF;AAEA;;;;AAIC,MACD,IAAIlE,qBAA4C,GAAA;QAC9C,OAAO,IAAI,CAACgB,sBAAsB;AACpC;IAEA,IAAIhB,qBAAAA,CAAsB8D,GAAuB,EAAE;AACjD,QAAA,IAAI,CAACA,GAAIC,CAAAA,QAAQ,CAAC,IAAI,CAAC/C,sBAAsB,CAAG,EAAA;AAC9C,YAAA,IAAI,CAACA,sBAAsB,CAACgD,GAAG,CAACF,GAAAA,CAAAA;AAChC,YAAA,IAAI,CAACI,SAAS,EAAA;AAChB;AACF;AAEA;;;;;;;AAOC,MACD,IAAIjE,eAAkB,GAAA;QACpB,OAAO,IAAI,CAACsB,gBAAgB;AAC9B;IAEA,IAAItB,eAAAA,CAAgB6D,GAAW,EAAE;AAC/B,QAAA,MAAMM,IAAOC,GAAAA,IAAAA,CAAKC,GAAG,CAAC,GAAGR,GAAO,IAAA,CAAA,CAAA;AAChC,QAAA,IAAIM,IAAS,KAAA,IAAI,CAAC7C,gBAAgB,EAAE;YAClC,IAAI,CAACA,gBAAgB,GAAG6C,IAAAA;AACxB,YAAA,IAAI,CAACF,SAAS,EAAA;AAChB;AACF;AAEA;;;;;;;AAOC,MACD,IAAIhE,WAAc,GAAA;QAChB,OAAO,IAAI,CAACsB,YAAY;AAC1B;IAEA,IAAItB,WAAAA,CAAY4D,GAAW,EAAE;AAC3B,QAAA,MAAMM,IAAOC,GAAAA,IAAAA,CAAKC,GAAG,CAAC,GAAGR,GAAO,IAAA,CAAA,CAAA;AAChC,QAAA,IAAIM,IAAS,KAAA,IAAI,CAAC5C,YAAY,EAAE;YAC9B,IAAI,CAACA,YAAY,GAAG4C,IAAAA;AACpB,YAAA,IAAI,CAACF,SAAS,EAAA;AAChB;AACF;AAEA;;;;;;;AAOC,MACD,IAAI/D,sBAAyB,GAAA;QAC3B,OAAO,IAAI,CAACsB,uBAAuB;AACrC;IAEA,IAAItB,sBAAAA,CAAuB2D,GAAW,EAAE;AACtC,QAAA,MAAMM,IAAO,GAAA,IAAI,CAACtB,OAAO,CAACgB,GAAO,IAAA,CAAA,CAAA;AACjC,QAAA,IAAIM,IAAS,KAAA,IAAI,CAAC3C,uBAAuB,EAAE;YACzC,IAAI,CAACA,uBAAuB,GAAG2C,IAAAA;AAC/B,YAAA,IAAI,CAACF,SAAS,EAAA;AAChB;AACF;AAEA;;;;;;MAOAQ,iBAAAA,CAAkBC,QAAoB,EAAE;AACtC,QAAA,IAAI,CAAChD,gBAAgB,CAACiD,GAAG,CAACD,QAAAA,CAAAA;AAC5B;AAEA;;;;;;MAOAE,oBAAAA,CAAqBF,QAAoB,EAAE;AACzC,QAAA,IAAI,CAAChD,gBAAgB,CAACmD,MAAM,CAACH,QAAAA,CAAAA;AAC/B;IAEA,OAAe7C,YAAAA,CAAaiD,OAA0B,EAAE;QACtD,IAAK,IAAIC,CAAI,GAAA,CAAA,EAAGA,CAAI,GAAA,IAAI,CAACxE,SAAS,CAAC2B,MAAM,EAAE6C,CAAK,EAAA,CAAA;AAC9C,YAAA,IAAI,CAAC,IAAI,CAACxE,SAAS,CAACwE,EAAE,EAAE;AACtB,gBAAA,IAAI,CAACxE,SAAS,CAACwE,CAAAA,CAAE,GAAGD,OAAAA;AACpB,gBAAA,IAAI,CAACpE,QAAQ,EAAA;gBACb,OAAOqE,CAAAA;AACT;AACF;AACA,QAAA,MAAM,IAAIC,KAAM,CAAA,kCAAA,CAAA;AAClB;IAEQf,SAAY,GAAA;AAClB5D,QAAAA,iBAAAA,CAAkBK,QAAQ,EAAA;AAC1B,QAAA,IAAI,CAACgB,gBAAgB,CAACuD,OAAO,CAAC,CAACP,QAAaA,GAAAA,QAAAA,EAAAA,CAAAA;AAC9C;IAEA,OAAeH,aAAAA,CAAcD,MAAkD,EAAE;AAC/E,QAAA,OAAO3F,+BAA+B,CAAC2F,MAAU,IAAA,cAAA,CAAe,IAAI,cAAA;AACtE;IAEA,OAAehC,oBAAAA,CAAqBD,KAAa,EAAoC;QACnF,KAAK,MAAM,CAAC6C,IAAMV,EAAAA,WAAAA,CAAY,IAAIW,MAAOC,CAAAA,OAAO,CAAC9F,+BAE9C,CAAA,CAAA;AACD,YAAA,IAAIkF,gBAAgBnC,KAAO,EAAA;gBACzB,OAAO6C,IAAAA;AACT;AACF;QACA,OAAO,cAAA;AACT;AAEQpD,IAAAA,mBAAAA,CAAoBwC,MAAwC,EAAEL,SAAY,GAAA,IAAI,EAAE;AACtF,QAAA,MAAMoB,WACJ9F,kCAAkC,CAAC+E,MAAO,CAAA,IAAI/E,mCAAmCT,YAAY;AAC/F,QAAA,IAAI,CAACgC,kBAAkB,CAACwE,MAAM,CAC5BD,QAAAA,CAAS7F,iBAAiB,CAAC,CAAA,CAAE,EAC7B6F,QAAAA,CAAS7F,iBAAiB,CAAC,CAAA,CAAE,EAC7B6F,QAAS7F,CAAAA,iBAAiB,CAAC,CAAE,CAAA,CAAA;AAE/B,QAAA,IAAI,CAACyB,qBAAqB,GAAGoE,QAAAA,CAAS5F,oBAAoB;AAC1D,QAAA,IAAI,CAACyB,SAAS,GAAGmE,QAAAA,CAAS1F,QAAQ;AAClC,QAAA,IAAI,CAACwB,MAAM,GAAGkE,QAAAA,CAASzF,KAAK;AAC5B,QAAA,IAAI,CAACwB,eAAe,GAAGiE,QAAAA,CAASxF,cAAc;AAC9C,QAAA,IAAI,CAACwB,mBAAmB,GAAGgE,QAAAA,CAASvF,kBAAkB;AACtD,QAAA,IAAI,CAACiB,sBAAsB,CAACuE,MAAM,CAChCD,QAAAA,CAAStF,qBAAqB,CAAC,CAAA,CAAE,EACjCsF,QAAAA,CAAStF,qBAAqB,CAAC,CAAA,CAAE,EACjCsF,QAAStF,CAAAA,qBAAqB,CAAC,CAAE,CAAA,CAAA;AAEnC,QAAA,IAAI,CAACuB,gBAAgB,GAAG+D,QAAAA,CAASrF,eAAe;AAChD,QAAA,IAAI,CAACuB,YAAY,GAAG8D,QAAAA,CAASpF,WAAW;AACxC,QAAA,IAAI,CAACuB,uBAAuB,GAAG6D,QAAAA,CAASnF,sBAAsB;QAC9D,IAAI,CAACgE,iCAAiC,CAAC,KAAA,CAAA;AACvC,QAAA,IAAID,SAAW,EAAA;AACb,YAAA,IAAI,CAACA,SAAS,EAAA;AAChB;AACF;IAEQD,iCAAkCC,CAAAA,SAAAA,GAAY,IAAI,EAAE;QAC1D,MAAMsB,SAAAA,GAAYnB,KAAKC,GAAG,CAAC,IAAI,CAACzD,cAAc,CAAC4E,CAAC,EAAE,IAAI,CAAC5E,cAAc,CAAC6E,CAAC,EAAE,IAAI,CAAC7E,cAAc,CAAC8E,CAAC,CAAA;AAC9F,QAAA,IAAIH,YAAY,IAAM,EAAA;YACpB,IAAI,CAACtE,qBAAqB,GAAGsE,SAAAA;YAC7B,IAAI,CAACzE,kBAAkB,CAACwE,MAAM,CAC5B,IAAI,CAAC1E,cAAc,CAAC4E,CAAC,GAAGD,SAAAA,EACxB,IAAI,CAAC3E,cAAc,CAAC6E,CAAC,GAAGF,SAAAA,EACxB,IAAI,CAAC3E,cAAc,CAAC8E,CAAC,GAAGH,SAAAA,CAAAA;SAErB,MAAA;YACL,IAAI,CAACtE,qBAAqB,GAAG,CAAA;AAC7B,YAAA,IAAI,CAACH,kBAAkB,CAACwE,MAAM,CAAC,GAAG,CAAG,EAAA,CAAA,CAAA;AACvC;QACA,IAAI,CAACK,2BAA2B,CAAC,KAAA,CAAA;AACjC,QAAA,IAAI1B,SAAW,EAAA;AACb,YAAA,IAAI,CAACA,SAAS,EAAA;AAChB;AACF;IAEQC,iCAAkCD,CAAAA,SAAAA,GAAY,IAAI,EAAE;AAC1D,QAAA,MAAM2B,WAAWxB,IAAKC,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAACpD,qBAAqB,CAAA;AACvD,QAAA,IAAI,CAACL,cAAc,CAAC0E,MAAM,CACxBlB,KAAKC,GAAG,CAAC,CAAG,EAAA,IAAI,CAACvD,kBAAkB,CAAC0E,CAAC,CAAA,GAAII,UACzCxB,IAAKC,CAAAA,GAAG,CAAC,CAAA,EAAG,IAAI,CAACvD,kBAAkB,CAAC2E,CAAC,IAAIG,QACzCxB,EAAAA,IAAAA,CAAKC,GAAG,CAAC,GAAG,IAAI,CAACvD,kBAAkB,CAAC4E,CAAC,CAAIE,GAAAA,QAAAA,CAAAA;QAE3C,IAAI,CAACD,2BAA2B,CAAC,KAAA,CAAA;AACjC,QAAA,IAAI1B,SAAW,EAAA;AACb,YAAA,IAAI,CAACA,SAAS,EAAA;AAChB;AACF;IAEQ0B,2BAA4B1B,CAAAA,SAAAA,GAAY,IAAI,EAAE;AACpD,QAAA,MAAMxB,IACJlD,GAAAA,kCAAkC,CAAC,IAAI,CAACyB,OAAO,CAAC,EAAEtB,YAClDH,IAAAA,kCAAAA,CAAmCT,YAAY,CAACY,YAAY;QAC9D,MAAMgD,OAAAA,GAAU,IAAI,CAACC,wBAAwB,EAAA;AAC7C,QAAA,MAAMkD,WAAW,IAAI,CAAChD,OAAO,CAC3B,OACEH,OAAQlD,CAAAA,iBAAiB,CAAC,CAAA,CAAE,GAAG,GAC/BkD,GAAAA,OAAAA,CAAQ3C,qBAAqB,CAAC,EAAE,GAAG,IAAA,GACnC2C,OAAQO,CAAAA,YAAY,GAAG,IACvBP,GAAAA,OAAAA,CAAQQ,SAAS,GAAG,OACpBR,OAAQe,CAAAA,gBAAgB,GAAG,IAAA,GAC3B,CAAC,CAAA,GAAIf,OAAQgB,CAAAA,kBAAkB,IAAI,IAAA,CAAA;AAEvC,QAAA,MAAMoC,QAAW,GAAA,IAAI,CAACjD,OAAO,CAC3B,IACEH,GAAAA,OAAAA,CAAQlD,iBAAiB,CAAC,CAAE,CAAA,GAAG,IAC/BkD,GAAAA,OAAAA,CAAQ3C,qBAAqB,CAAC,CAAA,CAAE,GAAG,IAAA,GACnC2C,OAAQO,CAAAA,YAAY,GAAG,IAAA,GACvBP,QAAQM,YAAY,GAAG,IACvBN,GAAAA,OAAAA,CAAQK,QAAQ,GAAG,IACnBL,GAAAA,OAAAA,CAAQI,QAAQ,GAAG,IAAA,CAAA;AAEvB,QAAA,MAAMK,QAAQ,IAAI,CAACC,UAAU,CAC3B,IAAA,GAAOV,QAAQO,YAAY,GAAG,IAAOP,GAAAA,OAAAA,CAAQQ,SAAS,GAAG,IAAA,GAAOR,QAAQY,YAAY,GAAG,MACvF,IACA,EAAA,IAAA,CAAA;QAEF,IAAI,CAACzC,aAAa,CAACyE,MAAM,CACvB,GACA,IAAI,CAAC/B,SAAS,CAACd,IAAI,CAAC,EAAE,EAAEoD,QAAAA,EAAU1C,KAClC,CAAA,EAAA,IAAI,CAACI,SAAS,CAACd,IAAI,CAAC,CAAE,CAAA,EAAEqD,QAAU3C,EAAAA,KAAAA,CAAAA,CAAAA;AAEpC,QAAA,IAAIc,SAAW,EAAA;AACb,YAAA,IAAI,CAACA,SAAS,EAAA;AAChB;AACF;IAEQ8B,kCAA+D,GAAA;QACrE,MAAMC,UAAAA,GAAa5B,KAAKC,GAAG,CACzB,IAAI,CAACtD,sBAAsB,CAACyE,CAAC,EAC7B,IAAI,CAACzE,sBAAsB,CAAC0E,CAAC,EAC7B,IAAI,CAAC1E,sBAAsB,CAAC2E,CAAC,EAC7B,IAAA,CAAA;QAEF,OAAO;YACLtB,IAAKC,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAACtD,sBAAsB,CAACyE,CAAC,CAAIQ,GAAAA,UAAAA;YAC7C5B,IAAKC,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAACtD,sBAAsB,CAAC0E,CAAC,CAAIO,GAAAA,UAAAA;YAC7C5B,IAAKC,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAACtD,sBAAsB,CAAC2E,CAAC,CAAIM,GAAAA;AAC9C,SAAA;AACH;IAEQrD,wBAA2B,GAAA;QACjC,MAAMnD,iBAAAA,GAAoB,IAAI,CAACyG,8BAA8B,EAAA;QAC7D,MAAMlG,qBAAAA,GAAwB,IAAI,CAACgG,kCAAkC,EAAA;QACrE,MAAMR,SAAAA,GAAYnB,KAAKC,GAAG,CAAC,IAAI,CAACzD,cAAc,CAAC4E,CAAC,EAAE,IAAI,CAAC5E,cAAc,CAAC6E,CAAC,EAAE,IAAI,CAAC7E,cAAc,CAAC8E,CAAC,CAAA;AAC9F,QAAA,MAAMrC,aAAa,IAAI,CAACD,UAAU,CAACmC,SAAAA,GAAY,MAAM,CAAG,EAAA,GAAA,CAAA;QACxD,MAAMtC,YAAAA,GAAe,IAAI,CAACG,UAAU,CAAC,IAAI,CAACnC,qBAAqB,GAAG,IAAA,EAAM,CAAG,EAAA,GAAA,CAAA;QAC3E,MAAMiC,SAAAA,GAAY,IAAI,CAACE,UAAU,CAAC,IAAI,CAACjC,MAAM,GAAG,IAAA,EAAM,CAAG,EAAA,GAAA,CAAA;QACzD,MAAMmC,YAAAA,GAAe,IAAI,CAACF,UAAU,CAAC,IAAI,CAAClC,SAAS,GAAG,GAAA,EAAK,CAAG,EAAA,GAAA,CAAA;QAC9D,MAAMyC,cAAAA,GAAiB,IAAI,CAACP,UAAU,CAAC,IAAI,CAAChC,eAAe,GAAG,IAAA,EAAM,CAAG,EAAA,GAAA,CAAA;AACvE,QAAA,MAAM4B,eAAe,IAAI,CAACH,OAAO,CAAC,IAAI,CAACxB,mBAAmB,CAAA;AAC1D,QAAA,MAAMoC,mBAAmB,IAAI,CAACZ,OAAO,CAAC,IAAI,CAACrB,uBAAuB,CAAA;AAClE,QAAA,MAAM0E,gBAAmB,GAAA,IAAI,CAAC9C,UAAU,CAAC,CAAIgB,GAAAA,IAAAA,CAAKC,GAAG,CAAC,IAAI,CAAC/C,gBAAgB,EAAE,OAAO,IAAM,EAAA,IAAA,CAAA;QAC1F,MAAMoC,kBAAAA,GAAqB,IAAI,CAACb,OAAO,CAAC,CAACqD,gBAAmB,GAAA,IAAG,IAAK,GAAA,CAAA;QACpE,MAAMpD,QAAAA,GAAW,IAAI,CAACD,OAAO,CAC3B,GACE,GAACrD,CAAAA,iBAAiB,CAAC,EAAE,GAAG4E,IAAAA,CAAKC,GAAG,CAAC7E,iBAAiB,CAAC,CAAE,CAAA,EAAEA,iBAAiB,CAAC,CAAA,CAAE,IAAI,IAAG,IAAK,OACvF,CAACO,qBAAqB,CAAC,CAAA,CAAE,GAAGqE,IAAKC,CAAAA,GAAG,CAACtE,qBAAqB,CAAC,EAAE,EAAEA,qBAAqB,CAAC,CAAE,CAAA,CAAA,GAAI,IAAG,IAAK,GAAA,CAAA;AAEvG,QAAA,MAAMgD,QAAW,GAAA,IAAI,CAACF,OAAO,CAC3B,IAAA,GACE,CAAC9C,qBAAqB,CAAC,CAAE,CAAA,GAAGA,qBAAqB,CAAC,CAAA,CAAE,GAAG,IAAG,IAAK,IAAA,GAC/D,CAACP,iBAAiB,CAAC,CAAE,CAAA,GAAGA,iBAAiB,CAAC,CAAE,CAAA,GAAG,IAAG,IAAK,IAAA,CAAA;QAE3D,OAAO;AACLA,YAAAA,iBAAAA;AACAO,YAAAA,qBAAAA;AACAsD,YAAAA,UAAAA;AACAJ,YAAAA,YAAAA;AACAC,YAAAA,SAAAA;AACAI,YAAAA,YAAAA;AACAK,YAAAA,cAAAA;AACAX,YAAAA,YAAAA;AACAS,YAAAA,gBAAAA;AACAC,YAAAA,kBAAAA;AACAZ,YAAAA,QAAAA;AACAC,YAAAA;AACF,SAAA;AACF;IAEQkD,8BAA2D,GAAA;QACjE,MAAMD,UAAAA,GAAa5B,KAAKC,GAAG,CACzB,IAAI,CAACvD,kBAAkB,CAAC0E,CAAC,EACzB,IAAI,CAAC1E,kBAAkB,CAAC2E,CAAC,EACzB,IAAI,CAAC3E,kBAAkB,CAAC4E,CAAC,EACzB,IAAA,CAAA;QAEF,OAAO;YACLtB,IAAKC,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAACvD,kBAAkB,CAAC0E,CAAC,CAAIQ,GAAAA,UAAAA;YACzC5B,IAAKC,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAACvD,kBAAkB,CAAC2E,CAAC,CAAIO,GAAAA,UAAAA;YACzC5B,IAAKC,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAACvD,kBAAkB,CAAC4E,CAAC,CAAIM,GAAAA;AAC1C,SAAA;AACH;AAEQzC,IAAAA,SAAAA,CAAU4C,CAAS,EAAEC,CAAS,EAAEC,CAAS,EAAE;AACjD,QAAA,OAAOF,CAAK,IAAA,CAAIE,GAAAA,CAAAA,IAAKD,CAAIC,GAAAA,CAAAA;AAC3B;AAEQjD,IAAAA,UAAAA,CAAWkD,KAAa,EAAEC,QAAgB,EAAEC,QAAgB,EAAE;AACpE,QAAA,OAAOpC,KAAKC,GAAG,CAACkC,UAAUnC,IAAKqC,CAAAA,GAAG,CAACD,QAAUF,EAAAA,KAAAA,CAAAA,CAAAA;AAC/C;AAEQzD,IAAAA,OAAAA,CAAQyD,KAAa,EAAE;AAC7B,QAAA,OAAOlC,KAAKC,GAAG,CAAC,GAAGD,IAAKqC,CAAAA,GAAG,CAAC,CAAGH,EAAAA,KAAAA,CAAAA,CAAAA;AACjC;AACF;;;;"}
1
+ {"version":3,"file":"subsurfaceprofile.js","sources":["../../src/material/subsurfaceprofile.ts"],"sourcesContent":["import { Vector3, type Immutable } from '@zephyr3d/base';\r\n\r\n/**\r\n * Built-in subsurface scattering profile preset names.\r\n *\r\n * @remarks\r\n * The short aliases (`skin`, `wax`, and `jade`) resolve to their default\r\n * canonical profiles.\r\n *\r\n * @public\r\n */\r\nexport type SubsurfaceProfilePreset =\r\n | 'skin'\r\n | 'skin_thin'\r\n | 'skin_default'\r\n | 'skin_heavy_makeup'\r\n | 'wax'\r\n | 'wax_backlit'\r\n | 'wax_soft'\r\n | 'jade'\r\n | 'jade_backlit'\r\n | 'jade_soft';\r\n\r\ntype CanonicalSubsurfaceProfilePreset =\r\n | 'skin_thin'\r\n | 'skin_default'\r\n | 'skin_heavy_makeup'\r\n | 'wax_backlit'\r\n | 'wax_soft'\r\n | 'jade_backlit'\r\n | 'jade_soft';\r\n\r\ntype SubsurfaceProfilePresetTemplate = {\r\n meanFreePathColor: [number, number, number];\r\n meanFreePathDistance: number;\r\n falloffColor: [number, number, number];\r\n strength: number;\r\n scale: number;\r\n worldUnitScale: number;\r\n boundaryColorBleed: number;\r\n transmissionTintColor: [number, number, number];\r\n extinctionScale: number;\r\n normalScale: number;\r\n scatteringDistribution: number;\r\n specularDetailSoftness: number;\r\n specularDetailRadius: number;\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_ALIAS: Record<SubsurfaceProfilePreset, CanonicalSubsurfaceProfilePreset> = {\r\n skin: 'skin_default',\r\n skin_thin: 'skin_thin',\r\n skin_default: 'skin_default',\r\n skin_heavy_makeup: 'skin_heavy_makeup',\r\n wax: 'wax_backlit',\r\n wax_backlit: 'wax_backlit',\r\n wax_soft: 'wax_soft',\r\n jade: 'jade_soft',\r\n jade_backlit: 'jade_backlit',\r\n jade_soft: 'jade_soft'\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_INDEX: Record<CanonicalSubsurfaceProfilePreset, number> = {\r\n skin_thin: 0,\r\n skin_default: 1,\r\n skin_heavy_makeup: 2,\r\n wax_backlit: 3,\r\n wax_soft: 4,\r\n jade_backlit: 5,\r\n jade_soft: 6\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_TEMPLATE: Record<\r\n CanonicalSubsurfaceProfilePreset,\r\n SubsurfaceProfilePresetTemplate\r\n> = {\r\n skin_thin: {\r\n meanFreePathColor: [1.0, 0.37, 0.11],\r\n meanFreePathDistance: 0.7,\r\n falloffColor: [1.0, 0.32, 0.2],\r\n strength: 0.68,\r\n scale: 0.82,\r\n worldUnitScale: 0.88,\r\n boundaryColorBleed: 0.13,\r\n transmissionTintColor: [1, 0.37, 0.28],\r\n extinctionScale: 1.24,\r\n normalScale: 1.18,\r\n scatteringDistribution: 0.56,\r\n specularDetailSoftness: 0.66,\r\n specularDetailRadius: 1.35\r\n },\r\n skin_default: {\r\n meanFreePathColor: [1.0, 0.45, 0.17],\r\n meanFreePathDistance: 0.92,\r\n falloffColor: [1.0, 0.39, 0.25],\r\n strength: 0.82,\r\n scale: 0.96,\r\n worldUnitScale: 1,\r\n boundaryColorBleed: 0.22,\r\n transmissionTintColor: [1, 0.46, 0.34],\r\n extinctionScale: 1.06,\r\n normalScale: 1,\r\n scatteringDistribution: 0.6,\r\n specularDetailSoftness: 0.78,\r\n specularDetailRadius: 1.8\r\n },\r\n skin_heavy_makeup: {\r\n meanFreePathColor: [1.0, 0.33, 0.11],\r\n meanFreePathDistance: 0.68,\r\n falloffColor: [1.0, 0.26, 0.16],\r\n strength: 0.56,\r\n scale: 0.76,\r\n worldUnitScale: 0.84,\r\n boundaryColorBleed: 0.08,\r\n transmissionTintColor: [0.94, 0.31, 0.22],\r\n extinctionScale: 1.4,\r\n normalScale: 1.26,\r\n scatteringDistribution: 0.5,\r\n specularDetailSoftness: 0.86,\r\n specularDetailRadius: 2.1\r\n },\r\n wax_backlit: {\r\n meanFreePathColor: [1.0, 0.68, 0.36],\r\n meanFreePathDistance: 1.54,\r\n falloffColor: [1.0, 0.8, 0.66],\r\n strength: 1.12,\r\n scale: 1.42,\r\n worldUnitScale: 1.26,\r\n boundaryColorBleed: 0.42,\r\n transmissionTintColor: [1, 0.82, 0.7],\r\n extinctionScale: 0.78,\r\n normalScale: 0.92,\r\n scatteringDistribution: 0.82,\r\n specularDetailSoftness: 0.88,\r\n specularDetailRadius: 2.35\r\n },\r\n wax_soft: {\r\n meanFreePathColor: [1.0, 0.72, 0.38],\r\n meanFreePathDistance: 1.2,\r\n falloffColor: [1.0, 0.86, 0.74],\r\n strength: 1.02,\r\n scale: 1.28,\r\n worldUnitScale: 1.12,\r\n boundaryColorBleed: 0.36,\r\n transmissionTintColor: [1, 0.86, 0.74],\r\n extinctionScale: 0.86,\r\n normalScale: 0.98,\r\n scatteringDistribution: 0.74,\r\n specularDetailSoftness: 0.94,\r\n specularDetailRadius: 2.65\r\n },\r\n jade_backlit: {\r\n meanFreePathColor: [0.74, 1.0, 0.88],\r\n meanFreePathDistance: 0.92,\r\n falloffColor: [0.66, 0.94, 0.88],\r\n strength: 0.92,\r\n scale: 1.14,\r\n worldUnitScale: 1.06,\r\n boundaryColorBleed: 0.26,\r\n transmissionTintColor: [0.68, 0.92, 0.86],\r\n extinctionScale: 0.92,\r\n normalScale: 1.02,\r\n scatteringDistribution: 0.7,\r\n specularDetailSoftness: 0.42,\r\n specularDetailRadius: 1.2\r\n },\r\n jade_soft: {\r\n meanFreePathColor: [0.68, 1.0, 0.84],\r\n meanFreePathDistance: 0.8,\r\n falloffColor: [0.72, 0.94, 0.86],\r\n strength: 0.82,\r\n scale: 1.02,\r\n worldUnitScale: 0.98,\r\n boundaryColorBleed: 0.22,\r\n transmissionTintColor: [0.74, 0.96, 0.9],\r\n extinctionScale: 1,\r\n normalScale: 1.04,\r\n scatteringDistribution: 0.66,\r\n specularDetailSoftness: 0.5,\r\n specularDetailRadius: 1.4\r\n }\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_TINT_BIAS: Record<\r\n CanonicalSubsurfaceProfilePreset,\r\n [number, number, number]\r\n> = {\r\n skin_thin: [1, 0.56, 0.46],\r\n skin_default: [1, 0.62, 0.5],\r\n skin_heavy_makeup: [1, 0.5, 0.42],\r\n wax_backlit: [1, 0.8, 0.7],\r\n wax_soft: [1, 0.86, 0.78],\r\n jade_backlit: [0.72, 0.92, 0.96],\r\n jade_soft: [0.68, 0.96, 0.88]\r\n};\r\n\r\nconst SUBSURFACE_PROFILE_PRESET_RESPONSE: Record<\r\n CanonicalSubsurfaceProfilePreset,\r\n [number, number, number, number]\r\n> = {\r\n skin_thin: [0.08, 0.12, 0.06, 0.12],\r\n skin_default: [0.1, 0.14, 0.08, 0.16],\r\n skin_heavy_makeup: [0.02, 0.05, -0.02, 0.01],\r\n wax_backlit: [0.12, 0.2, 0.26, 0.24],\r\n wax_soft: [0.2, 0.3, 0.34, 0.1],\r\n jade_backlit: [0.08, 0.18, 0.2, 0.24],\r\n jade_soft: [0.16, 0.24, 0.22, 0.12]\r\n};\r\n\r\n/**\r\n * Serializable subsurface scattering profile.\r\n *\r\n * @remarks\r\n * The profile stores the channel-dependent scattering radius and falloff used\r\n * by the screen-space SSS post effect. Materials can share a profile instance\r\n * to emulate Unreal-style skin profile assets.\r\n *\r\n * @public\r\n */\r\nexport class SubsurfaceProfile {\r\n private static readonly _maxProfiles = 255;\r\n private static readonly _profiles: Array<SubsurfaceProfile | null> = new Array(\r\n SubsurfaceProfile._maxProfiles + 1\r\n ).fill(null);\r\n private static _version = 0;\r\n private static _defaultSkinProfile: SubsurfaceProfile | null = null;\r\n private readonly _scatterRadius: Vector3;\r\n private readonly _falloffColor: Vector3;\r\n private readonly _meanFreePathColor: Vector3;\r\n private readonly _transmissionTintColor: Vector3;\r\n private _preset: CanonicalSubsurfaceProfilePreset;\r\n private _meanFreePathDistance: number;\r\n private _strength: number;\r\n private _scale: number;\r\n private _worldUnitScale: number;\r\n private _boundaryColorBleed: number;\r\n private _extinctionScale: number;\r\n private _normalScale: number;\r\n private _scatteringDistribution: number;\r\n private _specularDetailSoftness: number;\r\n private _specularDetailRadius: number;\r\n private readonly _slot: number;\r\n private readonly _changeListeners: Set<() => void>;\r\n private _disposed: boolean;\r\n\r\n /**\r\n * Creates a subsurface scattering profile initialized with the default skin preset.\r\n *\r\n * @public\r\n */\r\n constructor() {\r\n this._scatterRadius = new Vector3(0, 0, 0);\r\n this._falloffColor = new Vector3(0, 0, 0);\r\n this._meanFreePathColor = new Vector3(0, 0, 0);\r\n this._transmissionTintColor = new Vector3(0, 0, 0);\r\n this._preset = 'skin_default';\r\n this._meanFreePathDistance = 0;\r\n this._strength = 0;\r\n this._scale = 0;\r\n this._worldUnitScale = 1;\r\n this._boundaryColorBleed = 0;\r\n this._extinctionScale = 1;\r\n this._normalScale = 1;\r\n this._scatteringDistribution = 0.65;\r\n this._specularDetailSoftness = 0.78;\r\n this._specularDetailRadius = 1.8;\r\n this._changeListeners = new Set();\r\n this._disposed = false;\r\n this._slot = SubsurfaceProfile.allocateSlot(this);\r\n this.applyPresetTemplate(this._preset, false);\r\n }\r\n\r\n clone() {\r\n const other = new SubsurfaceProfile();\r\n other.copyFrom(this);\r\n return other;\r\n }\r\n\r\n copyFrom(other: SubsurfaceProfile) {\r\n this.preset = other.preset;\r\n this.meanFreePathColor = other.meanFreePathColor;\r\n this.meanFreePathDistance = other.meanFreePathDistance;\r\n this.strength = other.strength;\r\n this.scale = other.scale;\r\n this.worldUnitScale = other.worldUnitScale;\r\n this.boundaryColorBleed = other.boundaryColorBleed;\r\n this.transmissionTintColor = other.transmissionTintColor;\r\n this.extinctionScale = other.extinctionScale;\r\n this.normalScale = other.normalScale;\r\n this.scatteringDistribution = other.scatteringDistribution;\r\n this.specularDetailSoftness = other.specularDetailSoftness;\r\n this.specularDetailRadius = other.specularDetailRadius;\r\n this.falloffColor = other.falloffColor;\r\n }\r\n\r\n dispose() {\r\n if (this._disposed) {\r\n return;\r\n }\r\n this._disposed = true;\r\n this._changeListeners.clear();\r\n SubsurfaceProfile.releaseSlot(this._slot, this);\r\n }\r\n\r\n static get version() {\r\n return this._version;\r\n }\r\n\r\n /**\r\n * Gets the profile assigned to a packed profile slot.\r\n *\r\n * @param slot - The 1-based profile slot index.\r\n * @returns The profile assigned to the slot, or `null` if the slot is invalid or unused.\r\n *\r\n * @public\r\n */\r\n static getProfileBySlot(slot: number) {\r\n return slot > 0 && slot < this._profiles.length ? this._profiles[slot] : null;\r\n }\r\n\r\n /**\r\n * Gets the shared default skin subsurface profile.\r\n *\r\n * @returns The lazily-created default skin profile.\r\n *\r\n * @public\r\n */\r\n static getDefaultSkinProfile() {\r\n if (!this._defaultSkinProfile) {\r\n this._defaultSkinProfile = new SubsurfaceProfile();\r\n }\r\n return this._defaultSkinProfile;\r\n }\r\n\r\n /**\r\n * Gets the preset tint bias used by the screen-space transmission model.\r\n *\r\n * @param index - The packed canonical preset index.\r\n * @returns The RGB tint bias for the preset, or white when the index is unknown.\r\n *\r\n * @public\r\n */\r\n static getPresetTintBiasByIndex(index: number) {\r\n return SUBSURFACE_PROFILE_PRESET_TINT_BIAS[this.getPresetNameByIndex(index)] ?? [1, 1, 1];\r\n }\r\n\r\n /**\r\n * Gets the preset transmission response used by the screen-space SSS pass.\r\n *\r\n * @param index - The packed canonical preset index.\r\n * @returns The four-component transmission response for the preset.\r\n *\r\n * @public\r\n */\r\n static getPresetResponseByIndex(index: number) {\r\n return SUBSURFACE_PROFILE_PRESET_RESPONSE[this.getPresetNameByIndex(index)] ?? [0, 0, 0, 0];\r\n }\r\n\r\n /**\r\n * Computes the effective tint bias from the preset and current profile settings.\r\n *\r\n * @returns The derived RGB tint bias used for transmission tinting.\r\n *\r\n * @public\r\n */\r\n getDerivedTintBias(): [number, number, number] {\r\n const base = SUBSURFACE_PROFILE_PRESET_TINT_BIAS[this._preset] ?? [1, 1, 1];\r\n const factors = this.getDerivedProfileFactors();\r\n const derived: [number, number, number] = [\r\n this.clamp01(0.78 + factors.warmBias * 0.26 - factors.coolBias * 0.16 + factors.boundaryNorm * 0.04),\r\n this.clamp01(\r\n 0.3 +\r\n factors.meanFreePathColor[1] * 0.24 +\r\n factors.transmissionTintColor[1] * 0.28 +\r\n factors.distanceNorm * 0.08 +\r\n factors.scaleNorm * 0.05 +\r\n factors.boundaryNorm * 0.08 +\r\n factors.coolBias * 0.06\r\n ),\r\n this.clamp01(\r\n 0.14 +\r\n factors.meanFreePathColor[2] * 0.22 +\r\n factors.transmissionTintColor[2] * 0.32 +\r\n factors.distanceNorm * 0.06 +\r\n factors.boundaryNorm * 0.06 +\r\n factors.coolBias * 0.12 -\r\n factors.warmBias * 0.06\r\n )\r\n ];\r\n const blend = this.clampRange(\r\n 0.26 + factors.radiusNorm * 0.16 + factors.scaleNorm * 0.1 + factors.strengthNorm * 0.08,\r\n 0.25,\r\n 0.88\r\n );\r\n return [\r\n this.mixNumber(base[0], derived[0], blend),\r\n this.mixNumber(base[1], derived[1], blend),\r\n this.mixNumber(base[2], derived[2], blend)\r\n ];\r\n }\r\n\r\n /**\r\n * Computes the effective transmission response from the preset and current profile settings.\r\n *\r\n * @returns The derived transmission response packed as four scalar channels.\r\n *\r\n * @public\r\n */\r\n getDerivedTransmissionResponse(): [number, number, number, number] {\r\n const base = SUBSURFACE_PROFILE_PRESET_RESPONSE[this._preset] ?? [0, 0, 0, 0];\r\n const factors = this.getDerivedProfileFactors();\r\n const blend = this.clampRange(\r\n 0.32 +\r\n factors.distanceNorm * 0.18 +\r\n factors.scaleNorm * 0.12 +\r\n factors.strengthNorm * 0.1 +\r\n factors.boundaryNorm * 0.06,\r\n 0.28,\r\n 0.9\r\n );\r\n const derived: [number, number, number, number] = [\r\n this.clampRange(\r\n -0.06 +\r\n factors.radiusNorm * 0.08 +\r\n factors.distanceNorm * 0.08 +\r\n factors.strengthNorm * 0.05 +\r\n factors.distributionNorm * 0.04 +\r\n factors.boundaryNorm * 0.05 +\r\n factors.extinctionSoftness * 0.03,\r\n -0.25,\r\n 0.45\r\n ),\r\n this.clampRange(\r\n 0.02 +\r\n factors.radiusNorm * 0.1 +\r\n factors.scaleNorm * 0.08 +\r\n factors.worldScaleNorm * 0.04 +\r\n factors.distributionNorm * 0.08 +\r\n factors.extinctionSoftness * 0.06,\r\n -0.25,\r\n 0.45\r\n ),\r\n this.clampRange(\r\n -0.08 +\r\n factors.strengthNorm * 0.12 +\r\n factors.scaleNorm * 0.08 +\r\n factors.extinctionSoftness * 0.12 +\r\n factors.boundaryNorm * 0.06 +\r\n factors.warmBias * 0.05 -\r\n factors.coolBias * 0.04,\r\n -0.25,\r\n 0.45\r\n ),\r\n this.clampRange(\r\n -0.02 +\r\n factors.radiusNorm * 0.12 +\r\n factors.scaleNorm * 0.08 +\r\n factors.strengthNorm * 0.06 +\r\n factors.boundaryNorm * 0.06 +\r\n factors.extinctionSoftness * 0.16 +\r\n factors.warmBias * 0.07 +\r\n factors.transmissionTintColor[0] * 0.04,\r\n -0.25,\r\n 0.5\r\n )\r\n ];\r\n return [\r\n this.clampRange(this.mixNumber(base[0], derived[0], blend), -0.25, 0.45),\r\n this.clampRange(this.mixNumber(base[1], derived[1], blend), -0.25, 0.45),\r\n this.clampRange(this.mixNumber(base[2], derived[2], blend), -0.25, 0.45),\r\n this.clampRange(this.mixNumber(base[3], derived[3], blend), -0.25, 0.5)\r\n ];\r\n }\r\n\r\n /**\r\n * Gets the 1-based profile slot used when encoding this profile into SSS buffers.\r\n *\r\n * @public\r\n */\r\n get slot() {\r\n return this._slot;\r\n }\r\n\r\n /**\r\n * Gets or sets the RGB scatter radius.\r\n *\r\n * @remarks\r\n * Assigning a radius also updates the mean-free-path authoring controls.\r\n *\r\n * @public\r\n */\r\n get scatterRadius(): Immutable<Vector3> {\r\n return this._scatterRadius;\r\n }\r\n\r\n set scatterRadius(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._scatterRadius)) {\r\n this._scatterRadius.set(val);\r\n this.syncMeanFreePathFromScatterRadius();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the channel falloff color used by the diffusion kernel.\r\n *\r\n * @public\r\n */\r\n get falloffColor(): Immutable<Vector3> {\r\n return this._falloffColor;\r\n }\r\n\r\n set falloffColor(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._falloffColor)) {\r\n this._falloffColor.set(val);\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Mean free path color used to derive channel-dependent scatter radius.\r\n *\r\n * @remarks\r\n * This is a more UE-like authoring control that keeps the existing radius-\r\n * based implementation, while letting tools expose a color + distance pair.\r\n *\r\n * @public\r\n */\r\n get meanFreePathColor(): Immutable<Vector3> {\r\n return this._meanFreePathColor;\r\n }\r\n\r\n set meanFreePathColor(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._meanFreePathColor)) {\r\n this._meanFreePathColor.set(val);\r\n this.syncScatterRadiusFromMeanFreePath();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the mean free path distance used to derive the absolute scatter radius.\r\n *\r\n * @public\r\n */\r\n get meanFreePathDistance() {\r\n return this._meanFreePathDistance;\r\n }\r\n\r\n set meanFreePathDistance(val: number) {\r\n const next = Math.max(0, val ?? 0);\r\n if (next !== this._meanFreePathDistance) {\r\n this._meanFreePathDistance = next;\r\n this.syncScatterRadiusFromMeanFreePath();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the active subsurface profile preset.\r\n *\r\n * @remarks\r\n * Assigning a preset applies its template values to the profile. Alias preset\r\n * names are resolved to their canonical preset.\r\n *\r\n * @public\r\n */\r\n get preset() {\r\n return this._preset;\r\n }\r\n\r\n set preset(val: SubsurfaceProfilePreset) {\r\n const next = SubsurfaceProfile.resolvePreset(val);\r\n if (next !== this._preset) {\r\n this._preset = next;\r\n this.applyPresetTemplate(next);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the packed canonical preset index.\r\n *\r\n * @public\r\n */\r\n get presetIndex() {\r\n return SUBSURFACE_PROFILE_PRESET_INDEX[this._preset] ?? 0;\r\n }\r\n\r\n /**\r\n * Gets or sets the SSS strength multiplier.\r\n *\r\n * @public\r\n */\r\n get strength() {\r\n return this._strength;\r\n }\r\n\r\n set strength(val: number) {\r\n if (val !== this._strength) {\r\n this._strength = val;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the screen-space scatter width scale.\r\n *\r\n * @public\r\n */\r\n get scale() {\r\n return this._scale;\r\n }\r\n\r\n set scale(val: number) {\r\n if (val !== this._scale) {\r\n this._scale = val;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the world-unit scale used when converting profile radii.\r\n *\r\n * @public\r\n */\r\n get worldUnitScale() {\r\n return this._worldUnitScale;\r\n }\r\n\r\n set worldUnitScale(val: number) {\r\n const next = Math.max(0.05, val ?? 0.05);\r\n if (next !== this._worldUnitScale) {\r\n this._worldUnitScale = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the amount of color bleeding preserved near SSS boundaries.\r\n *\r\n * @remarks\r\n * Values are clamped to the `[0, 1]` range.\r\n *\r\n * @public\r\n */\r\n get boundaryColorBleed() {\r\n return this._boundaryColorBleed;\r\n }\r\n\r\n set boundaryColorBleed(val: number) {\r\n const next = this.clamp01(val ?? 0);\r\n if (next !== this._boundaryColorBleed) {\r\n this._boundaryColorBleed = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the RGB tint applied to transmitted subsurface light.\r\n *\r\n * @public\r\n */\r\n get transmissionTintColor(): Immutable<Vector3> {\r\n return this._transmissionTintColor;\r\n }\r\n\r\n set transmissionTintColor(val: Immutable<Vector3>) {\r\n if (!val.equalsTo(this._transmissionTintColor)) {\r\n this._transmissionTintColor.set(val);\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the extinction multiplier used by transmission attenuation.\r\n *\r\n * @remarks\r\n * Values are clamped to zero or greater.\r\n *\r\n * @public\r\n */\r\n get extinctionScale() {\r\n return this._extinctionScale;\r\n }\r\n\r\n set extinctionScale(val: number) {\r\n const next = Math.max(0, val ?? 0);\r\n if (next !== this._extinctionScale) {\r\n this._extinctionScale = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the normal sensitivity scale used by SSS filtering.\r\n *\r\n * @remarks\r\n * Values are clamped to zero or greater.\r\n *\r\n * @public\r\n */\r\n get normalScale() {\r\n return this._normalScale;\r\n }\r\n\r\n set normalScale(val: number) {\r\n const next = Math.max(0, val ?? 0);\r\n if (next !== this._normalScale) {\r\n this._normalScale = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /**\r\n * Gets or sets the scattering distribution blend.\r\n *\r\n * @remarks\r\n * Values are clamped to the `[0, 1]` range.\r\n *\r\n * @public\r\n */\r\n get scatteringDistribution() {\r\n return this._scatteringDistribution;\r\n }\r\n\r\n set scatteringDistribution(val: number) {\r\n const next = this.clamp01(val ?? 0);\r\n if (next !== this._scatteringDistribution) {\r\n this._scatteringDistribution = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /** Strength of the screen-space filter applied to normal-driven specular detail. */\r\n get specularDetailSoftness() {\r\n return this._specularDetailSoftness;\r\n }\r\n\r\n set specularDetailSoftness(val: number) {\r\n const next = this.clamp01(val ?? 0);\r\n if (next !== this._specularDetailSoftness) {\r\n this._specularDetailSoftness = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n /** Radius in screen pixels used to soften normal-driven specular detail. */\r\n get specularDetailRadius() {\r\n return this._specularDetailRadius;\r\n }\r\n\r\n set specularDetailRadius(val: number) {\r\n const next = this.clampRange(val ?? 0, 0, 4);\r\n if (next !== this._specularDetailRadius) {\r\n this._specularDetailRadius = next;\r\n this.markDirty();\r\n }\r\n }\r\n\r\n addChangeListener(listener: () => void) {\r\n this._changeListeners.add(listener);\r\n }\r\n\r\n /**\r\n * Removes a previously registered profile change listener.\r\n *\r\n * @param listener - The callback to remove.\r\n *\r\n * @public\r\n */\r\n removeChangeListener(listener: () => void) {\r\n this._changeListeners.delete(listener);\r\n }\r\n\r\n private static allocateSlot(profile: SubsurfaceProfile) {\r\n for (let i = 1; i < this._profiles.length; i++) {\r\n if (!this._profiles[i]) {\r\n this._profiles[i] = profile;\r\n this._version++;\r\n return i;\r\n }\r\n }\r\n throw new Error('SubsurfaceProfile limit exceeded');\r\n }\r\n\r\n private static releaseSlot(slot: number, profile: SubsurfaceProfile) {\r\n if (slot > 0 && slot < this._profiles.length && this._profiles[slot] === profile) {\r\n this._profiles[slot] = null;\r\n this._version++;\r\n }\r\n }\r\n\r\n private markDirty() {\r\n SubsurfaceProfile._version++;\r\n this._changeListeners.forEach((listener) => listener());\r\n }\r\n\r\n private static resolvePreset(preset: SubsurfaceProfilePreset | null | undefined) {\r\n return SUBSURFACE_PROFILE_PRESET_ALIAS[preset ?? 'skin_default'] ?? 'skin_default';\r\n }\r\n\r\n private static getPresetNameByIndex(index: number): CanonicalSubsurfaceProfilePreset {\r\n for (const [name, presetIndex] of Object.entries(SUBSURFACE_PROFILE_PRESET_INDEX) as Array<\r\n [CanonicalSubsurfaceProfilePreset, number]\r\n >) {\r\n if (presetIndex === index) {\r\n return name;\r\n }\r\n }\r\n return 'skin_default';\r\n }\r\n\r\n private applyPresetTemplate(preset: CanonicalSubsurfaceProfilePreset, markDirty = true) {\r\n const template =\r\n SUBSURFACE_PROFILE_PRESET_TEMPLATE[preset] ?? SUBSURFACE_PROFILE_PRESET_TEMPLATE.skin_default;\r\n this._meanFreePathColor.setXYZ(\r\n template.meanFreePathColor[0],\r\n template.meanFreePathColor[1],\r\n template.meanFreePathColor[2]\r\n );\r\n this._meanFreePathDistance = template.meanFreePathDistance;\r\n this._strength = template.strength;\r\n this._scale = template.scale;\r\n this._worldUnitScale = template.worldUnitScale;\r\n this._boundaryColorBleed = template.boundaryColorBleed;\r\n this._transmissionTintColor.setXYZ(\r\n template.transmissionTintColor[0],\r\n template.transmissionTintColor[1],\r\n template.transmissionTintColor[2]\r\n );\r\n this._extinctionScale = template.extinctionScale;\r\n this._normalScale = template.normalScale;\r\n this._scatteringDistribution = template.scatteringDistribution;\r\n this._specularDetailSoftness = template.specularDetailSoftness;\r\n this._specularDetailRadius = template.specularDetailRadius;\r\n this.syncScatterRadiusFromMeanFreePath(false);\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private syncMeanFreePathFromScatterRadius(markDirty = true) {\r\n const maxRadius = Math.max(this._scatterRadius.x, this._scatterRadius.y, this._scatterRadius.z);\r\n if (maxRadius > 1e-5) {\r\n this._meanFreePathDistance = maxRadius;\r\n this._meanFreePathColor.setXYZ(\r\n this._scatterRadius.x / maxRadius,\r\n this._scatterRadius.y / maxRadius,\r\n this._scatterRadius.z / maxRadius\r\n );\r\n } else {\r\n this._meanFreePathDistance = 0;\r\n this._meanFreePathColor.setXYZ(0, 0, 0);\r\n }\r\n this.syncFalloffFromMeanFreePath(false);\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private syncScatterRadiusFromMeanFreePath(markDirty = true) {\r\n const distance = Math.max(0, this._meanFreePathDistance);\r\n this._scatterRadius.setXYZ(\r\n Math.max(0, this._meanFreePathColor.x) * distance,\r\n Math.max(0, this._meanFreePathColor.y) * distance,\r\n Math.max(0, this._meanFreePathColor.z) * distance\r\n );\r\n this.syncFalloffFromMeanFreePath(false);\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private syncFalloffFromMeanFreePath(markDirty = true) {\r\n const base =\r\n SUBSURFACE_PROFILE_PRESET_TEMPLATE[this._preset]?.falloffColor ??\r\n SUBSURFACE_PROFILE_PRESET_TEMPLATE.skin_default.falloffColor;\r\n const factors = this.getDerivedProfileFactors();\r\n const derivedG = this.clamp01(\r\n 0.12 +\r\n factors.meanFreePathColor[1] * 0.4 +\r\n factors.transmissionTintColor[1] * 0.12 +\r\n factors.distanceNorm * 0.05 +\r\n factors.scaleNorm * 0.05 +\r\n factors.distributionNorm * 0.05 -\r\n (1 - factors.extinctionSoftness) * 0.04\r\n );\r\n const derivedB = this.clamp01(\r\n 0.04 +\r\n factors.meanFreePathColor[2] * 0.32 +\r\n factors.transmissionTintColor[2] * 0.18 +\r\n factors.distanceNorm * 0.04 +\r\n factors.boundaryNorm * 0.05 +\r\n factors.coolBias * 0.08 -\r\n factors.warmBias * 0.04\r\n );\r\n const blend = this.clampRange(\r\n 0.24 + factors.distanceNorm * 0.16 + factors.scaleNorm * 0.12 + factors.strengthNorm * 0.08,\r\n 0.22,\r\n 0.82\r\n );\r\n this._falloffColor.setXYZ(\r\n 1,\r\n this.mixNumber(base[1], derivedG, blend),\r\n this.mixNumber(base[2], derivedB, blend)\r\n );\r\n if (markDirty) {\r\n this.markDirty();\r\n }\r\n }\r\n\r\n private getNormalizedTransmissionTintColor(): [number, number, number] {\r\n const maxChannel = Math.max(\r\n this._transmissionTintColor.x,\r\n this._transmissionTintColor.y,\r\n this._transmissionTintColor.z,\r\n 1e-5\r\n );\r\n return [\r\n Math.max(0, this._transmissionTintColor.x) / maxChannel,\r\n Math.max(0, this._transmissionTintColor.y) / maxChannel,\r\n Math.max(0, this._transmissionTintColor.z) / maxChannel\r\n ];\r\n }\r\n\r\n private getDerivedProfileFactors() {\r\n const meanFreePathColor = this.getNormalizedMeanFreePathColor();\r\n const transmissionTintColor = this.getNormalizedTransmissionTintColor();\r\n const maxRadius = Math.max(this._scatterRadius.x, this._scatterRadius.y, this._scatterRadius.z);\r\n const radiusNorm = this.clampRange(maxRadius / 1.35, 0, 1.5);\r\n const distanceNorm = this.clampRange(this._meanFreePathDistance / 1.25, 0, 1.5);\r\n const scaleNorm = this.clampRange(this._scale / 1.35, 0, 1.5);\r\n const strengthNorm = this.clampRange(this._strength / 1.2, 0, 1.5);\r\n const worldScaleNorm = this.clampRange(this._worldUnitScale / 1.25, 0, 1.5);\r\n const boundaryNorm = this.clamp01(this._boundaryColorBleed);\r\n const distributionNorm = this.clamp01(this._scatteringDistribution);\r\n const extinctionWeight = this.clampRange(1 / Math.max(this._extinctionScale, 0.35), 0.25, 1.35);\r\n const extinctionSoftness = this.clamp01((extinctionWeight - 0.25) / 1.1);\r\n const warmBias = this.clamp01(\r\n 0.5 +\r\n (meanFreePathColor[0] - Math.max(meanFreePathColor[1], meanFreePathColor[2]) * 0.72) * 0.95 +\r\n (transmissionTintColor[0] - Math.max(transmissionTintColor[1], transmissionTintColor[2]) * 0.78) * 0.7\r\n );\r\n const coolBias = this.clamp01(\r\n 0.32 +\r\n (transmissionTintColor[2] - transmissionTintColor[0] * 0.55) * 0.55 +\r\n (meanFreePathColor[2] - meanFreePathColor[0] * 0.65) * 0.45\r\n );\r\n return {\r\n meanFreePathColor,\r\n transmissionTintColor,\r\n radiusNorm,\r\n distanceNorm,\r\n scaleNorm,\r\n strengthNorm,\r\n worldScaleNorm,\r\n boundaryNorm,\r\n distributionNorm,\r\n extinctionSoftness,\r\n warmBias,\r\n coolBias\r\n };\r\n }\r\n\r\n private getNormalizedMeanFreePathColor(): [number, number, number] {\r\n const maxChannel = Math.max(\r\n this._meanFreePathColor.x,\r\n this._meanFreePathColor.y,\r\n this._meanFreePathColor.z,\r\n 1e-5\r\n );\r\n return [\r\n Math.max(0, this._meanFreePathColor.x) / maxChannel,\r\n Math.max(0, this._meanFreePathColor.y) / maxChannel,\r\n Math.max(0, this._meanFreePathColor.z) / maxChannel\r\n ];\r\n }\r\n\r\n private mixNumber(a: number, b: number, t: number) {\r\n return a * (1 - t) + b * t;\r\n }\r\n\r\n private clampRange(value: number, minValue: number, maxValue: number) {\r\n return Math.max(minValue, Math.min(maxValue, value));\r\n }\r\n\r\n private clamp01(value: number) {\r\n return Math.max(0, Math.min(1, value));\r\n }\r\n}\r\n"],"names":["SUBSURFACE_PROFILE_PRESET_ALIAS","skin","skin_thin","skin_default","skin_heavy_makeup","wax","wax_backlit","wax_soft","jade","jade_backlit","jade_soft","SUBSURFACE_PROFILE_PRESET_INDEX","SUBSURFACE_PROFILE_PRESET_TEMPLATE","meanFreePathColor","meanFreePathDistance","falloffColor","strength","scale","worldUnitScale","boundaryColorBleed","transmissionTintColor","extinctionScale","normalScale","scatteringDistribution","specularDetailSoftness","specularDetailRadius","SUBSURFACE_PROFILE_PRESET_TINT_BIAS","SUBSURFACE_PROFILE_PRESET_RESPONSE","SubsurfaceProfile","_maxProfiles","_profiles","Array","fill","_version","_defaultSkinProfile","_scatterRadius","_falloffColor","_meanFreePathColor","_transmissionTintColor","_preset","_meanFreePathDistance","_strength","_scale","_worldUnitScale","_boundaryColorBleed","_extinctionScale","_normalScale","_scatteringDistribution","_specularDetailSoftness","_specularDetailRadius","_slot","_changeListeners","_disposed","Vector3","Set","allocateSlot","applyPresetTemplate","clone","other","copyFrom","preset","dispose","clear","releaseSlot","version","getProfileBySlot","slot","length","getDefaultSkinProfile","getPresetTintBiasByIndex","index","getPresetNameByIndex","getPresetResponseByIndex","getDerivedTintBias","base","factors","getDerivedProfileFactors","derived","clamp01","warmBias","coolBias","boundaryNorm","distanceNorm","scaleNorm","blend","clampRange","radiusNorm","strengthNorm","mixNumber","getDerivedTransmissionResponse","distributionNorm","extinctionSoftness","worldScaleNorm","scatterRadius","val","equalsTo","set","syncMeanFreePathFromScatterRadius","markDirty","syncScatterRadiusFromMeanFreePath","next","Math","max","resolvePreset","presetIndex","addChangeListener","listener","add","removeChangeListener","delete","profile","i","Error","forEach","name","Object","entries","template","setXYZ","maxRadius","x","y","z","syncFalloffFromMeanFreePath","distance","derivedG","derivedB","getNormalizedTransmissionTintColor","maxChannel","getNormalizedMeanFreePathColor","extinctionWeight","a","b","t","value","minValue","maxValue","min"],"mappings":"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"}
@@ -323,7 +323,9 @@ class WaterMaterial extends applyMaterialMixins(MeshMaterial, mixinLight) {
323
323
  this.$l.NoL = pb.clamp(pb.dot(this.normal, this.lightDir), 0, 1);
324
324
  this.$l.lightContrib = this.lightSpecular(this.lightDir, this.eyeVecNorm, this.normal, pb.mul(colorIntensity.rgb, colorIntensity.a, this.lightAtten));
325
325
  if (shadow) {
326
- this.$l.shadow = pb.vec3(that.calculateShadow(this, this.worldPos, this.NoL));
326
+ // Water is a horizontal clipmap, so +Y is the geometric normal. The
327
+ // wave normal would jitter the shadow lookup per-pixel.
328
+ this.$l.shadow = pb.vec3(that.calculateShadow(this, this.worldPos, pb.vec3(0, 1, 0), this.NoL));
327
329
  this.lightContrib = pb.mul(this.lightContrib, this.shadow);
328
330
  }
329
331
  this.finalColor = pb.add(this.finalColor, this.lightContrib);