@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
@@ -5,16 +5,20 @@ import { UnlitMaterial } from '../../../material/unlit.js';
5
5
  import { ParticleMaterial } from '../../../material/particle.js';
6
6
  import { SubsurfaceProfile } from '../../../material/subsurfaceprofile.js';
7
7
  import { SkinMaterial } from '../../../material/skin.js';
8
+ import { EyeMaterial } from '../../../material/eye.js';
8
9
  import '@zephyr3d/device';
9
10
  import '../../../values.js';
10
11
  import { Vector3, Vector4, Vector2 } from '@zephyr3d/base';
11
12
  import { MeshMaterial } from '../../../material/meshmaterial.js';
13
+ import { HairMaterial } from '../../../material/hair.js';
14
+ import '../../../material/hairstrand.js';
12
15
  import '../../../material/grassmaterial.js';
13
16
  import '../../../material/terrain-cm.js';
14
17
  import { PBRMetallicRoughnessMaterial } from '../../../material/pbrmr.js';
15
18
  import { PBRSpecularGlossinessMaterial } from '../../../material/pbrsg.js';
16
19
  import { MToonMaterial } from '../../../material/mtoon.js';
17
20
  import { PBRBluePrintMaterial } from '../../../material/pbrblueprint.js';
21
+ import { PBRBluePrintMaterialInstance } from '../../../material/pbrblueprint_instance.js';
18
22
  import { SpriteMaterial } from '../../../material/sprite.js';
19
23
  import { StandardSpriteMaterial } from '../../../material/sprite_std.js';
20
24
  import { SpriteBlueprintMaterial } from '../../../material/spriteblueprint.js';
@@ -26,6 +30,27 @@ function createBlueprintOutputHiddenPredicate(_outputs) {
26
30
  return this instanceof PBRBluePrintMaterial;
27
31
  };
28
32
  }
33
+ function canEditParentMaterialProperty(material) {
34
+ return !material.$isInstance && !material.isBlueprintMaterialInstance;
35
+ }
36
+ function isBlueprintMaterialAssetInstanceWithInheritedParentProps(material) {
37
+ return !!material.isBlueprintMaterialInstance;
38
+ }
39
+ function isBlueprintMaterialAssetInstance(material) {
40
+ return !!material.isBlueprintMaterialInstance;
41
+ }
42
+ function allowBlueprintInstanceOverride(material, propName, setter) {
43
+ setter();
44
+ if (isBlueprintMaterialAssetInstance(material)) {
45
+ material.markMaterialPropertyOverridden?.(propName);
46
+ }
47
+ }
48
+ function canEditBlueprintInstanceSubsurfaceProfile(material) {
49
+ return !!material.subsurfaceProfile && !!material.isBlueprintMaterialInstance;
50
+ }
51
+ function getBlueprintInstanceSubsurfaceMaterial(material) {
52
+ return material;
53
+ }
29
54
  function getSubsurfaceProfileClass() {
30
55
  return {
31
56
  ctor: SubsurfaceProfile,
@@ -247,6 +272,40 @@ function getSubsurfaceProfileClass() {
247
272
  set (value) {
248
273
  this.scatteringDistribution = value.num[0];
249
274
  }
275
+ },
276
+ {
277
+ name: 'SpecularDetailSoftness',
278
+ type: 'float',
279
+ default: 0.78,
280
+ options: {
281
+ label: 'SpecularDetailSoftness',
282
+ animatable: true,
283
+ minValue: 0,
284
+ maxValue: 1
285
+ },
286
+ get (value) {
287
+ value.num[0] = this.specularDetailSoftness;
288
+ },
289
+ set (value) {
290
+ this.specularDetailSoftness = value.num[0];
291
+ }
292
+ },
293
+ {
294
+ name: 'SpecularDetailRadius',
295
+ type: 'float',
296
+ default: 1.8,
297
+ options: {
298
+ label: 'SpecularDetailRadius',
299
+ animatable: true,
300
+ minValue: 0,
301
+ maxValue: 4
302
+ },
303
+ get (value) {
304
+ value.num[0] = this.specularDetailRadius;
305
+ },
306
+ set (value) {
307
+ this.specularDetailRadius = value.num[0];
308
+ }
250
309
  }
251
310
  ]);
252
311
  }
@@ -254,7 +313,7 @@ function getSubsurfaceProfileClass() {
254
313
  }
