@babylonjs/loaders 9.1.0 → 9.2.0
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.
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +2 -2
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_transmission.js +119 -24
- package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_volume.js +3 -6
- package/glTF/2.0/Extensions/KHR_materials_volume.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js +25 -19
- package/glTF/2.0/Extensions/KHR_materials_volume_scatter.js.map +1 -1
- package/glTF/2.0/glTFLoader.d.ts +1 -0
- package/glTF/2.0/glTFLoader.js +10 -28
- package/glTF/2.0/glTFLoader.js.map +1 -1
- package/glTF/2.0/materialLoadingAdapter.d.ts +21 -10
- package/glTF/2.0/materialLoadingAdapter.js.map +1 -1
- package/glTF/2.0/openpbrMaterialLoadingAdapter.d.ts +31 -17
- package/glTF/2.0/openpbrMaterialLoadingAdapter.js +106 -48
- package/glTF/2.0/openpbrMaterialLoadingAdapter.js.map +1 -1
- package/glTF/2.0/pbrMaterialLoadingAdapter.d.ts +18 -14
- package/glTF/2.0/pbrMaterialLoadingAdapter.js +26 -19
- package/glTF/2.0/pbrMaterialLoadingAdapter.js.map +1 -1
- package/package.json +3 -3
|
@@ -47,7 +47,7 @@ export class KHR_materials_diffuse_transmission {
|
|
|
47
47
|
const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);
|
|
48
48
|
adapter.configureSubsurface();
|
|
49
49
|
adapter.subsurfaceWeight = extension.diffuseTransmissionFactor ?? 0;
|
|
50
|
-
adapter.
|
|
50
|
+
adapter.diffuseTransmissionTint = extension.diffuseTransmissionColorFactor !== undefined ? Color3.FromArray(extension.diffuseTransmissionColorFactor) : Color3.White();
|
|
51
51
|
const promises = new Array();
|
|
52
52
|
if (extension.diffuseTransmissionTexture) {
|
|
53
53
|
extension.diffuseTransmissionTexture.nonColorData = true;
|
|
@@ -59,7 +59,7 @@ export class KHR_materials_diffuse_transmission {
|
|
|
59
59
|
if (extension.diffuseTransmissionColorTexture) {
|
|
60
60
|
promises.push(this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionColorTexture`, extension.diffuseTransmissionColorTexture).then((texture) => {
|
|
61
61
|
texture.name = `${babylonMaterial.name} (Diffuse Transmission Color)`;
|
|
62
|
-
adapter.
|
|
62
|
+
adapter.diffuseTransmissionTintTexture = texture;
|
|
63
63
|
}));
|
|
64
64
|
}
|
|
65
65
|
return Promise.all(promises).then(() => { });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KHR_materials_diffuse_transmission.js","sourceRoot":"","sources":["../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEhG,MAAM,IAAI,GAAG,oCAAoC,CAAC;AAalD;;;GAGG;AACH,gEAAgE;AAChE,MAAM,OAAO,kCAAkC;IAkB3C;;OAEG;IACH,YAAY,MAAkB;QApB9B;;WAEG;QACa,SAAI,GAAG,IAAI,CAAC;QAO5B;;WAEG;QACI,UAAK,GAAG,GAAG,CAAC;QAQf,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,MAAM,CAAC,MAAM,CAAC,sBAAsB,GAAG,IAAI,CAAC;QAChD,CAAC;IACL,CAAC;IAED,gBAAgB;IACT,OAAO;QACT,IAAI,CAAC,OAAe,GAAG,IAAI,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,gDAAgD;IACzC,2BAA2B,CAAC,OAAe,EAAE,QAAmB,EAAE,eAAyB;QAC9F,OAAO,UAAU,CAAC,kBAAkB,CAAmC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,EAAE;YACvI,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAgB,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;YAC5F,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC,gBAAgB,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;YAC5G,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACP,CAAC;IAED,2FAA2F;IACnF,+BAA+B,CAAC,OAAe,EAAE,QAAmB,EAAE,eAAyB,EAAE,SAA2C;QAChJ,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,eAAe,CAAC,CAAC;QAC1E,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAC9B,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,yBAAyB,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"KHR_materials_diffuse_transmission.js","sourceRoot":"","sources":["../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable github/no-then */\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader\";\r\nimport { type IKHRMaterialsDiffuseTransmission } from \"babylonjs-gltf2interface\";\r\nimport { Color3 } from \"core/Maths/math.color\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_diffuse_transmission\";\r\n\r\ndeclare module \"../../glTFFileLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/naming-convention\r\n export interface GLTFLoaderExtensionOptions {\r\n /**\r\n * Defines options for the KHR_materials_diffuse_transmission extension.\r\n */\r\n // NOTE: Don't use NAME here as it will break the UMD type declarations.\r\n [\"KHR_materials_diffuse_transmission\"]: {};\r\n }\r\n}\r\n\r\n/**\r\n * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)\r\n * !!! Experimental Extension Subject to Changes !!!\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_diffuse_transmission implements IGLTFLoaderExtension {\r\n /**\r\n * The name of this extension.\r\n */\r\n public readonly name = NAME;\r\n\r\n /**\r\n * Defines whether this extension is enabled.\r\n */\r\n public enabled: boolean;\r\n\r\n /**\r\n * Defines a number that determines the order the extensions are applied.\r\n */\r\n public order = 174;\r\n\r\n private _loader: GLTFLoader;\r\n\r\n /**\r\n * @internal\r\n */\r\n constructor(loader: GLTFLoader) {\r\n this._loader = loader;\r\n this.enabled = this._loader.isExtensionUsed(NAME);\r\n if (this.enabled) {\r\n loader.parent.transparencyAsCoverage = true;\r\n }\r\n }\r\n\r\n /** @internal */\r\n public dispose() {\r\n (this._loader as any) = null;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n // eslint-disable-next-line no-restricted-syntax\r\n public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n return GLTFLoader.LoadExtensionAsync<IKHRMaterialsDiffuseTransmission>(context, material, this.name, async (extensionContext, extension) => {\r\n const promises = new Array<Promise<any>>();\r\n promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n promises.push(this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n return await Promise.all(promises).then(() => {});\r\n });\r\n }\r\n\r\n // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async\r\n private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsDiffuseTransmission): Promise<void> {\r\n const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n adapter.configureSubsurface();\r\n adapter.subsurfaceWeight = extension.diffuseTransmissionFactor ?? 0;\r\n\r\n adapter.diffuseTransmissionTint = extension.diffuseTransmissionColorFactor !== undefined ? Color3.FromArray(extension.diffuseTransmissionColorFactor) : Color3.White();\r\n\r\n const promises = new Array<Promise<any>>();\r\n\r\n if (extension.diffuseTransmissionTexture) {\r\n (extension.diffuseTransmissionTexture as ITextureInfo).nonColorData = true;\r\n promises.push(\r\n this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionTexture`, extension.diffuseTransmissionTexture).then((texture: BaseTexture) => {\r\n texture.name = `${babylonMaterial.name} (Diffuse Transmission)`;\r\n adapter.subsurfaceWeightTexture = texture;\r\n })\r\n );\r\n }\r\n\r\n if (extension.diffuseTransmissionColorTexture) {\r\n promises.push(\r\n this._loader.loadTextureInfoAsync(`${context}/diffuseTransmissionColorTexture`, extension.diffuseTransmissionColorTexture).then((texture: BaseTexture) => {\r\n texture.name = `${babylonMaterial.name} (Diffuse Transmission Color)`;\r\n adapter.diffuseTransmissionTintTexture = texture;\r\n })\r\n );\r\n }\r\n\r\n return Promise.all(promises).then(() => {});\r\n }\r\n}\r\n\r\nunregisterGLTFExtension(NAME);\r\nregisterGLTFExtension(NAME, true, (loader) => new KHR_materials_diffuse_transmission(loader));\r\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MultiMaterial } from "@babylonjs/core/Materials/multiMaterial.js";
|
|
1
2
|
import { GLTFLoader } from "../glTFLoader.js";
|
|
2
3
|
import { RenderTargetTexture } from "@babylonjs/core/Materials/Textures/renderTargetTexture.js";
|
|
3
4
|
import { Observable } from "@babylonjs/core/Misc/observable.js";
|
|
@@ -33,6 +34,13 @@ class TransmissionHelper {
|
|
|
33
34
|
this._opaqueMeshesCache = [];
|
|
34
35
|
this._transparentMeshesCache = [];
|
|
35
36
|
this._materialObservers = {};
|
|
37
|
+
// For MultiMaterial meshes with mixed opaque/translucent sub-materials:
|
|
38
|
+
// maps mesh → set of materialIndex values that are translucent.
|
|
39
|
+
this._translucentMaterialIndices = new Map();
|
|
40
|
+
// Precomputed opaque-only submesh arrays for mixed meshes, swapped in
|
|
41
|
+
// during the opaque RT render to avoid per-frame allocations.
|
|
42
|
+
this._opaqueOnlySubMeshes = new Map();
|
|
43
|
+
this._savedSubMeshes = new Map();
|
|
36
44
|
this._options = {
|
|
37
45
|
...TransmissionHelper._GetDefaultOptions(),
|
|
38
46
|
...options,
|
|
@@ -82,23 +90,92 @@ class TransmissionHelper {
|
|
|
82
90
|
getOpaqueTarget() {
|
|
83
91
|
return this._opaqueRenderTarget;
|
|
84
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Classify a mesh's materials as transparent, opaque, or mixed.
|
|
95
|
+
* Sets the refraction background texture on any translucent materials found.
|
|
96
|
+
* For mixed MultiMaterial meshes, populates _translucentMaterialIndices so
|
|
97
|
+
* their translucent submeshes can be excluded from the opaque render target.
|
|
98
|
+
* @param mesh - The mesh to classify
|
|
99
|
+
* @returns 'transparent' if all materials are translucent, 'opaque' if none are, 'mixed' if both
|
|
100
|
+
*/
|
|
101
|
+
_classifyMeshMaterials(mesh) {
|
|
102
|
+
const material = mesh.material;
|
|
103
|
+
if (!material) {
|
|
104
|
+
return "opaque";
|
|
105
|
+
}
|
|
106
|
+
// Single material case
|
|
107
|
+
if (!(material instanceof MultiMaterial)) {
|
|
108
|
+
if (!this._loader.isMatchingMaterialType(material)) {
|
|
109
|
+
return "opaque";
|
|
110
|
+
}
|
|
111
|
+
const adapter = this._loader._getOrCreateMaterialAdapter(material);
|
|
112
|
+
if (adapter.isTranslucent()) {
|
|
113
|
+
adapter.refractionBackgroundTexture = this._opaqueRenderTarget;
|
|
114
|
+
return "transparent";
|
|
115
|
+
}
|
|
116
|
+
return "opaque";
|
|
117
|
+
}
|
|
118
|
+
// MultiMaterial case: check each sub-material individually
|
|
119
|
+
let hasTranslucent = false;
|
|
120
|
+
let hasOpaque = false;
|
|
121
|
+
const translucentIndices = new Set();
|
|
122
|
+
for (let i = 0; i < material.subMaterials.length; i++) {
|
|
123
|
+
const subMat = material.subMaterials[i];
|
|
124
|
+
if (!subMat) {
|
|
125
|
+
hasOpaque = true;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (this._loader.isMatchingMaterialType(subMat)) {
|
|
129
|
+
const adapter = this._loader._getOrCreateMaterialAdapter(subMat);
|
|
130
|
+
if (adapter.isTranslucent()) {
|
|
131
|
+
adapter.refractionBackgroundTexture = this._opaqueRenderTarget;
|
|
132
|
+
hasTranslucent = true;
|
|
133
|
+
translucentIndices.add(i);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
hasOpaque = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
hasOpaque = true;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (hasTranslucent && hasOpaque) {
|
|
144
|
+
this._translucentMaterialIndices.set(mesh, translucentIndices);
|
|
145
|
+
this._rebuildOpaqueOnlySubMeshes(mesh, translucentIndices);
|
|
146
|
+
return "mixed";
|
|
147
|
+
}
|
|
148
|
+
this._translucentMaterialIndices.delete(mesh);
|
|
149
|
+
this._opaqueOnlySubMeshes.delete(mesh);
|
|
150
|
+
return hasTranslucent ? "transparent" : "opaque";
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Rebuild the cached opaque-only submesh array for a mixed mesh.
|
|
154
|
+
* Called when classification changes so the per-frame swap is allocation-free.
|
|
155
|
+
* @param mesh - The mesh to rebuild for
|
|
156
|
+
* @param translucentIndices - Set of materialIndex values that are translucent
|
|
157
|
+
*/
|
|
158
|
+
_rebuildOpaqueOnlySubMeshes(mesh, translucentIndices) {
|
|
159
|
+
if (mesh.subMeshes) {
|
|
160
|
+
this._opaqueOnlySubMeshes.set(mesh, mesh.subMeshes.filter((sm) => !translucentIndices.has(sm.materialIndex)));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
85
163
|
_addMesh(mesh) {
|
|
86
164
|
this._materialObservers[mesh.uniqueId] = mesh.onMaterialChangedObservable.add(this._onMeshMaterialChanged.bind(this));
|
|
87
165
|
// we need to defer the processing because _addMesh may be called as part as an instance mesh creation, in which case some
|
|
88
166
|
// internal properties are not setup yet, like _sourceMesh (needed when doing mesh.material below)
|
|
89
167
|
Tools.SetImmediate(() => {
|
|
90
168
|
if (mesh.material) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
const adapter = this._loader._getOrCreateMaterialAdapter(mesh.material);
|
|
95
|
-
if (adapter.transmissionWeight > 0) {
|
|
96
|
-
adapter.refractionBackgroundTexture = this._opaqueRenderTarget;
|
|
169
|
+
const classification = this._classifyMeshMaterials(mesh);
|
|
170
|
+
if (classification === "transparent") {
|
|
97
171
|
if (this._transparentMeshesCache.indexOf(mesh) === -1) {
|
|
98
172
|
this._transparentMeshesCache.push(mesh);
|
|
99
173
|
}
|
|
100
174
|
}
|
|
101
175
|
else {
|
|
176
|
+
// Both 'opaque' and 'mixed' go in the opaque cache.
|
|
177
|
+
// For 'mixed', the translucent submeshes are temporarily
|
|
178
|
+
// excluded during the opaque render target render.
|
|
102
179
|
if (this._opaqueMeshesCache.indexOf(mesh) === -1) {
|
|
103
180
|
this._opaqueMeshesCache.push(mesh);
|
|
104
181
|
}
|
|
@@ -117,6 +194,8 @@ class TransmissionHelper {
|
|
|
117
194
|
if (idx !== -1) {
|
|
118
195
|
this._opaqueMeshesCache.splice(idx, 1);
|
|
119
196
|
}
|
|
197
|
+
this._translucentMaterialIndices.delete(mesh);
|
|
198
|
+
this._opaqueOnlySubMeshes.delete(mesh);
|
|
120
199
|
}
|
|
121
200
|
_parseScene() {
|
|
122
201
|
this._scene.meshes.forEach(this._addMesh.bind(this));
|
|
@@ -129,16 +208,9 @@ class TransmissionHelper {
|
|
|
129
208
|
_onMeshMaterialChanged(mesh) {
|
|
130
209
|
const transparentIdx = this._transparentMeshesCache.indexOf(mesh);
|
|
131
210
|
const opaqueIdx = this._opaqueMeshesCache.indexOf(mesh);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// If the material is transparent, make sure that it's added to the transparent list and removed from the opaque list
|
|
136
|
-
const adapter = mesh.material ? this._loader._getOrCreateMaterialAdapter(mesh.material) : null;
|
|
137
|
-
const useTransmission = adapter ? adapter.transmissionWeight > 0 : false;
|
|
138
|
-
if (useTransmission) {
|
|
139
|
-
if (adapter) {
|
|
140
|
-
adapter.refractionBackgroundTexture = this._opaqueRenderTarget;
|
|
141
|
-
}
|
|
211
|
+
const classification = this._classifyMeshMaterials(mesh);
|
|
212
|
+
if (classification === "transparent") {
|
|
213
|
+
// Fully translucent: move to transparent cache
|
|
142
214
|
if (opaqueIdx !== -1) {
|
|
143
215
|
this._opaqueMeshesCache.splice(opaqueIdx, 1);
|
|
144
216
|
this._transparentMeshesCache.push(mesh);
|
|
@@ -146,9 +218,10 @@ class TransmissionHelper {
|
|
|
146
218
|
else if (transparentIdx === -1) {
|
|
147
219
|
this._transparentMeshesCache.push(mesh);
|
|
148
220
|
}
|
|
149
|
-
// If the material is opaque, make sure that it's added to the opaque list and removed from the transparent list
|
|
150
221
|
}
|
|
151
222
|
else {
|
|
223
|
+
// Opaque or mixed: move to opaque cache (mixed meshes have their
|
|
224
|
+
// translucent submeshes excluded during opaque RT render)
|
|
152
225
|
if (transparentIdx !== -1) {
|
|
153
226
|
this._transparentMeshesCache.splice(transparentIdx, 1);
|
|
154
227
|
this._opaqueMeshesCache.push(mesh);
|
|
@@ -195,19 +268,38 @@ class TransmissionHelper {
|
|
|
195
268
|
else {
|
|
196
269
|
opaqueRenderTarget.clearColor.copyFrom(this._options.clearColor);
|
|
197
270
|
}
|
|
271
|
+
// For mixed MultiMaterial meshes, swap in the precomputed opaque-only
|
|
272
|
+
// submesh array so translucent submeshes don't render into the opaque texture.
|
|
273
|
+
const tlEntries = this._opaqueOnlySubMeshes.entries();
|
|
274
|
+
for (let tlEntry = tlEntries.next(); !tlEntry.done; tlEntry = tlEntries.next()) {
|
|
275
|
+
const mesh = tlEntry.value[0];
|
|
276
|
+
const opaqueOnly = tlEntry.value[1];
|
|
277
|
+
if (mesh.subMeshes) {
|
|
278
|
+
this._savedSubMeshes.set(mesh, mesh.subMeshes);
|
|
279
|
+
mesh.subMeshes = opaqueOnly;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
198
282
|
});
|
|
199
283
|
this._opaqueRenderTarget.onAfterUnbindObservable.add(() => {
|
|
200
284
|
this._scene.environmentIntensity = saveSceneEnvIntensity;
|
|
285
|
+
// Restore the full submesh list after the opaque RT render
|
|
286
|
+
const savedEntries = this._savedSubMeshes.entries();
|
|
287
|
+
for (let savedEntry = savedEntries.next(); !savedEntry.done; savedEntry = savedEntries.next()) {
|
|
288
|
+
savedEntry.value[0].subMeshes = savedEntry.value[1];
|
|
289
|
+
}
|
|
290
|
+
this._savedSubMeshes.clear();
|
|
201
291
|
});
|
|
292
|
+
// Update refraction textures on transparent and mixed meshes
|
|
202
293
|
for (const mesh of this._transparentMeshesCache) {
|
|
203
294
|
if (mesh.material) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
295
|
+
this._classifyMeshMaterials(mesh);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const mixedEntries = this._translucentMaterialIndices.entries();
|
|
299
|
+
for (let mixedEntry = mixedEntries.next(); !mixedEntry.done; mixedEntry = mixedEntries.next()) {
|
|
300
|
+
const mesh = mixedEntry.value[0];
|
|
301
|
+
if (mesh.material) {
|
|
302
|
+
this._classifyMeshMaterials(mesh);
|
|
211
303
|
}
|
|
212
304
|
}
|
|
213
305
|
}
|
|
@@ -222,6 +314,9 @@ class TransmissionHelper {
|
|
|
222
314
|
}
|
|
223
315
|
this._transparentMeshesCache = [];
|
|
224
316
|
this._opaqueMeshesCache = [];
|
|
317
|
+
this._translucentMaterialIndices.clear();
|
|
318
|
+
this._opaqueOnlySubMeshes.clear();
|
|
319
|
+
this._savedSubMeshes.clear();
|
|
225
320
|
}
|
|
226
321
|
}
|
|
227
322
|
const NAME = "KHR_materials_transmission";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KHR_materials_transmission.js","sourceRoot":"","sources":["../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader\";\r\nimport { type IKHRMaterialsTransmission } from \"babylonjs-gltf2interface\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { type Texture } from \"core/Materials/Textures/texture\";\r\nimport { RenderTargetTexture } from \"core/Materials/Textures/renderTargetTexture\";\r\nimport { type Observer, Observable } from \"core/Misc/observable\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport { type Color4 } from \"core/Maths/math.color\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\ninterface ITransmissionHelperHolder {\r\n /**\r\n * @internal\r\n */\r\n _transmissionHelper: TransmissionHelper | undefined;\r\n}\r\n\r\ninterface ITransmissionHelperOptions {\r\n /**\r\n * The size of the render buffers (default: 1024)\r\n */\r\n renderSize: number;\r\n\r\n /**\r\n * The number of samples to use when generating the render target texture for opaque meshes (default: 4)\r\n */\r\n samples: number;\r\n\r\n /**\r\n * Scale to apply when selecting the LOD level to sample the refraction texture (default: 1)\r\n */\r\n lodGenerationScale: number;\r\n\r\n /**\r\n * Offset to apply when selecting the LOD level to sample the refraction texture (default: -4)\r\n */\r\n lodGenerationOffset: number;\r\n\r\n /**\r\n * Type of the refraction render target texture (default: TEXTURETYPE_HALF_FLOAT)\r\n */\r\n renderTargetTextureType: number;\r\n\r\n /**\r\n * Defines if the mipmaps for the refraction render target texture must be generated (default: true)\r\n */\r\n generateMipmaps: boolean;\r\n\r\n /**\r\n * Clear color of the opaque texture. If not provided, use the scene clear color (which will be converted to linear space).\r\n * If provided, should be in linear space\r\n */\r\n clearColor?: Color4;\r\n}\r\n\r\n/**\r\n * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects.\r\n */\r\nclass TransmissionHelper {\r\n /**\r\n * Creates the default options for the helper.\r\n * @returns the default options\r\n */\r\n private static _GetDefaultOptions(): ITransmissionHelperOptions {\r\n return {\r\n renderSize: 1024,\r\n samples: 4,\r\n lodGenerationScale: 1,\r\n lodGenerationOffset: -4,\r\n renderTargetTextureType: Constants.TEXTURETYPE_HALF_FLOAT,\r\n generateMipmaps: true,\r\n };\r\n }\r\n\r\n /**\r\n * Stores the creation options.\r\n */\r\n private readonly _scene: Scene & ITransmissionHelperHolder;\r\n\r\n private _options: ITransmissionHelperOptions;\r\n\r\n private _opaqueRenderTarget: Nullable<RenderTargetTexture> = null;\r\n private _opaqueMeshesCache: AbstractMesh[] = [];\r\n private _transparentMeshesCache: AbstractMesh[] = [];\r\n private _materialObservers: { [id: string]: Nullable<Observer<AbstractMesh>> } = {};\r\n private _loader: GLTFLoader;\r\n\r\n /**\r\n * This observable will be notified with any error during the creation of the environment,\r\n * mainly texture creation errors.\r\n */\r\n public onErrorObservable: Observable<{ message?: string; exception?: any }>;\r\n\r\n /**\r\n * constructor\r\n * @param options Defines the options we want to customize the helper\r\n * @param scene The scene to add the material to\r\n * @param loader The glTF loader loading the asset\r\n */\r\n constructor(options: Partial<ITransmissionHelperOptions>, scene: Scene, loader: GLTFLoader) {\r\n this._options = {\r\n ...TransmissionHelper._GetDefaultOptions(),\r\n ...options,\r\n };\r\n this._scene = scene as any;\r\n this._scene._transmissionHelper = this;\r\n this._loader = loader;\r\n\r\n this.onErrorObservable = new Observable();\r\n this._scene.onDisposeObservable.addOnce(() => {\r\n this.dispose();\r\n });\r\n\r\n this._parseScene();\r\n this._setupRenderTargets();\r\n }\r\n\r\n /**\r\n * Updates the background according to the new options\r\n * @param options\r\n */\r\n public updateOptions(options: Partial<ITransmissionHelperOptions>) {\r\n // First check if any options are actually being changed. If not, exit.\r\n const newValues = Object.keys(options).filter((key: string) => (this._options as any)[key] !== (options as any)[key]);\r\n if (!newValues.length) {\r\n return;\r\n }\r\n\r\n const newOptions = {\r\n ...this._options,\r\n ...options,\r\n };\r\n\r\n const oldOptions = this._options;\r\n this._options = newOptions;\r\n\r\n // If size changes, recreate everything\r\n if (\r\n newOptions.renderSize !== oldOptions.renderSize ||\r\n newOptions.renderTargetTextureType !== oldOptions.renderTargetTextureType ||\r\n newOptions.generateMipmaps !== oldOptions.generateMipmaps ||\r\n !this._opaqueRenderTarget\r\n ) {\r\n this._setupRenderTargets();\r\n } else {\r\n this._opaqueRenderTarget.samples = newOptions.samples;\r\n this._opaqueRenderTarget.lodGenerationScale = newOptions.lodGenerationScale;\r\n this._opaqueRenderTarget.lodGenerationOffset = newOptions.lodGenerationOffset;\r\n }\r\n }\r\n\r\n /**\r\n * @returns the opaque render target texture or null if not available.\r\n */\r\n public getOpaqueTarget(): Nullable<Texture> {\r\n return this._opaqueRenderTarget;\r\n }\r\n\r\n private _addMesh(mesh: AbstractMesh): void {\r\n this._materialObservers[mesh.uniqueId] = mesh.onMaterialChangedObservable.add(this._onMeshMaterialChanged.bind(this));\r\n\r\n // we need to defer the processing because _addMesh may be called as part as an instance mesh creation, in which case some\r\n // internal properties are not setup yet, like _sourceMesh (needed when doing mesh.material below)\r\n Tools.SetImmediate(() => {\r\n if (mesh.material) {\r\n if (!this._loader.isMatchingMaterialType(mesh.material)) {\r\n return;\r\n }\r\n const adapter = this._loader._getOrCreateMaterialAdapter(mesh.material);\r\n if (adapter.transmissionWeight > 0) {\r\n adapter.refractionBackgroundTexture = this._opaqueRenderTarget;\r\n if (this._transparentMeshesCache.indexOf(mesh) === -1) {\r\n this._transparentMeshesCache.push(mesh);\r\n }\r\n } else {\r\n if (this._opaqueMeshesCache.indexOf(mesh) === -1) {\r\n this._opaqueMeshesCache.push(mesh);\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n private _removeMesh(mesh: AbstractMesh): void {\r\n mesh.onMaterialChangedObservable.remove(this._materialObservers[mesh.uniqueId]);\r\n delete this._materialObservers[mesh.uniqueId];\r\n let idx = this._transparentMeshesCache.indexOf(mesh);\r\n if (idx !== -1) {\r\n this._transparentMeshesCache.splice(idx, 1);\r\n }\r\n idx = this._opaqueMeshesCache.indexOf(mesh);\r\n if (idx !== -1) {\r\n this._opaqueMeshesCache.splice(idx, 1);\r\n }\r\n }\r\n\r\n private _parseScene(): void {\r\n this._scene.meshes.forEach(this._addMesh.bind(this));\r\n // Listen for when a mesh is added to the scene and add it to our cache lists.\r\n this._scene.onNewMeshAddedObservable.add(this._addMesh.bind(this));\r\n // Listen for when a mesh is removed from to the scene and remove it from our cache lists.\r\n this._scene.onMeshRemovedObservable.add(this._removeMesh.bind(this));\r\n }\r\n\r\n // When one of the meshes in the scene has its material changed, make sure that it's in the correct cache list.\r\n private _onMeshMaterialChanged(mesh: AbstractMesh) {\r\n const transparentIdx = this._transparentMeshesCache.indexOf(mesh);\r\n const opaqueIdx = this._opaqueMeshesCache.indexOf(mesh);\r\n\r\n if (!this._loader.isMatchingMaterialType(mesh.material)) {\r\n return;\r\n }\r\n // If the material is transparent, make sure that it's added to the transparent list and removed from the opaque list\r\n const adapter = mesh.material ? this._loader._getOrCreateMaterialAdapter(mesh.material) : null;\r\n const useTransmission = adapter ? adapter.transmissionWeight > 0 : false;\r\n\r\n if (useTransmission) {\r\n if (adapter) {\r\n adapter.refractionBackgroundTexture = this._opaqueRenderTarget;\r\n }\r\n if (opaqueIdx !== -1) {\r\n this._opaqueMeshesCache.splice(opaqueIdx, 1);\r\n this._transparentMeshesCache.push(mesh);\r\n } else if (transparentIdx === -1) {\r\n this._transparentMeshesCache.push(mesh);\r\n }\r\n // If the material is opaque, make sure that it's added to the opaque list and removed from the transparent list\r\n } else {\r\n if (transparentIdx !== -1) {\r\n this._transparentMeshesCache.splice(transparentIdx, 1);\r\n this._opaqueMeshesCache.push(mesh);\r\n } else if (opaqueIdx === -1) {\r\n this._opaqueMeshesCache.push(mesh);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @internal\r\n * Check if the opaque render target has not been disposed and can still be used.\r\n * @returns\r\n */\r\n public _isRenderTargetValid() {\r\n return this._opaqueRenderTarget?.getInternalTexture() !== null;\r\n }\r\n\r\n /**\r\n * @internal\r\n * Setup the render targets according to the specified options.\r\n */\r\n public _setupRenderTargets(): void {\r\n if (this._opaqueRenderTarget) {\r\n this._opaqueRenderTarget.dispose();\r\n }\r\n this._opaqueRenderTarget = new RenderTargetTexture(\r\n \"opaqueSceneTexture\",\r\n this._options.renderSize,\r\n this._scene,\r\n this._options.generateMipmaps,\r\n undefined,\r\n this._options.renderTargetTextureType\r\n );\r\n this._opaqueRenderTarget.ignoreCameraViewport = true;\r\n this._opaqueRenderTarget.renderList = this._opaqueMeshesCache;\r\n this._opaqueRenderTarget.clearColor = this._options.clearColor?.clone() ?? this._scene.clearColor.clone();\r\n this._opaqueRenderTarget.gammaSpace = false;\r\n this._opaqueRenderTarget.lodGenerationScale = this._options.lodGenerationScale;\r\n this._opaqueRenderTarget.lodGenerationOffset = this._options.lodGenerationOffset;\r\n this._opaqueRenderTarget.samples = this._options.samples;\r\n this._opaqueRenderTarget.renderSprites = true;\r\n this._opaqueRenderTarget.renderParticles = true;\r\n this._opaqueRenderTarget.disableImageProcessing = true;\r\n\r\n let saveSceneEnvIntensity: number;\r\n this._opaqueRenderTarget.onBeforeBindObservable.add((opaqueRenderTarget) => {\r\n saveSceneEnvIntensity = this._scene.environmentIntensity;\r\n this._scene.environmentIntensity = 1.0;\r\n if (!this._options.clearColor) {\r\n this._scene.clearColor.toLinearSpaceToRef(opaqueRenderTarget.clearColor, this._scene.getEngine().useExactSrgbConversions);\r\n } else {\r\n opaqueRenderTarget.clearColor.copyFrom(this._options.clearColor);\r\n }\r\n });\r\n this._opaqueRenderTarget.onAfterUnbindObservable.add(() => {\r\n this._scene.environmentIntensity = saveSceneEnvIntensity;\r\n });\r\n\r\n for (const mesh of this._transparentMeshesCache) {\r\n if (mesh.material) {\r\n if (!this._loader.isMatchingMaterialType(mesh.material)) {\r\n return;\r\n }\r\n const adapter = this._loader._getOrCreateMaterialAdapter(mesh.material);\r\n if (adapter.transmissionWeight > 0) {\r\n adapter.refractionBackgroundTexture = this._opaqueRenderTarget;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Dispose all the elements created by the Helper.\r\n */\r\n public dispose(): void {\r\n this._scene._transmissionHelper = undefined;\r\n if (this._opaqueRenderTarget) {\r\n this._opaqueRenderTarget.dispose();\r\n this._opaqueRenderTarget = null;\r\n }\r\n this._transparentMeshesCache = [];\r\n this._opaqueMeshesCache = [];\r\n }\r\n}\r\n\r\nconst NAME = \"KHR_materials_transmission\";\r\n\r\ndeclare module \"../../glTFFileLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/naming-convention\r\n export interface GLTFLoaderExtensionOptions {\r\n /**\r\n * Defines options for the KHR_materials_transmission extension.\r\n */\r\n // NOTE: Don't use NAME here as it will break the UMD type declarations.\r\n [\"KHR_materials_transmission\"]: {};\r\n }\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_transmission/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_transmission implements IGLTFLoaderExtension {\r\n /**\r\n * The name of this extension.\r\n */\r\n public readonly name = NAME;\r\n\r\n /**\r\n * Defines whether this extension is enabled.\r\n */\r\n public enabled: boolean;\r\n\r\n /**\r\n * Defines a number that determines the order the extensions are applied.\r\n */\r\n public order = 175;\r\n\r\n private _loader: GLTFLoader;\r\n\r\n /**\r\n * @internal\r\n */\r\n constructor(loader: GLTFLoader) {\r\n this._loader = loader;\r\n this.enabled = this._loader.isExtensionUsed(NAME);\r\n if (this.enabled) {\r\n loader.parent.transparencyAsCoverage = true;\r\n }\r\n }\r\n\r\n /** @internal */\r\n public dispose() {\r\n (this._loader as any) = null;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n // eslint-disable-next-line no-restricted-syntax\r\n public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n return GLTFLoader.LoadExtensionAsync<IKHRMaterialsTransmission>(context, material, this.name, async (extensionContext, extension) => {\r\n const promises = new Array<Promise<any>>();\r\n promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n // eslint-disable-next-line github/no-then\r\n return await Promise.all(promises).then(() => {});\r\n });\r\n }\r\n\r\n // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async\r\n private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise<void> {\r\n const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n const transmissionWeight = extension.transmissionFactor !== undefined ? extension.transmissionFactor : 0.0;\r\n\r\n if (transmissionWeight === 0 || !adapter) {\r\n return Promise.resolve();\r\n }\r\n\r\n // Set transmission properties immediately via adapter\r\n adapter.configureTransmission();\r\n adapter.transmissionWeight = transmissionWeight;\r\n\r\n // Handle transmission helper setup (only needed for PBR materials)\r\n if (transmissionWeight > 0 && !this._loader.parent.dontUseTransmissionHelper) {\r\n const scene = babylonMaterial.getScene() as unknown as ITransmissionHelperHolder;\r\n if (!scene._transmissionHelper) {\r\n new TransmissionHelper({}, babylonMaterial.getScene(), this._loader);\r\n } else if (!scene._transmissionHelper?._isRenderTargetValid()) {\r\n // If the render target is not valid, recreate it.\r\n scene._transmissionHelper?._setupRenderTargets();\r\n }\r\n }\r\n\r\n // Load texture if present\r\n let texturePromise: Promise<Nullable<BaseTexture>> = Promise.resolve(null);\r\n if (extension.transmissionTexture) {\r\n (extension.transmissionTexture as ITextureInfo).nonColorData = true;\r\n texturePromise = this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, (texture: BaseTexture) => {\r\n texture.name = `${babylonMaterial.name} (Transmission)`;\r\n adapter.transmissionWeightTexture = texture;\r\n });\r\n }\r\n\r\n // eslint-disable-next-line github/no-then\r\n return texturePromise.then(() => {});\r\n }\r\n}\r\n\r\nunregisterGLTFExtension(NAME);\r\nregisterGLTFExtension(NAME, true, (loader) => new KHR_materials_transmission(loader));\r\n"]}
|
|
1
|
+
{"version":3,"file":"KHR_materials_transmission.js","sourceRoot":"","sources":["../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { MultiMaterial } from \"core/Materials/multiMaterial\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader\";\r\nimport { type IKHRMaterialsTransmission } from \"babylonjs-gltf2interface\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { type SubMesh } from \"core/Meshes/subMesh\";\r\nimport { type Texture } from \"core/Materials/Textures/texture\";\r\nimport { RenderTargetTexture } from \"core/Materials/Textures/renderTargetTexture\";\r\nimport { type Observer, Observable } from \"core/Misc/observable\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport { type Color4 } from \"core/Maths/math.color\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\ninterface ITransmissionHelperHolder {\r\n /**\r\n * @internal\r\n */\r\n _transmissionHelper: TransmissionHelper | undefined;\r\n}\r\n\r\ninterface ITransmissionHelperOptions {\r\n /**\r\n * The size of the render buffers (default: 1024)\r\n */\r\n renderSize: number;\r\n\r\n /**\r\n * The number of samples to use when generating the render target texture for opaque meshes (default: 4)\r\n */\r\n samples: number;\r\n\r\n /**\r\n * Scale to apply when selecting the LOD level to sample the refraction texture (default: 1)\r\n */\r\n lodGenerationScale: number;\r\n\r\n /**\r\n * Offset to apply when selecting the LOD level to sample the refraction texture (default: -4)\r\n */\r\n lodGenerationOffset: number;\r\n\r\n /**\r\n * Type of the refraction render target texture (default: TEXTURETYPE_HALF_FLOAT)\r\n */\r\n renderTargetTextureType: number;\r\n\r\n /**\r\n * Defines if the mipmaps for the refraction render target texture must be generated (default: true)\r\n */\r\n generateMipmaps: boolean;\r\n\r\n /**\r\n * Clear color of the opaque texture. If not provided, use the scene clear color (which will be converted to linear space).\r\n * If provided, should be in linear space\r\n */\r\n clearColor?: Color4;\r\n}\r\n\r\n/**\r\n * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects.\r\n */\r\nclass TransmissionHelper {\r\n /**\r\n * Creates the default options for the helper.\r\n * @returns the default options\r\n */\r\n private static _GetDefaultOptions(): ITransmissionHelperOptions {\r\n return {\r\n renderSize: 1024,\r\n samples: 4,\r\n lodGenerationScale: 1,\r\n lodGenerationOffset: -4,\r\n renderTargetTextureType: Constants.TEXTURETYPE_HALF_FLOAT,\r\n generateMipmaps: true,\r\n };\r\n }\r\n\r\n /**\r\n * Stores the creation options.\r\n */\r\n private readonly _scene: Scene & ITransmissionHelperHolder;\r\n\r\n private _options: ITransmissionHelperOptions;\r\n\r\n private _opaqueRenderTarget: Nullable<RenderTargetTexture> = null;\r\n private _opaqueMeshesCache: AbstractMesh[] = [];\r\n private _transparentMeshesCache: AbstractMesh[] = [];\r\n private _materialObservers: { [id: string]: Nullable<Observer<AbstractMesh>> } = {};\r\n private _loader: GLTFLoader;\r\n\r\n // For MultiMaterial meshes with mixed opaque/translucent sub-materials:\r\n // maps mesh → set of materialIndex values that are translucent.\r\n private _translucentMaterialIndices: Map<AbstractMesh, Set<number>> = new Map();\r\n // Precomputed opaque-only submesh arrays for mixed meshes, swapped in\r\n // during the opaque RT render to avoid per-frame allocations.\r\n private _opaqueOnlySubMeshes: Map<AbstractMesh, SubMesh[]> = new Map();\r\n private _savedSubMeshes: Map<AbstractMesh, SubMesh[]> = new Map();\r\n\r\n /**\r\n * This observable will be notified with any error during the creation of the environment,\r\n * mainly texture creation errors.\r\n */\r\n public onErrorObservable: Observable<{ message?: string; exception?: any }>;\r\n\r\n /**\r\n * constructor\r\n * @param options Defines the options we want to customize the helper\r\n * @param scene The scene to add the material to\r\n * @param loader The glTF loader loading the asset\r\n */\r\n constructor(options: Partial<ITransmissionHelperOptions>, scene: Scene, loader: GLTFLoader) {\r\n this._options = {\r\n ...TransmissionHelper._GetDefaultOptions(),\r\n ...options,\r\n };\r\n this._scene = scene as any;\r\n this._scene._transmissionHelper = this;\r\n this._loader = loader;\r\n\r\n this.onErrorObservable = new Observable();\r\n this._scene.onDisposeObservable.addOnce(() => {\r\n this.dispose();\r\n });\r\n\r\n this._parseScene();\r\n this._setupRenderTargets();\r\n }\r\n\r\n /**\r\n * Updates the background according to the new options\r\n * @param options\r\n */\r\n public updateOptions(options: Partial<ITransmissionHelperOptions>) {\r\n // First check if any options are actually being changed. If not, exit.\r\n const newValues = Object.keys(options).filter((key: string) => (this._options as any)[key] !== (options as any)[key]);\r\n if (!newValues.length) {\r\n return;\r\n }\r\n\r\n const newOptions = {\r\n ...this._options,\r\n ...options,\r\n };\r\n\r\n const oldOptions = this._options;\r\n this._options = newOptions;\r\n\r\n // If size changes, recreate everything\r\n if (\r\n newOptions.renderSize !== oldOptions.renderSize ||\r\n newOptions.renderTargetTextureType !== oldOptions.renderTargetTextureType ||\r\n newOptions.generateMipmaps !== oldOptions.generateMipmaps ||\r\n !this._opaqueRenderTarget\r\n ) {\r\n this._setupRenderTargets();\r\n } else {\r\n this._opaqueRenderTarget.samples = newOptions.samples;\r\n this._opaqueRenderTarget.lodGenerationScale = newOptions.lodGenerationScale;\r\n this._opaqueRenderTarget.lodGenerationOffset = newOptions.lodGenerationOffset;\r\n }\r\n }\r\n\r\n /**\r\n * @returns the opaque render target texture or null if not available.\r\n */\r\n public getOpaqueTarget(): Nullable<Texture> {\r\n return this._opaqueRenderTarget;\r\n }\r\n\r\n /**\r\n * Classify a mesh's materials as transparent, opaque, or mixed.\r\n * Sets the refraction background texture on any translucent materials found.\r\n * For mixed MultiMaterial meshes, populates _translucentMaterialIndices so\r\n * their translucent submeshes can be excluded from the opaque render target.\r\n * @param mesh - The mesh to classify\r\n * @returns 'transparent' if all materials are translucent, 'opaque' if none are, 'mixed' if both\r\n */\r\n private _classifyMeshMaterials(mesh: AbstractMesh): \"transparent\" | \"opaque\" | \"mixed\" {\r\n const material = mesh.material;\r\n if (!material) {\r\n return \"opaque\";\r\n }\r\n\r\n // Single material case\r\n if (!(material instanceof MultiMaterial)) {\r\n if (!this._loader.isMatchingMaterialType(material)) {\r\n return \"opaque\";\r\n }\r\n const adapter = this._loader._getOrCreateMaterialAdapter(material);\r\n if (adapter.isTranslucent()) {\r\n adapter.refractionBackgroundTexture = this._opaqueRenderTarget;\r\n return \"transparent\";\r\n }\r\n return \"opaque\";\r\n }\r\n\r\n // MultiMaterial case: check each sub-material individually\r\n let hasTranslucent = false;\r\n let hasOpaque = false;\r\n const translucentIndices = new Set<number>();\r\n\r\n for (let i = 0; i < material.subMaterials.length; i++) {\r\n const subMat = material.subMaterials[i];\r\n if (!subMat) {\r\n hasOpaque = true;\r\n continue;\r\n }\r\n if (this._loader.isMatchingMaterialType(subMat)) {\r\n const adapter = this._loader._getOrCreateMaterialAdapter(subMat);\r\n if (adapter.isTranslucent()) {\r\n adapter.refractionBackgroundTexture = this._opaqueRenderTarget;\r\n hasTranslucent = true;\r\n translucentIndices.add(i);\r\n } else {\r\n hasOpaque = true;\r\n }\r\n } else {\r\n hasOpaque = true;\r\n }\r\n }\r\n\r\n if (hasTranslucent && hasOpaque) {\r\n this._translucentMaterialIndices.set(mesh, translucentIndices);\r\n this._rebuildOpaqueOnlySubMeshes(mesh, translucentIndices);\r\n return \"mixed\";\r\n }\r\n this._translucentMaterialIndices.delete(mesh);\r\n this._opaqueOnlySubMeshes.delete(mesh);\r\n return hasTranslucent ? \"transparent\" : \"opaque\";\r\n }\r\n\r\n /**\r\n * Rebuild the cached opaque-only submesh array for a mixed mesh.\r\n * Called when classification changes so the per-frame swap is allocation-free.\r\n * @param mesh - The mesh to rebuild for\r\n * @param translucentIndices - Set of materialIndex values that are translucent\r\n */\r\n private _rebuildOpaqueOnlySubMeshes(mesh: AbstractMesh, translucentIndices: Set<number>): void {\r\n if (mesh.subMeshes) {\r\n this._opaqueOnlySubMeshes.set(\r\n mesh,\r\n mesh.subMeshes.filter((sm: SubMesh) => !translucentIndices.has(sm.materialIndex))\r\n );\r\n }\r\n }\r\n\r\n private _addMesh(mesh: AbstractMesh): void {\r\n this._materialObservers[mesh.uniqueId] = mesh.onMaterialChangedObservable.add(this._onMeshMaterialChanged.bind(this));\r\n\r\n // we need to defer the processing because _addMesh may be called as part as an instance mesh creation, in which case some\r\n // internal properties are not setup yet, like _sourceMesh (needed when doing mesh.material below)\r\n Tools.SetImmediate(() => {\r\n if (mesh.material) {\r\n const classification = this._classifyMeshMaterials(mesh);\r\n if (classification === \"transparent\") {\r\n if (this._transparentMeshesCache.indexOf(mesh) === -1) {\r\n this._transparentMeshesCache.push(mesh);\r\n }\r\n } else {\r\n // Both 'opaque' and 'mixed' go in the opaque cache.\r\n // For 'mixed', the translucent submeshes are temporarily\r\n // excluded during the opaque render target render.\r\n if (this._opaqueMeshesCache.indexOf(mesh) === -1) {\r\n this._opaqueMeshesCache.push(mesh);\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n private _removeMesh(mesh: AbstractMesh): void {\r\n mesh.onMaterialChangedObservable.remove(this._materialObservers[mesh.uniqueId]);\r\n delete this._materialObservers[mesh.uniqueId];\r\n let idx = this._transparentMeshesCache.indexOf(mesh);\r\n if (idx !== -1) {\r\n this._transparentMeshesCache.splice(idx, 1);\r\n }\r\n idx = this._opaqueMeshesCache.indexOf(mesh);\r\n if (idx !== -1) {\r\n this._opaqueMeshesCache.splice(idx, 1);\r\n }\r\n this._translucentMaterialIndices.delete(mesh);\r\n this._opaqueOnlySubMeshes.delete(mesh);\r\n }\r\n\r\n private _parseScene(): void {\r\n this._scene.meshes.forEach(this._addMesh.bind(this));\r\n // Listen for when a mesh is added to the scene and add it to our cache lists.\r\n this._scene.onNewMeshAddedObservable.add(this._addMesh.bind(this));\r\n // Listen for when a mesh is removed from to the scene and remove it from our cache lists.\r\n this._scene.onMeshRemovedObservable.add(this._removeMesh.bind(this));\r\n }\r\n\r\n // When one of the meshes in the scene has its material changed, make sure that it's in the correct cache list.\r\n private _onMeshMaterialChanged(mesh: AbstractMesh) {\r\n const transparentIdx = this._transparentMeshesCache.indexOf(mesh);\r\n const opaqueIdx = this._opaqueMeshesCache.indexOf(mesh);\r\n\r\n const classification = this._classifyMeshMaterials(mesh);\r\n\r\n if (classification === \"transparent\") {\r\n // Fully translucent: move to transparent cache\r\n if (opaqueIdx !== -1) {\r\n this._opaqueMeshesCache.splice(opaqueIdx, 1);\r\n this._transparentMeshesCache.push(mesh);\r\n } else if (transparentIdx === -1) {\r\n this._transparentMeshesCache.push(mesh);\r\n }\r\n } else {\r\n // Opaque or mixed: move to opaque cache (mixed meshes have their\r\n // translucent submeshes excluded during opaque RT render)\r\n if (transparentIdx !== -1) {\r\n this._transparentMeshesCache.splice(transparentIdx, 1);\r\n this._opaqueMeshesCache.push(mesh);\r\n } else if (opaqueIdx === -1) {\r\n this._opaqueMeshesCache.push(mesh);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @internal\r\n * Check if the opaque render target has not been disposed and can still be used.\r\n * @returns\r\n */\r\n public _isRenderTargetValid() {\r\n return this._opaqueRenderTarget?.getInternalTexture() !== null;\r\n }\r\n\r\n /**\r\n * @internal\r\n * Setup the render targets according to the specified options.\r\n */\r\n public _setupRenderTargets(): void {\r\n if (this._opaqueRenderTarget) {\r\n this._opaqueRenderTarget.dispose();\r\n }\r\n this._opaqueRenderTarget = new RenderTargetTexture(\r\n \"opaqueSceneTexture\",\r\n this._options.renderSize,\r\n this._scene,\r\n this._options.generateMipmaps,\r\n undefined,\r\n this._options.renderTargetTextureType\r\n );\r\n this._opaqueRenderTarget.ignoreCameraViewport = true;\r\n this._opaqueRenderTarget.renderList = this._opaqueMeshesCache;\r\n this._opaqueRenderTarget.clearColor = this._options.clearColor?.clone() ?? this._scene.clearColor.clone();\r\n this._opaqueRenderTarget.gammaSpace = false;\r\n this._opaqueRenderTarget.lodGenerationScale = this._options.lodGenerationScale;\r\n this._opaqueRenderTarget.lodGenerationOffset = this._options.lodGenerationOffset;\r\n this._opaqueRenderTarget.samples = this._options.samples;\r\n this._opaqueRenderTarget.renderSprites = true;\r\n this._opaqueRenderTarget.renderParticles = true;\r\n this._opaqueRenderTarget.disableImageProcessing = true;\r\n\r\n let saveSceneEnvIntensity: number;\r\n this._opaqueRenderTarget.onBeforeBindObservable.add((opaqueRenderTarget) => {\r\n saveSceneEnvIntensity = this._scene.environmentIntensity;\r\n this._scene.environmentIntensity = 1.0;\r\n if (!this._options.clearColor) {\r\n this._scene.clearColor.toLinearSpaceToRef(opaqueRenderTarget.clearColor, this._scene.getEngine().useExactSrgbConversions);\r\n } else {\r\n opaqueRenderTarget.clearColor.copyFrom(this._options.clearColor);\r\n }\r\n\r\n // For mixed MultiMaterial meshes, swap in the precomputed opaque-only\r\n // submesh array so translucent submeshes don't render into the opaque texture.\r\n const tlEntries = this._opaqueOnlySubMeshes.entries();\r\n for (let tlEntry = tlEntries.next(); !tlEntry.done; tlEntry = tlEntries.next()) {\r\n const mesh = tlEntry.value[0];\r\n const opaqueOnly = tlEntry.value[1];\r\n if (mesh.subMeshes) {\r\n this._savedSubMeshes.set(mesh, mesh.subMeshes);\r\n mesh.subMeshes = opaqueOnly;\r\n }\r\n }\r\n });\r\n this._opaqueRenderTarget.onAfterUnbindObservable.add(() => {\r\n this._scene.environmentIntensity = saveSceneEnvIntensity;\r\n\r\n // Restore the full submesh list after the opaque RT render\r\n const savedEntries = this._savedSubMeshes.entries();\r\n for (let savedEntry = savedEntries.next(); !savedEntry.done; savedEntry = savedEntries.next()) {\r\n savedEntry.value[0].subMeshes = savedEntry.value[1];\r\n }\r\n this._savedSubMeshes.clear();\r\n });\r\n\r\n // Update refraction textures on transparent and mixed meshes\r\n for (const mesh of this._transparentMeshesCache) {\r\n if (mesh.material) {\r\n this._classifyMeshMaterials(mesh);\r\n }\r\n }\r\n const mixedEntries = this._translucentMaterialIndices.entries();\r\n for (let mixedEntry = mixedEntries.next(); !mixedEntry.done; mixedEntry = mixedEntries.next()) {\r\n const mesh = mixedEntry.value[0];\r\n if (mesh.material) {\r\n this._classifyMeshMaterials(mesh);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Dispose all the elements created by the Helper.\r\n */\r\n public dispose(): void {\r\n this._scene._transmissionHelper = undefined;\r\n if (this._opaqueRenderTarget) {\r\n this._opaqueRenderTarget.dispose();\r\n this._opaqueRenderTarget = null;\r\n }\r\n this._transparentMeshesCache = [];\r\n this._opaqueMeshesCache = [];\r\n this._translucentMaterialIndices.clear();\r\n this._opaqueOnlySubMeshes.clear();\r\n this._savedSubMeshes.clear();\r\n }\r\n}\r\n\r\nconst NAME = \"KHR_materials_transmission\";\r\n\r\ndeclare module \"../../glTFFileLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/naming-convention\r\n export interface GLTFLoaderExtensionOptions {\r\n /**\r\n * Defines options for the KHR_materials_transmission extension.\r\n */\r\n // NOTE: Don't use NAME here as it will break the UMD type declarations.\r\n [\"KHR_materials_transmission\"]: {};\r\n }\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_transmission/README.md)\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_transmission implements IGLTFLoaderExtension {\r\n /**\r\n * The name of this extension.\r\n */\r\n public readonly name = NAME;\r\n\r\n /**\r\n * Defines whether this extension is enabled.\r\n */\r\n public enabled: boolean;\r\n\r\n /**\r\n * Defines a number that determines the order the extensions are applied.\r\n */\r\n public order = 175;\r\n\r\n private _loader: GLTFLoader;\r\n\r\n /**\r\n * @internal\r\n */\r\n constructor(loader: GLTFLoader) {\r\n this._loader = loader;\r\n this.enabled = this._loader.isExtensionUsed(NAME);\r\n if (this.enabled) {\r\n loader.parent.transparencyAsCoverage = true;\r\n }\r\n }\r\n\r\n /** @internal */\r\n public dispose() {\r\n (this._loader as any) = null;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n // eslint-disable-next-line no-restricted-syntax\r\n public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n return GLTFLoader.LoadExtensionAsync<IKHRMaterialsTransmission>(context, material, this.name, async (extensionContext, extension) => {\r\n const promises = new Array<Promise<any>>();\r\n promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n // eslint-disable-next-line github/no-then\r\n return await Promise.all(promises).then(() => {});\r\n });\r\n }\r\n\r\n // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async\r\n private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise<void> {\r\n const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n const transmissionWeight = extension.transmissionFactor !== undefined ? extension.transmissionFactor : 0.0;\r\n\r\n if (transmissionWeight === 0 || !adapter) {\r\n return Promise.resolve();\r\n }\r\n\r\n // Set transmission properties immediately via adapter\r\n adapter.configureTransmission();\r\n adapter.transmissionWeight = transmissionWeight;\r\n\r\n // Handle transmission helper setup (only needed for PBR materials)\r\n if (transmissionWeight > 0 && !this._loader.parent.dontUseTransmissionHelper) {\r\n const scene = babylonMaterial.getScene() as unknown as ITransmissionHelperHolder;\r\n if (!scene._transmissionHelper) {\r\n new TransmissionHelper({}, babylonMaterial.getScene(), this._loader);\r\n } else if (!scene._transmissionHelper?._isRenderTargetValid()) {\r\n // If the render target is not valid, recreate it.\r\n scene._transmissionHelper?._setupRenderTargets();\r\n }\r\n }\r\n\r\n // Load texture if present\r\n let texturePromise: Promise<Nullable<BaseTexture>> = Promise.resolve(null);\r\n if (extension.transmissionTexture) {\r\n (extension.transmissionTexture as ITextureInfo).nonColorData = true;\r\n texturePromise = this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, (texture: BaseTexture) => {\r\n texture.name = `${babylonMaterial.name} (Transmission)`;\r\n adapter.transmissionWeightTexture = texture;\r\n });\r\n }\r\n\r\n // eslint-disable-next-line github/no-then\r\n return texturePromise.then(() => {});\r\n }\r\n}\r\n\r\nunregisterGLTFExtension(NAME);\r\nregisterGLTFExtension(NAME, true, (loader) => new KHR_materials_transmission(loader));\r\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Color3 } from "@babylonjs/core/Maths/math.color.js";
|
|
2
2
|
import { GLTFLoader } from "../glTFLoader.js";
|
|
3
3
|
import { registerGLTFExtension, unregisterGLTFExtension } from "../glTFLoaderExtensionRegistry.js";
|
|
4
|
-
import { Vector3 } from "@babylonjs/core/Maths/math.vector.js";
|
|
5
4
|
const NAME = "KHR_materials_volume";
|
|
6
5
|
/**
|
|
7
6
|
* [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md)
|
|
@@ -56,14 +55,12 @@ export class KHR_materials_volume {
|
|
|
56
55
|
if ((adapter.transmissionWeight === 0 && adapter.subsurfaceWeight === 0) || !extension.thicknessFactor) {
|
|
57
56
|
return Promise.resolve();
|
|
58
57
|
}
|
|
58
|
+
adapter.geometryThinWalled = false;
|
|
59
59
|
const attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE;
|
|
60
60
|
const attenuationColor = extension.attenuationColor !== undefined && extension.attenuationColor.length == 3 ? Color3.FromArray(extension.attenuationColor) : Color3.White();
|
|
61
|
-
|
|
62
|
-
const extinctionCoefficient = new Vector3(-Math.log(attenuationColor.r), -Math.log(attenuationColor.g), -Math.log(attenuationColor.b));
|
|
63
|
-
extinctionCoefficient.scaleInPlace(1 / Math.max(attenuationDistance, 0.001));
|
|
64
|
-
adapter.extinctionCoefficient = extinctionCoefficient;
|
|
65
|
-
adapter.transmissionDepth = attenuationDistance;
|
|
61
|
+
adapter.configureVolume();
|
|
66
62
|
adapter.transmissionColor = attenuationColor;
|
|
63
|
+
adapter.transmissionDepth = attenuationDistance;
|
|
67
64
|
adapter.volumeThickness = extension.thicknessFactor ?? 0;
|
|
68
65
|
const promises = new Array();
|
|
69
66
|
if (extension.thicknessTexture) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KHR_materials_volume.js","sourceRoot":"","sources":["../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAI/C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"KHR_materials_volume.js","sourceRoot":"","sources":["../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAI/C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEhG,MAAM,IAAI,GAAG,sBAAsB,CAAC;AAapC;;;GAGG;AACH,gEAAgE;AAChE,MAAM,OAAO,oBAAoB;IAkB7B;;OAEG;IACH,YAAY,MAAkB;QApB9B;;WAEG;QACa,SAAI,GAAG,IAAI,CAAC;QAO5B;;WAEG;QACI,UAAK,GAAG,GAAG,CAAC;QAQf,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,qHAAqH;YACrH,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;QACzC,CAAC;IACL,CAAC;IAED,gBAAgB;IACT,OAAO;QACV,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;QACzC,CAAC;QACA,IAAI,CAAC,OAAe,GAAG,IAAI,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,gDAAgD;IACzC,2BAA2B,CAAC,OAAe,EAAE,QAAmB,EAAE,eAAyB;QAC9F,OAAO,UAAU,CAAC,kBAAkB,CAAsB,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,EAAE;YAC1H,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAgB,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;YAC5F,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,gBAAgB,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;YACvG,0CAA0C;YAC1C,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACP,CAAC;IAED,2FAA2F;IACnF,0BAA0B,CAAC,OAAe,EAAE,QAAmB,EAAE,eAAyB,EAAE,SAA8B;QAC9H,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,eAAe,CAAC,CAAC;QAE1E,+EAA+E;QAC/E,2GAA2G;QAC3G,IAAI,CAAC,OAAO,CAAC,kBAAkB,KAAK,CAAC,IAAI,OAAO,CAAC,gBAAgB,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC;YACrG,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC;QAED,OAAO,CAAC,kBAAkB,GAAG,KAAK,CAAC;QACnC,MAAM,mBAAmB,GAAG,SAAS,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;QAC3H,MAAM,gBAAgB,GAAG,SAAS,CAAC,gBAAgB,KAAK,SAAS,IAAI,SAAS,CAAC,gBAAgB,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC5K,OAAO,CAAC,eAAe,EAAE,CAAC;QAC1B,OAAO,CAAC,iBAAiB,GAAG,gBAAgB,CAAC;QAC7C,OAAO,CAAC,iBAAiB,GAAG,mBAAmB,CAAC;QAEhD,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,eAAe,IAAI,CAAC,CAAC;QAEzD,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAgB,CAAC;QAE3C,IAAI,SAAS,CAAC,gBAAgB,EAAE,CAAC;YAC5B,SAAS,CAAC,gBAAiC,CAAC,YAAY,GAAG,IAAI,CAAC;YACjE,0CAA0C;YAC1C,QAAQ,CAAC,IAAI,CACT,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,GAAG,OAAO,mBAAmB,EAAE,SAAS,CAAC,gBAAgB,EAAE,CAAC,OAAoB,EAAE,EAAE;gBAClH,OAAO,CAAC,IAAI,GAAG,GAAG,eAAe,CAAC,IAAI,cAAc,CAAC;gBACrD,OAAO,CAAC,sBAAsB,GAAG,OAAO,CAAC;YAC7C,CAAC,CAAC,CACL,CAAC;QACN,CAAC;QAED,0CAA0C;QAC1C,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAChD,CAAC;CACJ;AAED,uBAAuB,CAAC,IAAI,CAAC,CAAC;AAC9B,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention */\r\nimport { type Nullable } from \"core/types\";\r\nimport { type Material } from \"core/Materials/material\";\r\nimport { Color3 } from \"core/Maths/math.color\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type IMaterial, type ITextureInfo } from \"../glTFLoaderInterfaces\";\r\nimport { type IGLTFLoaderExtension } from \"../glTFLoaderExtension\";\r\nimport { GLTFLoader } from \"../glTFLoader\";\r\nimport { type IKHRMaterialsVolume } from \"babylonjs-gltf2interface\";\r\nimport { registerGLTFExtension, unregisterGLTFExtension } from \"../glTFLoaderExtensionRegistry\";\r\n\r\nconst NAME = \"KHR_materials_volume\";\r\n\r\ndeclare module \"../../glTFFileLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/naming-convention\r\n export interface GLTFLoaderExtensionOptions {\r\n /**\r\n * Defines options for the KHR_materials_volume extension.\r\n */\r\n // NOTE: Don't use NAME here as it will break the UMD type declarations.\r\n [\"KHR_materials_volume\"]: {};\r\n }\r\n}\r\n\r\n/**\r\n * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md)\r\n * @since 5.0.0\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_materials_volume implements IGLTFLoaderExtension {\r\n /**\r\n * The name of this extension.\r\n */\r\n public readonly name = NAME;\r\n\r\n /**\r\n * Defines whether this extension is enabled.\r\n */\r\n public enabled: boolean;\r\n\r\n /**\r\n * Defines a number that determines the order the extensions are applied.\r\n */\r\n public order = 173;\r\n\r\n private _loader: GLTFLoader;\r\n\r\n /**\r\n * @internal\r\n */\r\n constructor(loader: GLTFLoader) {\r\n this._loader = loader;\r\n this.enabled = this._loader.isExtensionUsed(NAME);\r\n if (this.enabled) {\r\n // We need to disable instance usage because the attenuation factor depends on the node scale of each individual mesh\r\n this._loader._disableInstancedMesh++;\r\n }\r\n }\r\n\r\n /** @internal */\r\n public dispose() {\r\n if (this.enabled) {\r\n this._loader._disableInstancedMesh--;\r\n }\r\n (this._loader as any) = null;\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n // eslint-disable-next-line no-restricted-syntax\r\n public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {\r\n return GLTFLoader.LoadExtensionAsync<IKHRMaterialsVolume>(context, material, this.name, async (extensionContext, extension) => {\r\n const promises = new Array<Promise<any>>();\r\n promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));\r\n promises.push(this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension));\r\n // eslint-disable-next-line github/no-then\r\n return await Promise.all(promises).then(() => {});\r\n });\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n private _loadVolumePropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsVolume): Promise<void> {\r\n const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);\r\n\r\n // If transparency isn't enabled already, this extension shouldn't do anything.\r\n // i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions.\r\n if ((adapter.transmissionWeight === 0 && adapter.subsurfaceWeight === 0) || !extension.thicknessFactor) {\r\n return Promise.resolve();\r\n }\r\n\r\n adapter.geometryThinWalled = false;\r\n const attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE;\r\n const attenuationColor = extension.attenuationColor !== undefined && extension.attenuationColor.length == 3 ? Color3.FromArray(extension.attenuationColor) : Color3.White();\r\n adapter.configureVolume();\r\n adapter.transmissionColor = attenuationColor;\r\n adapter.transmissionDepth = attenuationDistance;\r\n\r\n adapter.volumeThickness = extension.thicknessFactor ?? 0;\r\n\r\n const promises = new Array<Promise<any>>();\r\n\r\n if (extension.thicknessTexture) {\r\n (extension.thicknessTexture as ITextureInfo).nonColorData = true;\r\n // eslint-disable-next-line github/no-then\r\n promises.push(\r\n this._loader.loadTextureInfoAsync(`${context}/thicknessTexture`, extension.thicknessTexture, (texture: BaseTexture) => {\r\n texture.name = `${babylonMaterial.name} (Thickness)`;\r\n adapter.volumeThicknessTexture = texture;\r\n })\r\n );\r\n }\r\n\r\n // eslint-disable-next-line github/no-then\r\n return Promise.all(promises).then(() => {});\r\n }\r\n}\r\n\r\nunregisterGLTFExtension(NAME);\r\nregisterGLTFExtension(NAME, true, (loader) => new KHR_materials_volume(loader));\r\n"]}
|
|
@@ -6,8 +6,7 @@ const NAME = "KHR_materials_volume_scatter";
|
|
|
6
6
|
function multiScatterToSingleScatterAlbedo(multiScatter) {
|
|
7
7
|
const multiScatterAlbedo = new Vector3(multiScatter.r, multiScatter.g, multiScatter.b);
|
|
8
8
|
const s = new Vector3(4.09712, 4.09712, 4.09712);
|
|
9
|
-
s.multiplyInPlace(multiScatterAlbedo);
|
|
10
|
-
s.addInPlace(new Vector3(4.20863, 4.20863, 4.20863));
|
|
9
|
+
s.addInPlace(new Vector3(4.20863, 4.20863, 4.20863).multiplyInPlace(multiScatterAlbedo));
|
|
11
10
|
const p = new Vector3(9.59217, 9.59217, 9.59217);
|
|
12
11
|
p.addInPlace(new Vector3(41.6808, 41.6808, 41.6808).multiplyInPlace(multiScatterAlbedo));
|
|
13
12
|
p.addInPlace(new Vector3(17.7126, 17.7126, 17.7126).multiplyInPlace(multiScatterAlbedo.multiply(multiScatterAlbedo)));
|
|
@@ -66,43 +65,50 @@ export class KHR_materials_volume_scatter {
|
|
|
66
65
|
const adapter = this._loader._getOrCreateMaterialAdapter(babylonMaterial);
|
|
67
66
|
// If transparency isn't enabled already, this extension shouldn't do anything.
|
|
68
67
|
// i.e. it requires either the KHR_materials_transmission or KHR_materials_diffuse_transmission extensions.
|
|
69
|
-
|
|
68
|
+
// Additionally, this already needs to be a volumetric material to apply this extension.
|
|
69
|
+
if ((adapter.transmissionWeight === 0 && adapter.subsurfaceWeight === 0) || adapter.geometryThinWalled) {
|
|
70
70
|
return Promise.resolve();
|
|
71
71
|
}
|
|
72
|
-
const scatterColor = extension.
|
|
72
|
+
const scatterColor = extension.multiscatterColorFactor !== undefined && extension.multiscatterColorFactor.length == 3 ? Color3.FromArray(extension.multiscatterColorFactor) : Color3.Black();
|
|
73
73
|
const scatterAnisotropy = extension.scatterAnisotropy !== undefined ? extension.scatterAnisotropy : 0;
|
|
74
|
+
// If diffuse_transmission, apply props to subsurface
|
|
75
|
+
// If transmission, apply props to transmission
|
|
76
|
+
// Load texture if present
|
|
77
|
+
let texturePromise = Promise.resolve(null);
|
|
78
|
+
if (extension.multiscatterColorTexture) {
|
|
79
|
+
extension.multiscatterColorTexture.nonColorData = true;
|
|
80
|
+
texturePromise = this._loader.loadTextureInfoAsync(`${context}/multiscatterColorTexture`, extension.multiscatterColorTexture, (texture) => {
|
|
81
|
+
texture.name = `${babylonMaterial.name} (Scatter Color)`;
|
|
82
|
+
if (adapter.transmissionWeight > 0) {
|
|
83
|
+
adapter.transmissionScatterTexture = texture;
|
|
84
|
+
}
|
|
85
|
+
if (adapter.subsurfaceWeight > 0) {
|
|
86
|
+
adapter.subsurfaceColorTexture = texture;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const extinctionCoefficient = new Vector3(-Math.log(adapter.transmissionColor.r), -Math.log(adapter.transmissionColor.g), -Math.log(adapter.transmissionColor.b));
|
|
91
|
+
extinctionCoefficient.scaleInPlace(1 / Math.max(adapter.transmissionDepth, 0.000001));
|
|
74
92
|
// In glTF, both the translucency volume and subsurface volume use the same input parameters.
|
|
75
93
|
// We'll apply them to both, as appropriate.
|
|
76
94
|
if (adapter.transmissionWeight > 0) {
|
|
77
95
|
const singleScatterAlbedo = multiScatterToSingleScatterAlbedo(scatterColor);
|
|
78
|
-
const extinctionCoefficient = new Vector3(-Math.log(adapter.transmissionColor.r), -Math.log(adapter.transmissionColor.g), -Math.log(adapter.transmissionColor.b));
|
|
79
|
-
extinctionCoefficient.scaleInPlace(1 / Math.max(adapter.transmissionDepth, 0.001));
|
|
80
96
|
const scatteringCoefficient = extinctionCoefficient.multiply(singleScatterAlbedo);
|
|
81
97
|
// The scattering coefficient in OpenPBR is defined as per unit distance, so we need to scale it back up by the depth.
|
|
82
98
|
scatteringCoefficient.scaleInPlace(adapter.transmissionDepth);
|
|
83
99
|
adapter.transmissionScatter.set(scatteringCoefficient.x, scatteringCoefficient.y, scatteringCoefficient.z);
|
|
84
|
-
// Load texture if present
|
|
85
|
-
let texturePromise = Promise.resolve(null);
|
|
86
|
-
if (extension.multiscatterColorTexture) {
|
|
87
|
-
extension.multiscatterColorTexture.nonColorData = true;
|
|
88
|
-
texturePromise = this._loader.loadTextureInfoAsync(`${context}/multiscatterColorTexture`, extension.multiscatterColorTexture, (texture) => {
|
|
89
|
-
texture.name = `${babylonMaterial.name} (Transmission)`;
|
|
90
|
-
adapter.transmissionWeightTexture = texture;
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
100
|
adapter.transmissionScatterAnisotropy = scatterAnisotropy;
|
|
94
|
-
// eslint-disable-next-line github/no-then
|
|
95
|
-
return texturePromise.then(() => { });
|
|
96
101
|
}
|
|
97
102
|
// Subsurface volume
|
|
98
103
|
if (adapter.subsurfaceWeight > 0) {
|
|
99
104
|
adapter.subsurfaceScatterAnisotropy = scatterAnisotropy;
|
|
100
105
|
adapter.subsurfaceColor = scatterColor;
|
|
101
|
-
const mfp = new Vector3(
|
|
106
|
+
const mfp = new Vector3(extinctionCoefficient.x !== 0 ? 1.0 / extinctionCoefficient.x : 1.0, extinctionCoefficient.y !== 0 ? 1.0 / extinctionCoefficient.y : 1.0, extinctionCoefficient.z !== 0 ? 1.0 / extinctionCoefficient.z : 1.0);
|
|
102
107
|
adapter.subsurfaceRadius = Math.max(mfp.x, mfp.y, mfp.z);
|
|
103
108
|
adapter.subsurfaceRadiusScale = new Color3(mfp.x / adapter.subsurfaceRadius, mfp.y / adapter.subsurfaceRadius, mfp.z / adapter.subsurfaceRadius);
|
|
104
109
|
}
|
|
105
|
-
|
|
110
|
+
// eslint-disable-next-line github/no-then
|
|
111
|
+
return texturePromise.then(() => { });
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
114
|
unregisterGLTFExtension(NAME);
|