KHR_materials_volume.js 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { PBRMaterial } from "@babylonjs/core/Materials/PBR/pbrMaterial.js";
  2. import { GLTFLoader } from "../glTFLoader.js";
  3. const NAME = "KHR_materials_volume";
  4. /**
  5. * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md)
  6. * @since 5.0.0
  7. */
  8. // eslint-disable-next-line @typescript-eslint/naming-convention
  9. export class KHR_materials_volume {
  10. /**
  11. * @internal
  12. */
  13. constructor(loader) {
  14. /**
  15. * The name of this extension.
  16. */
  17. this.name = NAME;
  18. /**
  19. * Defines a number that determines the order the extensions are applied.
  20. */
  21. this.order = 173;
  22. this._loader = loader;
  23. this.enabled = this._loader.isExtensionUsed(NAME);
  24. if (this.enabled) {
  25. // We need to disable instance usage because the attenuation factor depends on the node scale of each individual mesh
  26. this._loader._disableInstancedMesh++;
  27. }
  28. }
  29. /** @internal */
  30. dispose() {
  31. if (this.enabled) {
  32. this._loader._disableInstancedMesh--;
  33. }
  34. this._loader = null;
  35. }
  36. /**
  37. * @internal
  38. */
  39. loadMaterialPropertiesAsync(context, material, babylonMaterial) {
  40. return GLTFLoader.LoadExtensionAsync(context, material, this.name, (extensionContext, extension) => {
  41. const promises = new Array();
  42. promises.push(this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
  43. promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));
  44. promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension));
  45. return Promise.all(promises).then(() => { });
  46. });
  47. }
  48. _loadVolumePropertiesAsync(context, material, babylonMaterial, extension) {
  49. if (!(babylonMaterial instanceof PBRMaterial)) {
  50. throw new Error(`${context}: Material type not supported`);
  51. }
  52. // If transparency isn't enabled already, this extension shouldn't do anything.
  53. // i.e. it requires either the KHR_materials_transmission or KHR_materials_translucency extensions.
  54. if ((!babylonMaterial.subSurface.isRefractionEnabled && !babylonMaterial.subSurface.isTranslucencyEnabled) || !extension.thicknessFactor) {
  55. return Promise.resolve();
  56. }
  57. // IOR in this extension only affects interior.
  58. babylonMaterial.subSurface.volumeIndexOfRefraction = babylonMaterial.indexOfRefraction;
  59. const attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE;
  60. babylonMaterial.subSurface.tintColorAtDistance = attenuationDistance;
  61. if (extension.attenuationColor !== undefined && extension.attenuationColor.length == 3) {
  62. babylonMaterial.subSurface.tintColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]);
  63. }
  64. babylonMaterial.subSurface.minimumThickness = 0.0;
  65. babylonMaterial.subSurface.maximumThickness = extension.thicknessFactor;
  66. babylonMaterial.subSurface.useThicknessAsDepth = true;
  67. if (extension.thicknessTexture) {
  68. extension.thicknessTexture.nonColorData = true;
  69. return this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture).then((texture) => {
  70. babylonMaterial.subSurface.thicknessTexture = texture;
  71. babylonMaterial.subSurface.useGltfStyleTextures = true;
  72. });
  73. }
  74. else {
  75. return Promise.resolve();
  76. }
  77. }
  78. }
  79. GLTFLoader.RegisterExtension(NAME, (loader) => new KHR_materials_volume(loader));
  80. //# sourceMappingURL=KHR_materials_volume.js.map