255
314
  function getPBRCommonProps(manager) {
256
315
  const supportsSSSThicknessAuthoring = function() {
257
- return !this.$isInstance && !!(this.transmission || this.subsurfaceProfile);
316
+ return (!this.$isInstance || isBlueprintMaterialAssetInstance(this)) && !!(this.transmission || this.subsurfaceProfile);
258
317
  };
259
318
  return defineProps([
260
319
  {
@@ -400,6 +459,9 @@ function getPBRCommonProps(manager) {
400
459
  this.rectSpecularScale = value.num[0];
401
460
  },
402
461
  getDefaultValue () {
462
+ if (this instanceof PBRBluePrintMaterialInstance) {
463
+ return this.parentMaterial?.rectSpecularScale ?? 1;
464
+ }
403
465
  return this.$isInstance ? this.coreMaterial.rectSpecularScale : 1;
404
466
  }
405
467
  },
@@ -419,10 +481,12 @@ function getPBRCommonProps(manager) {
419
481
  value.bool[0] = this.transmission;
420
482
  },
421
483
  set (value) {
422
- this.transmission = value.bool[0];
484
+ allowBlueprintInstanceOverride(this, 'Transmission', ()=>{
485
+ this.transmission = value.bool[0];
486
+ });
423
487
  },
424
488
  isValid () {
425
- return !this.$isInstance;
489
+ return !this.$isInstance || isBlueprintMaterialAssetInstance(this);
426
490
  }
427
491
  },
428
492
  {
@@ -430,7 +494,7 @@ function getPBRCommonProps(manager) {
430
494
  description: 'Amount of transmitted light, from fully opaque to fully transparent',
431
495
  type: 'float',
432
496
  phase: 1,
433
- default: 0,
497
+ default: 0.2,
434
498
  options: {
435
499
  animatable: true,
436
500
  minValue: 0,
@@ -440,7 +504,12 @@ function getPBRCommonProps(manager) {
440
504
  value.num[0] = this.transmissionFactor;
441
505
  },
442
506
  set (value) {
443
- this.transmissionFactor = value.num[0];
507
+ allowBlueprintInstanceOverride(this, 'TransmissionFactor', ()=>{
508
+ this.transmissionFactor = value.num[0];
509
+ });
510
+ },
511
+ getDefaultValue () {
512
+ return this.$isInstance ? this.coreMaterial.transmissionFactor : 0.2;
444
513
  },
445
514
  isValid () {
446
515
  return supportsSSSThicknessAuthoring.call(this);
@@ -454,7 +523,7 @@ function getPBRCommonProps(manager) {
454
523
  description: 'Physical thickness used by transmission and volume attenuation',
455
524
  type: 'float',
456
525
  phase: 1,
457
- default: 0,
526
+ default: 0.35,
458
527
  options: {
459
528
  animatable: true,
460
529
  minValue: 0,
@@ -464,7 +533,12 @@ function getPBRCommonProps(manager) {
464
533
  value.num[0] = this.thicknessFactor;
465
534
  },
466
535
  set (value) {
467
- this.thicknessFactor = value.num[0];
536
+ allowBlueprintInstanceOverride(this, 'ThicknessFactor', ()=>{
537
+ this.thicknessFactor = value.num[0];
538
+ });
539
+ },
540
+ getDefaultValue () {
541
+ return this.$isInstance ? this.coreMaterial.thicknessFactor : 0.35;
468
542
  },
469
543
  isValid () {
470
544
  return supportsSSSThicknessAuthoring.call(this);
@@ -480,8 +554,8 @@ function getPBRCommonProps(manager) {
480
554
  phase: 1,
481
555
  default: [
482
556
  1,
483
- 1,
484
- 1
557
+ 0.5,
558
+ 0.4
485
559
  ],
486
560
  options: {
487
561
  animatable: true
@@ -492,7 +566,16 @@ function getPBRCommonProps(manager) {
492
566
  value.num[2] = this.attenuationColor.z;
493
567
  },
494
568
  set (value) {
495
- this.attenuationColor = new Vector3(value.num[0], value.num[1], value.num[2]);
569
+ allowBlueprintInstanceOverride(this, 'AttenuationColor', ()=>{
570
+ this.attenuationColor = new Vector3(value.num[0], value.num[1], value.num[2]);
571
+ });
572
+ },
573
+ getDefaultValue () {
574
+ return this.$isInstance ? this.coreMaterial.attenuationColor : [
575
+ 1,
576
+ 0.5,
577
+ 0.4
578
+ ];
496
579
  },
497
580
  isValid () {
498
581
  return supportsSSSThicknessAuthoring.call(this);
@@ -503,7 +586,7 @@ function getPBRCommonProps(manager) {
503
586
  description: 'Distance over which transmitted light is attenuated inside the material',
504
587
  type: 'float',
505
588
  phase: 1,
506
- default: 99999,
589
+ default: 0.6,
507
590
  options: {
508
591
  animatable: true,
509
592
  minValue: 0,
@@ -513,7 +596,12 @@ function getPBRCommonProps(manager) {
513
596
  value.num[0] = this.attenuationDistance;
514
597
  },
515
598
  set (value) {
516
- this.attenuationDistance = value.num[0];
599
+ allowBlueprintInstanceOverride(this, 'AttenuationDistance', ()=>{
600
+ this.attenuationDistance = value.num[0];
601
+ });
602
+ },
603
+ getDefaultValue () {
604
+ return this.$isInstance ? this.coreMaterial.attenuationDistance : 0.6;
517
605
  },
518
606
  isValid () {
519
607
  return supportsSSSThicknessAuthoring.call(this);
@@ -636,7 +724,7 @@ function getPBRCommonProps(manager) {
636
724
  this.clearcoat = value.bool[0];
637
725
  },
638
726
  isValid () {
639
- return !this.$isInstance;
727
+ return !this.$isInstance && !isBlueprintMaterialAssetInstanceWithInheritedParentProps(this);
640
728
  }
641
729
  },
642
730
  {
@@ -657,11 +745,11 @@ function getPBRCommonProps(manager) {
657
745
  this.clearcoatIntensity = value.num[0];
658
746
  },
659
747
  isValid () {
660
- return !this.$isInstance && !!this.clearcoat;
748
+ return !this.$isInstance && !isBlueprintMaterialAssetInstanceWithInheritedParentProps(this) && !!this.clearcoat;
661
749
  }
662
750
  },
663
751
  ...getTextureProps(manager, 'clearcoatIntensityTexture', '2D', false, 1, function() {
664
- return this.clearcoat;
752
+ return !isBlueprintMaterialAssetInstanceWithInheritedParentProps(this) && this.clearcoat;
665
753
  }),
666
754
  {
667
755
  name: 'ClearCoatRoughnessFactor',
@@ -681,14 +769,14 @@ function getPBRCommonProps(manager) {
681
769
  this.clearcoatRoughnessFactor = value.num[0];
682
770
  },
683
771
  isValid () {
684
- return !this.$isInstance && !!this.clearcoat;
772
+ return !this.$isInstance && !isBlueprintMaterialAssetInstanceWithInheritedParentProps(this) && !!this.clearcoat;
685
773
  }
686
774
  },
687
775
  ...getTextureProps(manager, 'clearcoatRoughnessTexture', '2D', false, 1, function() {
688
- return this.clearcoat;
776
+ return !isBlueprintMaterialAssetInstanceWithInheritedParentProps(this) && this.clearcoat;
689
777
  }),
690
778
  ...getTextureProps(manager, 'clearcoatNormalTexture', '2D', false, 1, function() {
691
- return this.clearcoat;
779
+ return !isBlueprintMaterialAssetInstanceWithInheritedParentProps(this) && this.clearcoat;
692
780
  }),
693
781
  {
694
782
  name: 'Sheen',
@@ -764,40 +852,86 @@ function getPBRCommonProps(manager) {
764
852
  function getLitMaterialProps(manager) {
765
853
  return defineProps([
766
854
  ...getUnlitMaterialProps(manager),
767
- {
768
- name: 'doubleSidedLighting',
769
- description: 'If true, lighting is evaluated on both sides of the surface',
770
- type: 'bool',
771
- default: true,
772
- isValid () {
773
- return !this.$isInstance;
774
- },
775
- get (value) {
776
- value.bool[0] = this.doubleSidedLighting;
777
- },
778
- set (value) {
779
- this.doubleSidedLighting = value.bool[0];
780
- }
781
- },
782
855
  {
783
856
  name: 'NormalScale',
784
- description: 'Scalar applied to the normal texture',
857
+ description: 'Strength multiplier for normal map X and Y components',
785
858
  type: 'float',
786
- phase: 1,
787
859
  default: 1,
788
860
  options: {
789
861
  animatable: true,
790
862
  minValue: 0,
791
- maxValue: 2
863
+ maxValue: 3
792
864
  },
793
865
  get (value) {
794
866
  value.num[0] = this.normalScale;
795
867
  },
796
868
  set (value) {
797
- this.normalScale = value.num[0];
869
+ allowBlueprintInstanceOverride(this, 'NormalScale', ()=>{
870
+ this.normalScale = value.num[0];
871
+ });
872
+ },
873
+ isHidden: createBlueprintOutputHiddenPredicate(),
874
+ getDefaultValue () {
875
+ if (this instanceof PBRBluePrintMaterialInstance) {
876
+ return this.parentMaterial?.normalScale ?? 1;
877
+ }
878
+ return this.$isInstance ? this.coreMaterial.normalScale : 1;
798
879
  },
799
880
  isValid () {
800
- return !this.$isInstance && !!this.normalTexture;
881
+ return !this.$isInstance || isBlueprintMaterialAssetInstance(this);
882
+ }
883
+ },
884
+ {
885
+ name: 'NormalFlipY',
886
+ description: 'If true, flips the green (Y) component sampled from the normal map',
887
+ type: 'bool',
888
+ default: false,
889
+ get (value) {
890
+ value.bool[0] = this.normalFlipY;
891
+ },
892
+ set (value) {
893
+ allowBlueprintInstanceOverride(this, 'NormalFlipY', ()=>{
894
+ this.normalFlipY = value.bool[0];
895
+ });
896
+ },
897
+ isHidden: createBlueprintOutputHiddenPredicate(),
898
+ getDefaultValue () {
899
+ if (this instanceof PBRBluePrintMaterialInstance) {
900
+ return this.parentMaterial?.normalFlipY ?? false;
901
+ }
902
+ return this.$isInstance ? this.coreMaterial.normalFlipY : false;
903
+ },
904
+ isValid () {
905
+ return !this.$isInstance || isBlueprintMaterialAssetInstance(this);
906
+ }
907
+ },
908
+ {
909
+ name: 'doubleSidedLighting',
910
+ description: 'If true, lighting is evaluated on both sides of the surface',
911
+ type: 'bool',
912
+ default: true,
913
+ isValid () {
914
+ return !this.$isInstance;
915
+ },
916
+ get (value) {
917
+ value.bool[0] = this.doubleSidedLighting;
918
+ },
919
+ set (value) {
920
+ allowBlueprintInstanceOverride(this, 'doubleSidedLighting', ()=>{
921
+ this.doubleSidedLighting = value.bool[0];
922
+ });
923
+ },
924
+ getDefaultValue () {
925
+ if (this instanceof PBRBluePrintMaterialInstance) {
926
+ return this.parentMaterial?.doubleSidedLighting ?? true;
927
+ }
928
+ // Must match what the constructor actually sets - mixinLight enables
929
+ // FEATURE_DOUBLE_SIDED_LIGHTING - because this value is used both to
930
+ // decide whether to omit the property when saving and to fill it in
931
+ // when it is absent on load. Returning false here made every asset
932
+ // written before this accessor existed (all of which omitted the key,
933
+ // since true was then the assumed default) load as single-sided.
934
+ return this.$isInstance ? this.coreMaterial.doubleSidedLighting : true;
801
935
  }
802
936
  },
803
937
  {
@@ -1453,7 +1587,7 @@ function getMToonMaterialProps(manager) {
1453
1587
  this.alphaCutoff = value.num[0];
1454
1588
  },
1455
1589
  isValid () {
1456
- return !this.$isInstance;
1590
+ return canEditParentMaterialProperty(this);
1457
1591
  }
1458
1592
  },
1459
1593
  {
@@ -1468,7 +1602,7 @@ function getMToonMaterialProps(manager) {
1468
1602
  this.alphaToCoverage = value.bool[0];
1469
1603
  },
1470
1604
  isValid () {
1471
- return !this.$isInstance;
1605
+ return canEditParentMaterialProperty(this);
1472
1606
  }
1473
1607
  },
1474
1608
  {
@@ -1483,7 +1617,7 @@ function getMToonMaterialProps(manager) {
1483
1617
  this.alphaDither = value.bool[0];
1484
1618
  },
1485
1619
  isValid () {
1486
- return !this.$isInstance && this.alphaCutoff > 0;
1620
+ return canEditParentMaterialProperty(this) && this.alphaCutoff > 0;
1487
1621
  }
1488
1622
  },
1489
1623
  {
@@ -1512,7 +1646,7 @@ function getMToonMaterialProps(manager) {
1512
1646
  this.blendMode = value.str[0];
1513
1647
  },
1514
1648
  isValid () {
1515
- return !this.$isInstance;
1649
+ return canEditParentMaterialProperty(this);
1516
1650
  }
1517
1651
  },
1518
1652
  {
@@ -1526,7 +1660,7 @@ function getMToonMaterialProps(manager) {
1526
1660
  this.transparentShadowCaster = value.bool[0];
1527
1661
  },
1528
1662
  isValid () {
1529
- return !this.$isInstance && this.blendMode !== 'none';
1663
+ return canEditParentMaterialProperty(this) && this.blendMode !== 'none';
1530
1664
  }
1531
1665
  },
1532
1666
  {
@@ -1545,7 +1679,7 @@ function getMToonMaterialProps(manager) {
1545
1679
  this.shadowAlphaCutoff = value.num[0];
1546
1680
  },
1547
1681
  isValid () {
1548
- return !this.$isInstance && this.blendMode !== 'none' && this.transparentShadowCaster;
1682
+ return canEditParentMaterialProperty(this) && this.blendMode !== 'none' && this.transparentShadowCaster;
1549
1683
  }
1550
1684
  },
1551
1685
  {
@@ -1574,7 +1708,7 @@ function getMToonMaterialProps(manager) {
1574
1708
  this.cullMode = value.str[0];
1575
1709
  },
1576
1710
  isValid () {
1577
- return !this.$isInstance;
1711
+ return canEditParentMaterialProperty(this);
1578
1712
  }
1579
1713
  },
1580
1714
  {
@@ -1614,7 +1748,7 @@ function getMToonMaterialProps(manager) {
1614
1748
  this.TAAStrength = value.num[0];
1615
1749
  },
1616
1750
  isValid () {
1617
- return !this.$isInstance;
1751
+ return canEditParentMaterialProperty(this);
1618
1752
  }
1619
1753
  }
1620
1754
  ]);
@@ -1805,6 +1939,19 @@ function getMToonMaterialProps(manager) {
1805
1939
  getMeshMaterialInstanceUniformsClass(PBRBluePrintMaterial)
1806
1940
  ];
1807
1941
  }
1942
+ /** @internal */ function getPBRBluePrintMaterialInstanceClass() {
1943
+ return [
1944
+ {
1945
+ ctor: PBRBluePrintMaterialInstance,
1946
+ parent: PBRBluePrintMaterial,
1947
+ name: 'PBRBluePrintMaterialInstance',
1948
+ getProps () {
1949
+ return defineProps([]);
1950
+ }
1951
+ },
1952
+ getMeshMaterialInstanceUniformsClass(PBRBluePrintMaterialInstance)
1953
+ ];
1954
+ }
1808
1955
  /** @internal */ function getSpriteBlueprintMaterialClass() {
1809
1956
  return [
1810
1957
  {
@@ -1891,207 +2038,1408 @@ function getMToonMaterialProps(manager) {
1891
2038
  getMeshMaterialInstanceUniformsClass(BlinnMaterial)
1892
2039
  ];
1893
2040
  }
1894
- /** @internal */ function getSkinMaterialClass(manager) {
2041
+ /** @internal */ function getHairMaterialClass(manager) {
1895
2042
  return [
1896
2043
  {
1897
- ctor: SkinMaterial,
2044
+ ctor: HairMaterial,
1898
2045
  parent: MeshMaterial,
1899
- name: 'SkinMaterial',
2046
+ name: 'HairMaterial',
1900
2047
  getProps () {
1901
2048
  return defineProps([
1902
2049
  {
1903
- name: 'Shininess',
1904
- description: 'Blinn specular exponent for skin highlights',
1905
- type: 'float',
1906
- default: 72,
2050
+ name: 'ShadingModel',
2051
+ description: 'Which scattering model shades the hair. Marschner derives the lobes from the fibre; Kajiya-Kay is the art-directed double lobe',
2052
+ type: 'string',
2053
+ default: 'kajiya-kay',
1907
2054
  options: {
1908
- animatable: true,
1909
- minValue: 1,
1910
- maxValue: 2048
2055
+ enum: {
2056
+ labels: [
2057
+ 'Kajiya-Kay (double lobe)',
2058
+ 'Marschner (fibre)'
2059
+ ],
2060
+ values: [
2061
+ 'kajiya-kay',
2062
+ 'marschner'
2063
+ ]
2064
+ }
1911
2065
  },
1912
2066
  get (value) {
1913
- value.num[0] = this.shininess;
2067
+ value.str[0] = this.shadingModel;
1914
2068
  },
1915
2069
  set (value) {
1916
- this.shininess = value.num[0];
2070
+ this.shadingModel = value.str[0];
1917
2071
  },
1918
- getDefaultValue () {
1919
- return this.$isInstance ? this.coreMaterial.shininess : 72;
2072
+ isValid () {
2073
+ return !this.$isInstance;
1920
2074
  }
1921
2075
  },
1922
2076
  {
1923
- name: 'SpecularStrength',
1924
- description: 'Direct specular strength for restrained skin highlights',
1925
- type: 'float',
1926
- default: 0.22,
2077
+ name: 'Specular1Color',
2078
+ description: 'Color of the primary (sharp, near-white) specular lobe',
2079
+ type: 'rgb',
2080
+ default: [
2081
+ 0.35,
2082
+ 0.35,
2083
+ 0.35
2084
+ ],
1927
2085
  options: {
1928
2086
  animatable: true,
1929
2087
  minValue: 0,
1930
- maxValue: 4
2088
+ maxValue: 1
1931
2089
  },
1932
2090
  get (value) {
1933
- value.num[0] = this.specularStrength;
2091
+ value.num[0] = this.specular1Color.x;
2092
+ value.num[1] = this.specular1Color.y;
2093
+ value.num[2] = this.specular1Color.z;
1934
2094
  },
1935
2095
  set (value) {
1936
- this.specularStrength = value.num[0];
1937
- },
1938
- getDefaultValue () {
1939
- return this.$isInstance ? this.coreMaterial.specularStrength : 0.22;
2096
+ this.specular1Color = new Vector3(value.num[0], value.num[1], value.num[2]);
1940
2097
  }
1941
2098
  },
1942
2099
  {
1943
- name: 'DiffuseWrap',
1944
- description: 'Wrap amount for visible diffuse lighting',
2100
+ name: 'Specular1Power',
2101
+ description: 'Exponent of the primary specular lobe',
1945
2102
  type: 'float',
1946
- default: 0.28,
2103
+ default: 160,
1947
2104
  options: {
1948
2105
  animatable: true,
1949
- minValue: 0,
1950
- maxValue: 2
2106
+ minValue: 1,
2107
+ maxValue: 1024
1951
2108
  },
1952
2109
  get (value) {
1953
- value.num[0] = this.diffuseWrap;
2110
+ value.num[0] = this.specular1Power;
1954
2111
  },
1955
2112
  set (value) {
1956
- this.diffuseWrap = value.num[0];
1957
- },
1958
- getDefaultValue () {
1959
- return this.$isInstance ? this.coreMaterial.diffuseWrap : 0.28;
2113
+ this.specular1Power = value.num[0];
1960
2114
  }
1961
2115
  },
1962
2116
  {
1963
- name: 'DiffuseSoftness',
1964
- description: 'Blend from hard Lambert lighting to wrapped diffuse lighting',
2117
+ name: 'Specular1Shift',
2118
+ description: 'Shift of the primary specular lobe along the strand',
1965
2119
  type: 'float',
1966
- default: 0.45,
2120
+ default: -0.15,
1967
2121
  options: {
1968
2122
  animatable: true,
1969
- minValue: 0,
2123
+ minValue: -1,
1970
2124
  maxValue: 1
1971
2125
  },
1972
2126
  get (value) {
1973
- value.num[0] = this.diffuseSoftness;
2127
+ value.num[0] = this.specular1Shift;
1974
2128
  },
1975
2129
  set (value) {
1976
- this.diffuseSoftness = value.num[0];
1977
- },
1978
- getDefaultValue () {
1979
- return this.$isInstance ? this.coreMaterial.diffuseSoftness : 0.45;
2130
+ this.specular1Shift = value.num[0];
1980
2131
  }
1981
2132
  },
1982
2133
  {
1983
- name: 'ScatterWrap',
1984
- description: 'Wide wrap amount written to the Skin SSS scattering source',
1985
- type: 'float',
1986
- default: 0.65,
2134
+ name: 'Specular2Color',
2135
+ description: 'Color of the secondary (broad, hair-tinted) specular lobe',
2136
+ type: 'rgb',
2137
+ default: [
2138
+ 0.5,
2139
+ 0.45,
2140
+ 0.4
2141
+ ],
1987
2142
  options: {
1988
2143
  animatable: true,
1989
2144
  minValue: 0,
1990
- maxValue: 2
2145
+ maxValue: 1
1991
2146
  },
1992
2147
  get (value) {
1993
- value.num[0] = this.scatterWrap;
2148
+ value.num[0] = this.specular2Color.x;
2149
+ value.num[1] = this.specular2Color.y;
2150
+ value.num[2] = this.specular2Color.z;
1994
2151
  },
1995
2152
  set (value) {
1996
- this.scatterWrap = value.num[0];
1997
- },
1998
- getDefaultValue () {
1999
- return this.$isInstance ? this.coreMaterial.scatterWrap : 0.65;
2153
+ this.specular2Color = new Vector3(value.num[0], value.num[1], value.num[2]);
2000
2154
  }
2001
2155
  },
2002
2156
  {
2003
- name: 'ScatterStrength',
2004
- description: 'Strength of the lighting multiplier written to the Skin SSS side buffer',
2157
+ name: 'Specular2Power',
2158
+ description: 'Exponent of the secondary specular lobe',
2005
2159
  type: 'float',
2006
- default: 0.7,
2160
+ default: 40,
2007
2161
  options: {
2008
2162
  animatable: true,
2009
- minValue: 0,
2010
- maxValue: 4
2163
+ minValue: 1,
2164
+ maxValue: 1024
2011
2165
  },
2012
2166
  get (value) {
2013
- value.num[0] = this.scatterStrength;
2167
+ value.num[0] = this.specular2Power;
2014
2168
  },
2015
2169
  set (value) {
2016
- this.scatterStrength = value.num[0];
2017
- },
2018
- getDefaultValue () {
2019
- return this.$isInstance ? this.coreMaterial.scatterStrength : 0.7;
2170
+ this.specular2Power = value.num[0];
2020
2171
  }
2021
2172
  },
2022
2173
  {
2023
- name: 'ScatterColor',
2024
- description: 'Warm tint for the blurred skin scattering contribution',
2025
- type: 'rgba',
2026
- default: [
2027
- 1,
2028
- 0.42,
2029
- 0.28,
2030
- 1
2031
- ],
2174
+ name: 'Specular2Shift',
2175
+ description: 'Shift of the secondary specular lobe along the strand',
2176
+ type: 'float',
2177
+ default: 0.1,
2032
2178
  options: {
2033
2179
  animatable: true,
2034
- minValue: 0,
2180
+ minValue: -1,
2035
2181
  maxValue: 1
2036
2182
  },
2037
2183
  get (value) {
2038
- value.num[0] = this.scatterColor.x;
2039
- value.num[1] = this.scatterColor.y;
2040
- value.num[2] = this.scatterColor.z;
2041
- value.num[3] = this.scatterColor.w;
2184
+ value.num[0] = this.specular2Shift;
2042
2185
  },
2043
2186
  set (value) {
2044
- this.scatterColor = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
2045
- },
2046
- getDefaultValue () {
2047
- const color = this.$isInstance ? this.coreMaterial.scatterColor : new Vector4(1, 0.42, 0.28, 1);
2048
- return [
2049
- color.x,
2050
- color.y,
2051
- color.z,
2052
- color.w
2053
- ];
2187
+ this.specular2Shift = value.num[0];
2054
2188
  }
2055
2189
  },
2056
- ...getTextureProps(manager, 'subsurfaceTexture', '2D', false, 1),
2057
- ...getLitMaterialProps(manager)
2058
- ]);
2059
- }
2060
- },
2061
- getMeshMaterialInstanceUniformsClass(SkinMaterial)
2062
- ];
2063
- }
2064
- /** @internal */ function getPBRMetallicRoughnessMaterialClass(manager) {
2065
- return [
2066
- {
2067
- ctor: PBRMetallicRoughnessMaterial,
2068
- parent: MeshMaterial,
2069
- name: 'PBRMetallicRoughnessMaterial',
2070
- getProps () {
2071
- return defineProps([
2072
2190
  {
2073
- name: 'Metallic',
2074
- description: 'Metallic value',
2075
- type: 'float',
2191
+ name: 'StrandDirection',
2192
+ description: 'Which TBN axis runs along the hair strands in the card atlas',
2193
+ type: 'string',
2194
+ default: 'binormal',
2076
2195
  options: {
2077
- animatable: true,
2078
- minValue: 0,
2079
- maxValue: 1
2196
+ enum: {
2197
+ labels: [
2198
+ 'Tangent (U)',
2199
+ 'Binormal (V)'
2200
+ ],
2201
+ values: [
2202
+ 'tangent',
2203
+ 'binormal'
2204
+ ]
2205
+ }
2080
2206
  },
2081
2207
  get (value) {
2082
- value.num[0] = this.metallic;
2208
+ value.str[0] = this.strandDirection;
2083
2209
  },
2084
2210
  set (value) {
2085
- this.metallic = value.num[0];
2211
+ this.strandDirection = value.str[0];
2086
2212
  },
2087
- isHidden: createBlueprintOutputHiddenPredicate(),
2088
- getDefaultValue () {
2089
- return this.$isInstance ? this.coreMaterial.metallic : 1;
2213
+ isValid () {
2214
+ return !this.$isInstance;
2090
2215
  }
2091
2216
  },
2217
+ // The Marschner parameters are deliberately not gated on ShadingModel.
2218
+ // An invalid property is skipped on both save and load, so gating them
2219
+ // would drop one model's tuning every time the material was saved under
2220
+ // the other - and switching back and forth is exactly what comparing
2221
+ // two models involves.
2092
2222
  {
2093
- name: 'Roughness',
2094
- description: 'Roughness value',
2223
+ name: 'MarschnerShift',
2224
+ description: 'Cuticle tilt that separates the three Marschner lobes, in sine units',
2225
+ type: 'float',
2226
+ default: 0.035,
2227
+ options: {
2228
+ animatable: true,
2229
+ minValue: -0.2,
2230
+ maxValue: 0.2
2231
+ },
2232
+ get (value) {
2233
+ value.num[0] = this.marschnerShift;
2234
+ },
2235
+ set (value) {
2236
+ this.marschnerShift = value.num[0];
2237
+ },
2238
+ isValid () {
2239
+ return !this.$isInstance;
2240
+ }
2241
+ },
2242
+ {
2243
+ name: 'MarschnerRoughness',
2244
+ description: 'Longitudinal width of the Marschner lobes',
2245
+ type: 'float',
2246
+ default: 0.3,
2247
+ options: {
2248
+ animatable: true,
2249
+ minValue: 0.005,
2250
+ maxValue: 1
2251
+ },
2252
+ get (value) {
2253
+ value.num[0] = this.marschnerRoughness;
2254
+ },
2255
+ set (value) {
2256
+ this.marschnerRoughness = value.num[0];
2257
+ },
2258
+ isValid () {
2259
+ return !this.$isInstance;
2260
+ }
2261
+ },
2262
+ {
2263
+ name: 'MarschnerIOR',
2264
+ description: 'Refractive index of the fibre. 1.55 is the measured value for keratin',
2265
+ type: 'float',
2266
+ default: 1.55,
2267
+ options: {
2268
+ animatable: true,
2269
+ minValue: 1.01,
2270
+ maxValue: 2.5
2271
+ },
2272
+ get (value) {
2273
+ value.num[0] = this.marschnerIOR;
2274
+ },
2275
+ set (value) {
2276
+ this.marschnerIOR = value.num[0];
2277
+ },
2278
+ isValid () {
2279
+ return !this.$isInstance;
2280
+ }
2281
+ },
2282
+ {
2283
+ name: 'MarschnerAbsorption',
2284
+ description: 'How strongly the transmitted Marschner paths take on the hair colour',
2285
+ type: 'float',
2286
+ default: 1,
2287
+ options: {
2288
+ animatable: true,
2289
+ minValue: 0,
2290
+ maxValue: 4
2291
+ },
2292
+ get (value) {
2293
+ value.num[0] = this.marschnerAbsorption;
2294
+ },
2295
+ set (value) {
2296
+ this.marschnerAbsorption = value.num[0];
2297
+ },
2298
+ isValid () {
2299
+ return !this.$isInstance;
2300
+ }
2301
+ },
2302
+ {
2303
+ name: 'MarschnerLobes',
2304
+ description: 'Per-path intensities of the Marschner model as (R, TT, TRT)',
2305
+ type: 'vec3',
2306
+ default: [
2307
+ 1,
2308
+ 1,
2309
+ 1
2310
+ ],
2311
+ options: {
2312
+ animatable: true,
2313
+ minValue: 0,
2314
+ maxValue: 4
2315
+ },
2316
+ get (value) {
2317
+ value.num[0] = this.marschnerLobes.x;
2318
+ value.num[1] = this.marschnerLobes.y;
2319
+ value.num[2] = this.marschnerLobes.z;
2320
+ },
2321
+ set (value) {
2322
+ this.marschnerLobes = new Vector3(value.num[0], value.num[1], value.num[2]);
2323
+ },
2324
+ isValid () {
2325
+ return !this.$isInstance;
2326
+ }
2327
+ },
2328
+ {
2329
+ name: 'ShiftMapScale',
2330
+ description: 'Scale applied to the per-strand shift texture',
2331
+ type: 'float',
2332
+ phase: 1,
2333
+ default: 1,
2334
+ options: {
2335
+ animatable: true,
2336
+ minValue: 0,
2337
+ maxValue: 4
2338
+ },
2339
+ get (value) {
2340
+ value.num[0] = this.shiftMapScale;
2341
+ },
2342
+ set (value) {
2343
+ this.shiftMapScale = value.num[0];
2344
+ },
2345
+ isValid () {
2346
+ return !this.$isInstance && !!this.specularShiftTexture;
2347
+ }
2348
+ },
2349
+ ...getTextureProps(manager, 'specularShiftTexture', '2D', false, 0),
2350
+ {
2351
+ name: 'DiffuseWrap',
2352
+ description: 'Wrap diffuse amount that softens the terminator across thin cards',
2353
+ type: 'float',
2354
+ default: 0.5,
2355
+ options: {
2356
+ animatable: true,
2357
+ minValue: 0,
2358
+ maxValue: 1
2359
+ },
2360
+ get (value) {
2361
+ value.num[0] = this.diffuseWrap;
2362
+ },
2363
+ set (value) {
2364
+ this.diffuseWrap = value.num[0];
2365
+ }
2366
+ },
2367
+ {
2368
+ name: 'TransmissionColor',
2369
+ description: 'Tint color of the backlit transmission term',
2370
+ type: 'rgb',
2371
+ default: [
2372
+ 0.9,
2373
+ 0.65,
2374
+ 0.45
2375
+ ],
2376
+ options: {
2377
+ animatable: true,
2378
+ minValue: 0,
2379
+ maxValue: 1
2380
+ },
2381
+ get (value) {
2382
+ value.num[0] = this.transmissionColor.x;
2383
+ value.num[1] = this.transmissionColor.y;
2384
+ value.num[2] = this.transmissionColor.z;
2385
+ },
2386
+ set (value) {
2387
+ this.transmissionColor = new Vector3(value.num[0], value.num[1], value.num[2]);
2388
+ }
2389
+ },
2390
+ {
2391
+ name: 'TransmissionIntensity',
2392
+ description: 'Intensity of the backlit transmission term, 0 disables it',
2393
+ type: 'float',
2394
+ default: 0,
2395
+ options: {
2396
+ animatable: true,
2397
+ minValue: 0,
2398
+ maxValue: 4
2399
+ },
2400
+ get (value) {
2401
+ value.num[0] = this.transmissionIntensity;
2402
+ },
2403
+ set (value) {
2404
+ this.transmissionIntensity = value.num[0];
2405
+ }
2406
+ },
2407
+ {
2408
+ name: 'TransmissionPower',
2409
+ description: 'View-alignment exponent of the transmission term',
2410
+ type: 'float',
2411
+ default: 6,
2412
+ options: {
2413
+ animatable: true,
2414
+ minValue: 1,
2415
+ maxValue: 64
2416
+ },
2417
+ get (value) {
2418
+ value.num[0] = this.transmissionPower;
2419
+ },
2420
+ set (value) {
2421
+ this.transmissionPower = value.num[0];
2422
+ }
2423
+ },
2424
+ {
2425
+ name: 'ScatterColor',
2426
+ description: 'Tint of multiply-scattered light',
2427
+ type: 'rgb',
2428
+ default: [
2429
+ 1,
2430
+ 0.85,
2431
+ 0.7
2432
+ ],
2433
+ options: {
2434
+ animatable: true
2435
+ },
2436
+ get (value) {
2437
+ value.num[0] = this.scatterColor.x;
2438
+ value.num[1] = this.scatterColor.y;
2439
+ value.num[2] = this.scatterColor.z;
2440
+ },
2441
+ set (value) {
2442
+ this.scatterColor = new Vector3(value.num[0], value.num[1], value.num[2]);
2443
+ }
2444
+ },
2445
+ {
2446
+ name: 'ScatterIntensity',
2447
+ description: 'Intensity of the multiple scattering term, 0 disables it',
2448
+ type: 'float',
2449
+ default: 0,
2450
+ options: {
2451
+ animatable: true,
2452
+ minValue: 0,
2453
+ maxValue: 4
2454
+ },
2455
+ get (value) {
2456
+ value.num[0] = this.scatterIntensity;
2457
+ },
2458
+ set (value) {
2459
+ this.scatterIntensity = value.num[0];
2460
+ }
2461
+ },
2462
+ {
2463
+ name: 'ScatterLocal',
2464
+ description: 'Balance between scattering that follows the light and scattering that survives where it is blocked',
2465
+ type: 'float',
2466
+ default: 0.5,
2467
+ options: {
2468
+ animatable: true,
2469
+ minValue: 0,
2470
+ maxValue: 1
2471
+ },
2472
+ get (value) {
2473
+ value.num[0] = this.scatterLocal;
2474
+ },
2475
+ set (value) {
2476
+ this.scatterLocal = value.num[0];
2477
+ }
2478
+ },
2479
+ {
2480
+ name: 'ScatterWrap',
2481
+ description: 'Angular width of the forward-scattered lobe',
2482
+ type: 'float',
2483
+ default: 1,
2484
+ options: {
2485
+ animatable: true,
2486
+ minValue: 0,
2487
+ maxValue: 4
2488
+ },
2489
+ get (value) {
2490
+ value.num[0] = this.scatterWrap;
2491
+ },
2492
+ set (value) {
2493
+ this.scatterWrap = value.num[0];
2494
+ }
2495
+ },
2496
+ {
2497
+ name: 'OcclusionStrength',
2498
+ description: 'Strength of the baked occlusion (root darkening) texture',
2499
+ type: 'float',
2500
+ phase: 1,
2501
+ default: 1,
2502
+ options: {
2503
+ animatable: true,
2504
+ minValue: 0,
2505
+ maxValue: 1
2506
+ },
2507
+ get (value) {
2508
+ value.num[0] = this.occlusionStrength;
2509
+ },
2510
+ set (value) {
2511
+ this.occlusionStrength = value.num[0];
2512
+ },
2513
+ isValid () {
2514
+ return !this.$isInstance && !!this.occlusionTexture;
2515
+ }
2516
+ },
2517
+ ...getTextureProps(manager, 'occlusionTexture', '2D', false, 0),
2518
+ ...getLitMaterialProps(manager)
2519
+ ]);
2520
+ }
2521
+ },
2522
+ getMeshMaterialInstanceUniformsClass(HairMaterial)
2523
+ ];
2524
+ }
2525
+ /** @internal */ function getSkinMaterialClass(manager) {
2526
+ return [
2527
+ {
2528
+ ctor: SkinMaterial,
2529
+ parent: MeshMaterial,
2530
+ name: 'SkinMaterial',
2531
+ getProps () {
2532
+ return defineProps([
2533
+ {
2534
+ name: 'Shininess',
2535
+ description: 'Blinn specular exponent for skin highlights',
2536
+ type: 'float',
2537
+ default: 72,
2538
+ options: {
2539
+ animatable: true,
2540
+ minValue: 1,
2541
+ maxValue: 2048
2542
+ },
2543
+ get (value) {
2544
+ value.num[0] = this.shininess;
2545
+ },
2546
+ set (value) {
2547
+ this.shininess = value.num[0];
2548
+ },
2549
+ getDefaultValue () {
2550
+ return this.$isInstance ? this.coreMaterial.shininess : 72;
2551
+ }
2552
+ },
2553
+ {
2554
+ name: 'SpecularStrength',
2555
+ description: 'Direct specular strength for restrained skin highlights',
2556
+ type: 'float',
2557
+ default: 1,
2558
+ options: {
2559
+ animatable: true,
2560
+ minValue: 0,
2561
+ maxValue: 4
2562
+ },
2563
+ get (value) {
2564
+ value.num[0] = this.specularStrength;
2565
+ },
2566
+ set (value) {
2567
+ this.specularStrength = value.num[0];
2568
+ },
2569
+ getDefaultValue () {
2570
+ return this.$isInstance ? this.coreMaterial.specularStrength : 1;
2571
+ }
2572
+ },
2573
+ {
2574
+ name: 'DiffuseWrap',
2575
+ description: 'Wrap amount for visible diffuse lighting',
2576
+ type: 'float',
2577
+ default: 0.28,
2578
+ options: {
2579
+ animatable: true,
2580
+ minValue: 0,
2581
+ maxValue: 2
2582
+ },
2583
+ get (value) {
2584
+ value.num[0] = this.diffuseWrap;
2585
+ },
2586
+ set (value) {
2587
+ this.diffuseWrap = value.num[0];
2588
+ },
2589
+ getDefaultValue () {
2590
+ return this.$isInstance ? this.coreMaterial.diffuseWrap : 0.28;
2591
+ }
2592
+ },
2593
+ {
2594
+ name: 'DiffuseSoftness',
2595
+ description: 'Blend from hard Lambert lighting to wrapped diffuse lighting',
2596
+ type: 'float',
2597
+ default: 0.45,
2598
+ options: {
2599
+ animatable: true,
2600
+ minValue: 0,
2601
+ maxValue: 1
2602
+ },
2603
+ get (value) {
2604
+ value.num[0] = this.diffuseSoftness;
2605
+ },
2606
+ set (value) {
2607
+ this.diffuseSoftness = value.num[0];
2608
+ },
2609
+ getDefaultValue () {
2610
+ return this.$isInstance ? this.coreMaterial.diffuseSoftness : 0.45;
2611
+ }
2612
+ },
2613
+ {
2614
+ name: 'ScatterWrap',
2615
+ description: 'Wide wrap amount written to the Skin SSS scattering source',
2616
+ type: 'float',
2617
+ default: 0.65,
2618
+ options: {
2619
+ animatable: true,
2620
+ minValue: 0,
2621
+ maxValue: 2
2622
+ },
2623
+ get (value) {
2624
+ value.num[0] = this.scatterWrap;
2625
+ },
2626
+ set (value) {
2627
+ this.scatterWrap = value.num[0];
2628
+ },
2629
+ getDefaultValue () {
2630
+ return this.$isInstance ? this.coreMaterial.scatterWrap : 0.65;
2631
+ }
2632
+ },
2633
+ {
2634
+ name: 'ScatterStrength',
2635
+ description: 'Strength of the scatter irradiance written to the Skin SSS side buffer',
2636
+ type: 'float',
2637
+ default: 1.5,
2638
+ options: {
2639
+ animatable: true,
2640
+ minValue: 0,
2641
+ maxValue: 4
2642
+ },
2643
+ get (value) {
2644
+ value.num[0] = this.scatterStrength;
2645
+ },
2646
+ set (value) {
2647
+ this.scatterStrength = value.num[0];
2648
+ },
2649
+ getDefaultValue () {
2650
+ return this.$isInstance ? this.coreMaterial.scatterStrength : 1.5;
2651
+ }
2652
+ },
2653
+ {
2654
+ name: 'ScatterColor',
2655
+ description: 'Warm tint for the blurred skin scattering contribution',
2656
+ type: 'rgba',
2657
+ default: [
2658
+ 1,
2659
+ 0.42,
2660
+ 0.28,
2661
+ 1
2662
+ ],
2663
+ options: {
2664
+ animatable: true,
2665
+ minValue: 0,
2666
+ maxValue: 1
2667
+ },
2668
+ get (value) {
2669
+ value.num[0] = this.scatterColor.x;
2670
+ value.num[1] = this.scatterColor.y;
2671
+ value.num[2] = this.scatterColor.z;
2672
+ value.num[3] = this.scatterColor.w;
2673
+ },
2674
+ set (value) {
2675
+ this.scatterColor = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
2676
+ },
2677
+ getDefaultValue () {
2678
+ const color = this.$isInstance ? this.coreMaterial.scatterColor : new Vector4(1, 0.42, 0.28, 1);
2679
+ return [
2680
+ color.x,
2681
+ color.y,
2682
+ color.z,
2683
+ color.w
2684
+ ];
2685
+ }
2686
+ },
2687
+ {
2688
+ name: 'ShadowTint',
2689
+ description: 'NPR shadow tint the dark end of the diffuse ramp lifts toward (black is neutral)',
2690
+ type: 'rgba',
2691
+ default: [
2692
+ 0,
2693
+ 0,
2694
+ 0,
2695
+ 1
2696
+ ],
2697
+ options: {
2698
+ animatable: true,
2699
+ minValue: 0,
2700
+ maxValue: 1
2701
+ },
2702
+ get (value) {
2703
+ value.num[0] = this.shadowTint.x;
2704
+ value.num[1] = this.shadowTint.y;
2705
+ value.num[2] = this.shadowTint.z;
2706
+ value.num[3] = this.shadowTint.w;
2707
+ },
2708
+ set (value) {
2709
+ this.shadowTint = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
2710
+ },
2711
+ getDefaultValue () {
2712
+ const color = this.$isInstance ? this.coreMaterial.shadowTint : new Vector4(0, 0, 0, 1);
2713
+ return [
2714
+ color.x,
2715
+ color.y,
2716
+ color.z,
2717
+ color.w
2718
+ ];
2719
+ }
2720
+ },
2721
+ {
2722
+ name: 'Brightening',
2723
+ description: 'Whitening gain applied to the whole diffuse response',
2724
+ type: 'float',
2725
+ default: 0,
2726
+ options: {
2727
+ animatable: true,
2728
+ minValue: 0,
2729
+ maxValue: 2
2730
+ },
2731
+ get (value) {
2732
+ value.num[0] = this.brightening;
2733
+ },
2734
+ set (value) {
2735
+ this.brightening = value.num[0];
2736
+ },
2737
+ getDefaultValue () {
2738
+ return this.$isInstance ? this.coreMaterial.brightening : 0;
2739
+ }
2740
+ },
2741
+ {
2742
+ name: 'TransmissionStrength',
2743
+ description: 'Back-lit transmission strength (needs thickness in subsurface texture B)',
2744
+ type: 'float',
2745
+ default: 0,
2746
+ options: {
2747
+ animatable: true,
2748
+ minValue: 0,
2749
+ maxValue: 4
2750
+ },
2751
+ get (value) {
2752
+ value.num[0] = this.transmissionStrength;
2753
+ },
2754
+ set (value) {
2755
+ this.transmissionStrength = value.num[0];
2756
+ },
2757
+ getDefaultValue () {
2758
+ return this.$isInstance ? this.coreMaterial.transmissionStrength : 0;
2759
+ }
2760
+ },
2761
+ {
2762
+ name: 'TransmissionPower',
2763
+ description: 'Exponent of the back-lit transmission falloff',
2764
+ type: 'float',
2765
+ default: 4,
2766
+ options: {
2767
+ animatable: true,
2768
+ minValue: 1,
2769
+ maxValue: 16
2770
+ },
2771
+ get (value) {
2772
+ value.num[0] = this.transmissionPower;
2773
+ },
2774
+ set (value) {
2775
+ this.transmissionPower = value.num[0];
2776
+ },
2777
+ getDefaultValue () {
2778
+ return this.$isInstance ? this.coreMaterial.transmissionPower : 4;
2779
+ }
2780
+ },
2781
+ ...getTextureProps(manager, 'subsurfaceTexture', '2D', false, 1),
2782
+ ...getLitMaterialProps(manager)
2783
+ ]);
2784
+ }
2785
+ },
2786
+ getMeshMaterialInstanceUniformsClass(SkinMaterial)
2787
+ ];
2788
+ }
2789
+ /**
2790
+ * Serialization for {@link EyeMaterial}.
2791
+ *
2792
+ * Every `getDefaultValue()` non-instance branch below must return exactly what
2793
+ * the constructor sets. The serializer uses this both to decide whether a
2794
+ * property can be omitted when saving and to fill it in when it is absent on
2795
+ * load, so a mismatch silently rewrites assets - which is what a mismatched
2796
+ * `doubleSidedLighting` default did before it was found.
2797
+ */ function getEyeMaterialClass(manager) {
2798
+ return [
2799
+ {
2800
+ ctor: EyeMaterial,
2801
+ parent: MeshMaterial,
2802
+ name: 'EyeMaterial',
2803
+ getProps () {
2804
+ return defineProps([
2805
+ {
2806
+ name: 'IrisCenter',
2807
+ description: 'UV coordinate of the pupil centre on the eyeball mesh',
2808
+ type: 'vec2',
2809
+ default: [
2810
+ 0.5,
2811
+ 0.5
2812
+ ],
2813
+ options: {
2814
+ minValue: 0,
2815
+ maxValue: 1
2816
+ },
2817
+ get (value) {
2818
+ value.num[0] = this.irisCenter.x;
2819
+ value.num[1] = this.irisCenter.y;
2820
+ },
2821
+ set (value) {
2822
+ this.irisCenter = new Vector4(value.num[0], value.num[1], 0, 0);
2823
+ },
2824
+ getDefaultValue () {
2825
+ const c = this.$isInstance ? this.coreMaterial.irisCenter : new Vector4(0.5, 0.5, 0, 0);
2826
+ return [
2827
+ c.x,
2828
+ c.y
2829
+ ];
2830
+ }
2831
+ },
2832
+ {
2833
+ name: 'IrisRadius',
2834
+ description: 'Iris disc radius in UV units',
2835
+ type: 'float',
2836
+ default: 0.22,
2837
+ options: {
2838
+ animatable: true,
2839
+ minValue: 0.001,
2840
+ maxValue: 0.5
2841
+ },
2842
+ get (value) {
2843
+ value.num[0] = this.irisRadius;
2844
+ },
2845
+ set (value) {
2846
+ this.irisRadius = value.num[0];
2847
+ },
2848
+ getDefaultValue () {
2849
+ return this.$isInstance ? this.coreMaterial.irisRadius : 0.22;
2850
+ }
2851
+ },
2852
+ {
2853
+ name: 'IrisDepth',
2854
+ description: 'Depth of the iris plane below the cornea; 0 disables parallax',
2855
+ type: 'float',
2856
+ default: 0.06,
2857
+ options: {
2858
+ animatable: true,
2859
+ minValue: 0,
2860
+ maxValue: 0.5
2861
+ },
2862
+ get (value) {
2863
+ value.num[0] = this.irisDepth;
2864
+ },
2865
+ set (value) {
2866
+ this.irisDepth = value.num[0];
2867
+ },
2868
+ getDefaultValue () {
2869
+ return this.$isInstance ? this.coreMaterial.irisDepth : 0.06;
2870
+ }
2871
+ },
2872
+ {
2873
+ name: 'IOR',
2874
+ description: 'Index of refraction of the cornea (1.376 is physical)',
2875
+ type: 'float',
2876
+ default: 1.376,
2877
+ options: {
2878
+ animatable: true,
2879
+ minValue: 1,
2880
+ maxValue: 2
2881
+ },
2882
+ get (value) {
2883
+ value.num[0] = this.ior;
2884
+ },
2885
+ set (value) {
2886
+ this.ior = value.num[0];
2887
+ },
2888
+ getDefaultValue () {
2889
+ return this.$isInstance ? this.coreMaterial.ior : 1.376;
2890
+ }
2891
+ },
2892
+ {
2893
+ name: 'PupilRadius',
2894
+ description: 'Pupil radius as a fraction of the iris radius',
2895
+ type: 'float',
2896
+ default: 0.35,
2897
+ options: {
2898
+ animatable: true,
2899
+ minValue: 0.01,
2900
+ maxValue: 0.95
2901
+ },
2902
+ get (value) {
2903
+ value.num[0] = this.pupilRadius;
2904
+ },
2905
+ set (value) {
2906
+ this.pupilRadius = value.num[0];
2907
+ },
2908
+ getDefaultValue () {
2909
+ return this.$isInstance ? this.coreMaterial.pupilRadius : 0.35;
2910
+ }
2911
+ },
2912
+ {
2913
+ name: 'PupilDilation',
2914
+ description: 'Pupil dilation from -1 (constricted) to 1 (dilated)',
2915
+ type: 'float',
2916
+ default: 0,
2917
+ options: {
2918
+ animatable: true,
2919
+ minValue: -1,
2920
+ maxValue: 1
2921
+ },
2922
+ get (value) {
2923
+ value.num[0] = this.pupilDilation;
2924
+ },
2925
+ set (value) {
2926
+ this.pupilDilation = value.num[0];
2927
+ },
2928
+ getDefaultValue () {
2929
+ return this.$isInstance ? this.coreMaterial.pupilDilation : 0;
2930
+ }
2931
+ },
2932
+ {
2933
+ name: 'IrisColor',
2934
+ description: 'Tint multiplied over the iris texture',
2935
+ type: 'rgba',
2936
+ default: [
2937
+ 1,
2938
+ 1,
2939
+ 1,
2940
+ 1
2941
+ ],
2942
+ options: {
2943
+ animatable: true,
2944
+ minValue: 0,
2945
+ maxValue: 4
2946
+ },
2947
+ get (value) {
2948
+ value.num[0] = this.irisColor.x;
2949
+ value.num[1] = this.irisColor.y;
2950
+ value.num[2] = this.irisColor.z;
2951
+ value.num[3] = this.irisColor.w;
2952
+ },
2953
+ set (value) {
2954
+ this.irisColor = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
2955
+ },
2956
+ getDefaultValue () {
2957
+ const c = this.$isInstance ? this.coreMaterial.irisColor : new Vector4(1, 1, 1, 1);
2958
+ return [
2959
+ c.x,
2960
+ c.y,
2961
+ c.z,
2962
+ c.w
2963
+ ];
2964
+ }
2965
+ },
2966
+ {
2967
+ name: 'IrisBrightness',
2968
+ description: 'Internal scattering that keeps the iris from crushing to black in shadow',
2969
+ type: 'float',
2970
+ default: 0.15,
2971
+ options: {
2972
+ animatable: true,
2973
+ minValue: 0,
2974
+ maxValue: 2
2975
+ },
2976
+ get (value) {
2977
+ value.num[0] = this.irisBrightness;
2978
+ },
2979
+ set (value) {
2980
+ this.irisBrightness = value.num[0];
2981
+ },
2982
+ getDefaultValue () {
2983
+ return this.$isInstance ? this.coreMaterial.irisBrightness : 0.15;
2984
+ }
2985
+ },
2986
+ {
2987
+ name: 'LimbalRingWidth',
2988
+ description: 'Width of the dark ring at the iris edge, as a fraction of the iris radius',
2989
+ type: 'float',
2990
+ default: 0.15,
2991
+ options: {
2992
+ animatable: true,
2993
+ minValue: 0,
2994
+ maxValue: 1
2995
+ },
2996
+ get (value) {
2997
+ value.num[0] = this.limbalRingWidth;
2998
+ },
2999
+ set (value) {
3000
+ this.limbalRingWidth = value.num[0];
3001
+ },
3002
+ getDefaultValue () {
3003
+ return this.$isInstance ? this.coreMaterial.limbalRingWidth : 0.15;
3004
+ }
3005
+ },
3006
+ {
3007
+ name: 'LimbalRingStrength',
3008
+ description: 'How dark the limbal ring gets; 0 disables it',
3009
+ type: 'float',
3010
+ default: 0.7,
3011
+ options: {
3012
+ animatable: true,
3013
+ minValue: 0,
3014
+ maxValue: 1
3015
+ },
3016
+ get (value) {
3017
+ value.num[0] = this.limbalRingStrength;
3018
+ },
3019
+ set (value) {
3020
+ this.limbalRingStrength = value.num[0];
3021
+ },
3022
+ getDefaultValue () {
3023
+ return this.$isInstance ? this.coreMaterial.limbalRingStrength : 0.7;
3024
+ }
3025
+ },
3026
+ {
3027
+ name: 'ScleraColor',
3028
+ description: 'Base sclera colour; pure white reads as plastic',
3029
+ type: 'rgba',
3030
+ default: [
3031
+ 0.9,
3032
+ 0.88,
3033
+ 0.86,
3034
+ 1
3035
+ ],
3036
+ options: {
3037
+ animatable: true,
3038
+ minValue: 0,
3039
+ maxValue: 1
3040
+ },
3041
+ get (value) {
3042
+ value.num[0] = this.scleraColor.x;
3043
+ value.num[1] = this.scleraColor.y;
3044
+ value.num[2] = this.scleraColor.z;
3045
+ value.num[3] = this.scleraColor.w;
3046
+ },
3047
+ set (value) {
3048
+ this.scleraColor = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
3049
+ },
3050
+ getDefaultValue () {
3051
+ const c = this.$isInstance ? this.coreMaterial.scleraColor : new Vector4(0.9, 0.88, 0.86, 1);
3052
+ return [
3053
+ c.x,
3054
+ c.y,
3055
+ c.z,
3056
+ c.w
3057
+ ];
3058
+ }
3059
+ },
3060
+ {
3061
+ name: 'ScleraWrap',
3062
+ description: 'Diffuse wrap for the sclera, standing in for its subsurface softness',
3063
+ type: 'float',
3064
+ default: 0.35,
3065
+ options: {
3066
+ animatable: true,
3067
+ minValue: 0,
3068
+ maxValue: 2
3069
+ },
3070
+ get (value) {
3071
+ value.num[0] = this.scleraWrap;
3072
+ },
3073
+ set (value) {
3074
+ this.scleraWrap = value.num[0];
3075
+ },
3076
+ getDefaultValue () {
3077
+ return this.$isInstance ? this.coreMaterial.scleraWrap : 0.35;
3078
+ }
3079
+ },
3080
+ {
3081
+ name: 'ScleraEdgeTint',
3082
+ description: 'Vasculature colour bled into the sclera away from the iris; alpha is its strength',
3083
+ type: 'rgba',
3084
+ default: [
3085
+ 0.55,
3086
+ 0.22,
3087
+ 0.18,
3088
+ 1
3089
+ ],
3090
+ options: {
3091
+ animatable: true,
3092
+ minValue: 0,
3093
+ maxValue: 1
3094
+ },
3095
+ get (value) {
3096
+ value.num[0] = this.scleraEdgeTint.x;
3097
+ value.num[1] = this.scleraEdgeTint.y;
3098
+ value.num[2] = this.scleraEdgeTint.z;
3099
+ value.num[3] = this.scleraEdgeTint.w;
3100
+ },
3101
+ set (value) {
3102
+ this.scleraEdgeTint = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
3103
+ },
3104
+ getDefaultValue () {
3105
+ const c = this.$isInstance ? this.coreMaterial.scleraEdgeTint : new Vector4(0.55, 0.22, 0.18, 1);
3106
+ return [
3107
+ c.x,
3108
+ c.y,
3109
+ c.z,
3110
+ c.w
3111
+ ];
3112
+ }
3113
+ },
3114
+ {
3115
+ name: 'CorneaSpecularStrength',
3116
+ description: 'Strength of the corneal highlight - the main cue that an eye is wet',
3117
+ type: 'float',
3118
+ default: 1,
3119
+ options: {
3120
+ animatable: true,
3121
+ minValue: 0,
3122
+ maxValue: 4
3123
+ },
3124
+ get (value) {
3125
+ value.num[0] = this.corneaSpecularStrength;
3126
+ },
3127
+ set (value) {
3128
+ this.corneaSpecularStrength = value.num[0];
3129
+ },
3130
+ getDefaultValue () {
3131
+ return this.$isInstance ? this.coreMaterial.corneaSpecularStrength : 1;
3132
+ }
3133
+ },
3134
+ {
3135
+ name: 'CorneaRoughness',
3136
+ description: 'Corneal roughness; the cornea is close to a mirror, so keep this very low',
3137
+ type: 'float',
3138
+ default: 0.05,
3139
+ options: {
3140
+ animatable: true,
3141
+ minValue: 0.001,
3142
+ maxValue: 1
3143
+ },
3144
+ get (value) {
3145
+ value.num[0] = this.corneaRoughness;
3146
+ },
3147
+ set (value) {
3148
+ this.corneaRoughness = value.num[0];
3149
+ },
3150
+ getDefaultValue () {
3151
+ return this.$isInstance ? this.coreMaterial.corneaRoughness : 0.05;
3152
+ }
3153
+ },
3154
+ {
3155
+ name: 'vertexTangent',
3156
+ description: 'Whether the mesh supplies tangents; without them refraction is disabled',
3157
+ type: 'bool',
3158
+ default: false,
3159
+ get (value) {
3160
+ value.bool[0] = this.vertexTangent;
3161
+ },
3162
+ set (value) {
3163
+ this.vertexTangent = value.bool[0];
3164
+ },
3165
+ getDefaultValue () {
3166
+ return this.$isInstance ? this.coreMaterial.vertexTangent : false;
3167
+ }
3168
+ },
3169
+ {
3170
+ name: 'SocketOcclusion',
3171
+ description: 'Enables analytic shadowing of the eyeball by the eyelids and socket',
3172
+ type: 'bool',
3173
+ default: false,
3174
+ get (value) {
3175
+ value.bool[0] = this.socketOcclusion;
3176
+ },
3177
+ set (value) {
3178
+ this.socketOcclusion = value.bool[0];
3179
+ },
3180
+ getDefaultValue () {
3181
+ return this.$isInstance ? this.coreMaterial.socketOcclusion : false;
3182
+ }
3183
+ },
3184
+ {
3185
+ name: 'SocketRotation',
3186
+ description: 'Euler rotation in degrees of the socket frame; zero matches +Y up, +Z gaze assets',
3187
+ type: 'vec3',
3188
+ default: [
3189
+ 0,
3190
+ 0,
3191
+ 0
3192
+ ],
3193
+ options: {
3194
+ minValue: -180,
3195
+ maxValue: 180
3196
+ },
3197
+ get (value) {
3198
+ value.num[0] = this.socketRotation.x;
3199
+ value.num[1] = this.socketRotation.y;
3200
+ value.num[2] = this.socketRotation.z;
3201
+ },
3202
+ set (value) {
3203
+ this.socketRotation = new Vector4(value.num[0], value.num[1], value.num[2], 0);
3204
+ },
3205
+ getDefaultValue () {
3206
+ const r = this.$isInstance ? this.coreMaterial.socketRotation : new Vector4(0, 0, 0, 0);
3207
+ return [
3208
+ r.x,
3209
+ r.y,
3210
+ r.z
3211
+ ];
3212
+ }
3213
+ },
3214
+ {
3215
+ name: 'UpperLidAngle',
3216
+ description: 'Aperture half-angle towards the upper lid, in degrees',
3217
+ type: 'float',
3218
+ default: 50,
3219
+ options: {
3220
+ animatable: true,
3221
+ minValue: 5,
3222
+ maxValue: 90
3223
+ },
3224
+ get (value) {
3225
+ value.num[0] = this.upperLidAngle;
3226
+ },
3227
+ set (value) {
3228
+ this.upperLidAngle = value.num[0];
3229
+ },
3230
+ getDefaultValue () {
3231
+ return this.$isInstance ? this.coreMaterial.upperLidAngle : 50;
3232
+ }
3233
+ },
3234
+ {
3235
+ name: 'LowerLidAngle',
3236
+ description: 'Aperture half-angle towards the lower lid, in degrees',
3237
+ type: 'float',
3238
+ default: 65,
3239
+ options: {
3240
+ animatable: true,
3241
+ minValue: 5,
3242
+ maxValue: 90
3243
+ },
3244
+ get (value) {
3245
+ value.num[0] = this.lowerLidAngle;
3246
+ },
3247
+ set (value) {
3248
+ this.lowerLidAngle = value.num[0];
3249
+ },
3250
+ getDefaultValue () {
3251
+ return this.$isInstance ? this.coreMaterial.lowerLidAngle : 65;
3252
+ }
3253
+ },
3254
+ {
3255
+ name: 'SocketOcclusionSoftness',
3256
+ description: 'Width of the lit-to-shadowed transition, in degrees',
3257
+ type: 'float',
3258
+ default: 15,
3259
+ options: {
3260
+ animatable: true,
3261
+ minValue: 1,
3262
+ maxValue: 45
3263
+ },
3264
+ get (value) {
3265
+ value.num[0] = this.socketOcclusionSoftness;
3266
+ },
3267
+ set (value) {
3268
+ this.socketOcclusionSoftness = value.num[0];
3269
+ },
3270
+ getDefaultValue () {
3271
+ return this.$isInstance ? this.coreMaterial.socketOcclusionSoftness : 15;
3272
+ }
3273
+ },
3274
+ {
3275
+ name: 'SocketOcclusionStrength',
3276
+ description: 'Overall socket occlusion strength',
3277
+ type: 'float',
3278
+ default: 0.65,
3279
+ options: {
3280
+ animatable: true,
3281
+ minValue: 0,
3282
+ maxValue: 1
3283
+ },
3284
+ get (value) {
3285
+ value.num[0] = this.socketOcclusionStrength;
3286
+ },
3287
+ set (value) {
3288
+ this.socketOcclusionStrength = value.num[0];
3289
+ },
3290
+ getDefaultValue () {
3291
+ return this.$isInstance ? this.coreMaterial.socketOcclusionStrength : 0.65;
3292
+ }
3293
+ },
3294
+ {
3295
+ name: 'ContactAO',
3296
+ description: 'Enables screen-space contact occlusion of the eyeball by the eyelid, read from the depth prepass',
3297
+ type: 'bool',
3298
+ default: false,
3299
+ get (value) {
3300
+ value.bool[0] = this.contactAO;
3301
+ },
3302
+ set (value) {
3303
+ this.contactAO = value.bool[0];
3304
+ },
3305
+ getDefaultValue () {
3306
+ return this.$isInstance ? this.coreMaterial.contactAO : false;
3307
+ }
3308
+ },
3309
+ {
3310
+ name: 'ContactAORadius',
3311
+ description: 'Radius of the contact occlusion disc, in world units',
3312
+ type: 'float',
3313
+ default: 0.006,
3314
+ options: {
3315
+ animatable: true,
3316
+ minValue: 0.0001,
3317
+ maxValue: 0.1
3318
+ },
3319
+ get (value) {
3320
+ value.num[0] = this.contactAORadius;
3321
+ },
3322
+ set (value) {
3323
+ this.contactAORadius = value.num[0];
3324
+ },
3325
+ getDefaultValue () {
3326
+ return this.$isInstance ? this.coreMaterial.contactAORadius : 0.006;
3327
+ }
3328
+ },
3329
+ {
3330
+ name: 'ContactAOMinDistance',
3331
+ description: 'Smallest depth step counted as an occluder, in world units',
3332
+ type: 'float',
3333
+ default: 0.0004,
3334
+ options: {
3335
+ animatable: true,
3336
+ minValue: 0.00001,
3337
+ maxValue: 0.02
3338
+ },
3339
+ get (value) {
3340
+ value.num[0] = this.contactAOMinDistance;
3341
+ },
3342
+ set (value) {
3343
+ this.contactAOMinDistance = value.num[0];
3344
+ },
3345
+ getDefaultValue () {
3346
+ return this.$isInstance ? this.coreMaterial.contactAOMinDistance : 0.0004;
3347
+ }
3348
+ },
3349
+ {
3350
+ name: 'ContactAOMaxDistance',
3351
+ description: 'Largest depth step counted as an occluder, in world units',
3352
+ type: 'float',
3353
+ default: 0.006,
3354
+ options: {
3355
+ animatable: true,
3356
+ minValue: 0.00001,
3357
+ maxValue: 0.2
3358
+ },
3359
+ get (value) {
3360
+ value.num[0] = this.contactAOMaxDistance;
3361
+ },
3362
+ set (value) {
3363
+ this.contactAOMaxDistance = value.num[0];
3364
+ },
3365
+ getDefaultValue () {
3366
+ return this.$isInstance ? this.coreMaterial.contactAOMaxDistance : 0.006;
3367
+ }
3368
+ },
3369
+ {
3370
+ name: 'ContactAOStrength',
3371
+ description: 'Overall contact occlusion strength',
3372
+ type: 'float',
3373
+ default: 0.7,
3374
+ options: {
3375
+ animatable: true,
3376
+ minValue: 0,
3377
+ maxValue: 1
3378
+ },
3379
+ get (value) {
3380
+ value.num[0] = this.contactAOStrength;
3381
+ },
3382
+ set (value) {
3383
+ this.contactAOStrength = value.num[0];
3384
+ },
3385
+ getDefaultValue () {
3386
+ return this.$isInstance ? this.coreMaterial.contactAOStrength : 0.7;
3387
+ }
3388
+ },
3389
+ {
3390
+ name: 'ContactAOTemporalJitter',
3391
+ description: 'Advances the contact occlusion noise pattern every frame so TAA can integrate it away; enable only with temporal anti-aliasing',
3392
+ type: 'bool',
3393
+ default: false,
3394
+ get (value) {
3395
+ value.bool[0] = this.contactAOTemporalJitter;
3396
+ },
3397
+ set (value) {
3398
+ this.contactAOTemporalJitter = value.bool[0];
3399
+ },
3400
+ getDefaultValue () {
3401
+ return this.$isInstance ? this.coreMaterial.contactAOTemporalJitter : false;
3402
+ }
3403
+ },
3404
+ ...getTextureProps(manager, 'irisTexture', '2D', true, 0),
3405
+ ...getTextureProps(manager, 'scleraTexture', '2D', true, 0)
3406
+ ]);
3407
+ }
3408
+ },
3409
+ getMeshMaterialInstanceUniformsClass(EyeMaterial)
3410
+ ];
3411
+ }
3412
+ /** @internal */ function getPBRMetallicRoughnessMaterialClass(manager) {
3413
+ return [
3414
+ {
3415
+ ctor: PBRMetallicRoughnessMaterial,
3416
+ parent: MeshMaterial,
3417
+ name: 'PBRMetallicRoughnessMaterial',
3418
+ getProps () {
3419
+ return defineProps([
3420
+ {
3421
+ name: 'Metallic',
3422
+ description: 'Metallic value',
3423
+ type: 'float',
3424
+ options: {
3425
+ animatable: true,
3426
+ minValue: 0,
3427
+ maxValue: 1
3428
+ },
3429
+ get (value) {
3430
+ value.num[0] = this.metallic;
3431
+ },
3432
+ set (value) {
3433
+ this.metallic = value.num[0];
3434
+ },
3435
+ isHidden: createBlueprintOutputHiddenPredicate(),
3436
+ getDefaultValue () {
3437
+ return this.$isInstance ? this.coreMaterial.metallic : 1;
3438
+ }
3439
+ },
3440
+ {
3441
+ name: 'Roughness',
3442
+ description: 'Roughness value',
2095
3443
  type: 'float',
2096
3444
  options: {
2097
3445
  animatable: true,
@@ -2160,7 +3508,13 @@ function getMToonMaterialProps(manager) {
2160
3508
  value.str[0] = this.reflectionMode;
2161
3509
  },
2162
3510
  set (value) {
2163
- this.reflectionMode = value.str[0];
3511
+ const reflectionMode = value.str[0];
3512
+ const blueprintInstance = this;
3513
+ if (blueprintInstance.isBlueprintMaterialInstance && blueprintInstance.setBlueprintInstanceReflectionMode) {
3514
+ blueprintInstance.setBlueprintInstanceReflectionMode(reflectionMode);
3515
+ } else {
3516
+ this.reflectionMode = reflectionMode;
3517
+ }
2164
3518
  },
2165
3519
  getDefaultValue () {
2166
3520
  return this.$isInstance ? this.coreMaterial.reflectionMode : 'ggx';
@@ -2243,11 +3597,358 @@ function getMToonMaterialProps(manager) {
2243
3597
  return !this.$isInstance && this.reflectionMode === 'anisotropic' && !!this.anisotropyDirectionTexture;
2244
3598
  }
2245
3599
  },
3600
+ {
3601
+ name: 'SubsurfaceLookPreset',
3602
+ description: 'Per-instance preset override for the active subsurface profile',
3603
+ type: 'string',
3604
+ phase: 1,
3605
+ default: 'skin_default',
3606
+ options: {
3607
+ label: 'LookPreset',
3608
+ enum: {
3609
+ labels: [
3610
+ 'Skin Thin',
3611
+ 'Skin Default',
3612
+ 'Skin HeavyMakeup',
3613
+ 'Wax Backlit',
3614
+ 'Wax Soft',
3615
+ 'Jade Backlit',
3616
+ 'Jade Soft'
3617
+ ],
3618
+ values: [
3619
+ 'skin_thin',
3620
+ 'skin_default',
3621
+ 'skin_heavy_makeup',
3622
+ 'wax_backlit',
3623
+ 'wax_soft',
3624
+ 'jade_backlit',
3625
+ 'jade_soft'
3626
+ ]
3627
+ },
3628
+ group: 'Subsurface Profile'
3629
+ },
3630
+ get (value) {
3631
+ value.str[0] = this.subsurfaceProfile?.preset ?? 'skin_default';
3632
+ },
3633
+ set (value) {
3634
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3635
+ if (profile.isBlueprintMaterialInstance && profile.setBlueprintInstanceSubsurfacePreset) {
3636
+ profile.setBlueprintInstanceSubsurfacePreset(value.str[0]);
3637
+ }
3638
+ },
3639
+ isValid () {
3640
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3641
+ }
3642
+ },
3643
+ {
3644
+ name: 'SubsurfaceMeanFreePathColor',
3645
+ description: 'Per-instance mean free path color override for the active subsurface profile',
3646
+ type: 'rgb',
3647
+ phase: 1,
3648
+ default: [
3649
+ 1,
3650
+ 0.45,
3651
+ 0.17
3652
+ ],
3653
+ options: {
3654
+ label: 'MeanFreePathColor',
3655
+ animatable: true,
3656
+ minValue: 0,
3657
+ maxValue: 1,
3658
+ group: 'Subsurface Profile'
3659
+ },
3660
+ get (value) {
3661
+ value.num[0] = this.subsurfaceProfile?.meanFreePathColor.x ?? 0;
3662
+ value.num[1] = this.subsurfaceProfile?.meanFreePathColor.y ?? 0;
3663
+ value.num[2] = this.subsurfaceProfile?.meanFreePathColor.z ?? 0;
3664
+ },
3665
+ set (value) {
3666
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3667
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceMeanFreePathColor', 'meanFreePathColor', new Vector3(value.num[0], value.num[1], value.num[2]));
3668
+ },
3669
+ isValid () {
3670
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3671
+ }
3672
+ },
3673
+ {
3674
+ name: 'SubsurfaceMeanFreePathDistance',
3675
+ description: 'Per-instance mean free path distance override for the active subsurface profile',
3676
+ type: 'float',
3677
+ phase: 1,
3678
+ default: 0.92,
3679
+ options: {
3680
+ label: 'MeanFreePathDistance',
3681
+ animatable: true,
3682
+ minValue: 0,
3683
+ maxValue: 8,
3684
+ group: 'Subsurface Profile'
3685
+ },
3686
+ get (value) {
3687
+ value.num[0] = this.subsurfaceProfile?.meanFreePathDistance ?? 0;
3688
+ },
3689
+ set (value) {
3690
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3691
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceMeanFreePathDistance', 'meanFreePathDistance', value.num[0]);
3692
+ },
3693
+ isValid () {
3694
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3695
+ }
3696
+ },
3697
+ {
3698
+ name: 'SubsurfaceScatterWeight',
3699
+ description: 'Per-instance scatter weight override for the active subsurface profile',
3700
+ type: 'float',
3701
+ phase: 1,
3702
+ default: 0.82,
3703
+ options: {
3704
+ label: 'ScatterWeight',
3705
+ animatable: true,
3706
+ minValue: 0,
3707
+ maxValue: 8,
3708
+ group: 'Subsurface Profile'
3709
+ },
3710
+ get (value) {
3711
+ value.num[0] = this.subsurfaceProfile?.strength ?? 0;
3712
+ },
3713
+ set (value) {
3714
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3715
+ if (profile.isBlueprintMaterialInstance && profile.setBlueprintInstanceSubsurfaceStrength) {
3716
+ profile.setBlueprintInstanceSubsurfaceStrength(value.num[0]);
3717
+ }
3718
+ },
3719
+ isValid () {
3720
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3721
+ }
3722
+ },
3723
+ {
3724
+ name: 'SubsurfaceScatterScale',
3725
+ description: 'Per-instance scatter scale override for the active subsurface profile',
3726
+ type: 'float',
3727
+ phase: 1,
3728
+ default: 0.96,
3729
+ options: {
3730
+ label: 'ScatterScale',
3731
+ animatable: true,
3732
+ minValue: 0,
3733
+ maxValue: 8,
3734
+ group: 'Subsurface Profile'
3735
+ },
3736
+ get (value) {
3737
+ value.num[0] = this.subsurfaceProfile?.scale ?? 0;
3738
+ },
3739
+ set (value) {
3740
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3741
+ if (profile.isBlueprintMaterialInstance && profile.setBlueprintInstanceSubsurfaceScale) {
3742
+ profile.setBlueprintInstanceSubsurfaceScale(value.num[0]);
3743
+ }
3744
+ },
3745
+ isValid () {
3746
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3747
+ }
3748
+ },
3749
+ {
3750
+ name: 'SubsurfaceWorldUnitScale',
3751
+ description: 'Per-instance world unit scale override for the active subsurface profile',
3752
+ type: 'float',
3753
+ phase: 1,
3754
+ default: 1,
3755
+ options: {
3756
+ label: 'WorldUnitScale',
3757
+ animatable: true,
3758
+ minValue: 0.05,
3759
+ maxValue: 4,
3760
+ group: 'Subsurface Profile'
3761
+ },
3762
+ get (value) {
3763
+ value.num[0] = this.subsurfaceProfile?.worldUnitScale ?? 1;
3764
+ },
3765
+ set (value) {
3766
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3767
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceWorldUnitScale', 'worldUnitScale', value.num[0]);
3768
+ },
3769
+ isValid () {
3770
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3771
+ }
3772
+ },
3773
+ {
3774
+ name: 'SubsurfaceBoundaryColorBleed',
3775
+ description: 'Per-instance boundary color bleed override for the active subsurface profile',
3776
+ type: 'float',
3777
+ phase: 1,
3778
+ default: 0.22,
3779
+ options: {
3780
+ label: 'BoundaryColorBleed',
3781
+ animatable: true,
3782
+ minValue: 0,
3783
+ maxValue: 1,
3784
+ group: 'Subsurface Profile'
3785
+ },
3786
+ get (value) {
3787
+ value.num[0] = this.subsurfaceProfile?.boundaryColorBleed ?? 0;
3788
+ },
3789
+ set (value) {
3790
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3791
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceBoundaryColorBleed', 'boundaryColorBleed', value.num[0]);
3792
+ },
3793
+ isValid () {
3794
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3795
+ }
3796
+ },
3797
+ {
3798
+ name: 'SubsurfaceTransmissionTintColor',
3799
+ description: 'Per-instance transmission tint color override for the active subsurface profile',
3800
+ type: 'rgb',
3801
+ phase: 1,
3802
+ default: [
3803
+ 1,
3804
+ 0.46,
3805
+ 0.34
3806
+ ],
3807
+ options: {
3808
+ label: 'TransmissionTintColor',
3809
+ animatable: true,
3810
+ minValue: 0,
3811
+ maxValue: 1,
3812
+ group: 'Subsurface Profile'
3813
+ },
3814
+ get (value) {
3815
+ value.num[0] = this.subsurfaceProfile?.transmissionTintColor.x ?? 0;
3816
+ value.num[1] = this.subsurfaceProfile?.transmissionTintColor.y ?? 0;
3817
+ value.num[2] = this.subsurfaceProfile?.transmissionTintColor.z ?? 0;
3818
+ },
3819
+ set (value) {
3820
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3821
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceTransmissionTintColor', 'transmissionTintColor', new Vector3(value.num[0], value.num[1], value.num[2]));
3822
+ },
3823
+ isValid () {
3824
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3825
+ }
3826
+ },
3827
+ {
3828
+ name: 'SubsurfaceExtinctionScale',
3829
+ description: 'Per-instance extinction scale override for the active subsurface profile',
3830
+ type: 'float',
3831
+ phase: 1,
3832
+ default: 1.06,
3833
+ options: {
3834
+ label: 'ExtinctionScale',
3835
+ animatable: true,
3836
+ minValue: 0,
3837
+ maxValue: 4,
3838
+ group: 'Subsurface Profile'
3839
+ },
3840
+ get (value) {
3841
+ value.num[0] = this.subsurfaceProfile?.extinctionScale ?? 0;
3842
+ },
3843
+ set (value) {
3844
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3845
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceExtinctionScale', 'extinctionScale', value.num[0]);
3846
+ },
3847
+ isValid () {
3848
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3849
+ }
3850
+ },
3851
+ {
3852
+ name: 'SubsurfaceNormalScale',
3853
+ description: 'Per-instance normal scale override for the active subsurface profile',
3854
+ type: 'float',
3855
+ phase: 1,
3856
+ default: 1,
3857
+ options: {
3858
+ label: 'NormalScale',
3859
+ animatable: true,
3860
+ minValue: 0,
3861
+ maxValue: 2,
3862
+ group: 'Subsurface Profile'
3863
+ },
3864
+ get (value) {
3865
+ value.num[0] = this.subsurfaceProfile?.normalScale ?? 0;
3866
+ },
3867
+ set (value) {
3868
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3869
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceNormalScale', 'normalScale', value.num[0]);
3870
+ },
3871
+ isValid () {
3872
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3873
+ }
3874
+ },
3875
+ {
3876
+ name: 'SubsurfaceScatteringDistribution',
3877
+ description: 'Per-instance scattering distribution override for the active subsurface profile',
3878
+ type: 'float',
3879
+ phase: 1,
3880
+ default: 0.6,
3881
+ options: {
3882
+ label: 'ScatteringDistribution',
3883
+ animatable: true,
3884
+ minValue: 0,
3885
+ maxValue: 1,
3886
+ group: 'Subsurface Profile'
3887
+ },
3888
+ get (value) {
3889
+ value.num[0] = this.subsurfaceProfile?.scatteringDistribution ?? 0;
3890
+ },
3891
+ set (value) {
3892
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3893
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceScatteringDistribution', 'scatteringDistribution', value.num[0]);
3894
+ },
3895
+ isValid () {
3896
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3897
+ }
3898
+ },
3899
+ {
3900
+ name: 'SubsurfaceSpecularDetailSoftness',
3901
+ description: 'Per-instance specular detail softness override for the active subsurface profile',
3902
+ type: 'float',
3903
+ phase: 1,
3904
+ default: 0.78,
3905
+ options: {
3906
+ label: 'SpecularDetailSoftness',
3907
+ animatable: true,
3908
+ minValue: 0,
3909
+ maxValue: 1,
3910
+ group: 'Subsurface Profile'
3911
+ },
3912
+ get (value) {
3913
+ value.num[0] = this.subsurfaceProfile?.specularDetailSoftness ?? 0;
3914
+ },
3915
+ set (value) {
3916
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3917
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceSpecularDetailSoftness', 'specularDetailSoftness', value.num[0]);
3918
+ },
3919
+ isValid () {
3920
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3921
+ }
3922
+ },
3923
+ {
3924
+ name: 'SubsurfaceSpecularDetailRadius',
3925
+ description: 'Per-instance specular detail radius override for the active subsurface profile',
3926
+ type: 'float',
3927
+ phase: 1,
3928
+ default: 1.8,
3929
+ options: {
3930
+ label: 'SpecularDetailRadius',
3931
+ animatable: true,
3932
+ minValue: 0,
3933
+ maxValue: 4,
3934
+ group: 'Subsurface Profile'
3935
+ },
3936
+ get (value) {
3937
+ value.num[0] = this.subsurfaceProfile?.specularDetailRadius ?? 0;
3938
+ },
3939
+ set (value) {
3940
+ const profile = getBlueprintInstanceSubsurfaceMaterial(this);
3941
+ profile.setBlueprintInstanceSubsurfaceProfileValue?.('SubsurfaceSpecularDetailRadius', 'specularDetailRadius', value.num[0]);
3942
+ },
3943
+ isValid () {
3944
+ return canEditBlueprintInstanceSubsurfaceProfile(this);
3945
+ }
3946
+ },
2246
3947
  {
2247
3948
  name: 'SubsurfaceProfile',
2248
3949
  description: 'If true, enables subsurface scattering for translucent materials',
2249
3950
  type: 'object',
2250
- phase: 1,
3951
+ phase: 0,
2251
3952
  default: null,
2252
3953
  options: {
2253
3954
  objectTypes: [
@@ -2264,7 +3965,7 @@ function getMToonMaterialProps(manager) {
2264
3965
  this.subsurfaceProfile = value.object[0] ?? null;
2265
3966
  },
2266
3967
  isValid () {
2267
- return !this.$isInstance;
3968
+ return canEditParentMaterialProperty(this);
2268
3969
  }
2269
3970
  },
2270
3971
  ...getTextureProps(manager, 'subsurfaceTexture', '2D', false, 1, function() {
@@ -2342,5 +4043,5 @@ function getMToonMaterialProps(manager) {
2342
4043
  ];
2343
4044
  }
2344
4045
 
2345
- export { getBlinnMaterialClass, getLambertMaterialClass, getMToonMaterialClass, getMeshMaterialClass, getPBRBluePrintMaterialClass, getPBRMetallicRoughnessMaterialClass, getPBRSpecularGlossinessMaterialClass, getParticleMaterialClass, getSkinMaterialClass, getSpriteBlueprintMaterialClass, getSpriteMaterialClass, getStandardSpriteMaterialClass, getSubsurfaceProfileClass, getUnlitMaterialClass };
4046
+ export { getBlinnMaterialClass, getEyeMaterialClass, getHairMaterialClass, getLambertMaterialClass, getMToonMaterialClass, getMeshMaterialClass, getPBRBluePrintMaterialClass, getPBRBluePrintMaterialInstanceClass, getPBRMetallicRoughnessMaterialClass, getPBRSpecularGlossinessMaterialClass, getParticleMaterialClass, getSkinMaterialClass, getSpriteBlueprintMaterialClass, getSpriteMaterialClass, getStandardSpriteMaterialClass, getSubsurfaceProfileClass, getUnlitMaterialClass };
2346
4047
  //# sourceMappingURL=material.js.map