|
1 | 1 | import type { Nullable } from "core/types";
|
2 |
| -import { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; |
| 2 | +import type { PBRMaterial } from "core/Materials/PBR/pbrMaterial"; |
| 3 | +import type { OpenPBRMaterial } from "core/Materials/PBR/openPbrMaterial"; |
3 | 4 | import type { Material } from "core/Materials/material";
|
4 | 5 | import type { BaseTexture } from "core/Materials/Textures/baseTexture";
|
5 | 6 | import type { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces";
|
@@ -62,6 +63,8 @@ interface ITransmissionHelperOptions {
|
62 | 63 | clearColor?: Color4;
|
63 | 64 | }
|
64 | 65 |
|
| 66 | +let PBRMaterialClass: typeof PBRMaterial | typeof OpenPBRMaterial; |
| 67 | + |
65 | 68 | /**
|
66 | 69 | * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects.
|
67 | 70 | */
|
@@ -166,7 +169,7 @@ class TransmissionHelper {
|
166 | 169 | if (!material) {
|
167 | 170 | return false;
|
168 | 171 | }
|
169 |
| - if (material instanceof PBRMaterial && material.subSurface.isRefractionEnabled) { |
| 172 | + if (material instanceof PBRMaterialClass && (material as any).subSurface.isRefractionEnabled) { |
170 | 173 | return true;
|
171 | 174 | }
|
172 | 175 | return false;
|
@@ -220,8 +223,8 @@ class TransmissionHelper {
|
220 | 223 | // If the material is transparent, make sure that it's added to the transparent list and removed from the opaque list
|
221 | 224 | const useTransmission = this._shouldRenderAsTransmission(mesh.material);
|
222 | 225 | if (useTransmission) {
|
223 |
| - if (mesh.material instanceof PBRMaterial) { |
224 |
| - mesh.material.subSurface.refractionTexture = this._opaqueRenderTarget; |
| 226 | + if (mesh.material instanceof PBRMaterialClass) { |
| 227 | + (mesh.material as any).subSurface.refractionTexture = this._opaqueRenderTarget; |
225 | 228 | }
|
226 | 229 | if (opaqueIdx !== -1) {
|
227 | 230 | this._opaqueMeshesCache.splice(opaqueIdx, 1);
|
@@ -366,60 +369,87 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension {
|
366 | 369 | * @internal
|
367 | 370 | */
|
368 | 371 | // eslint-disable-next-line no-restricted-syntax
|
369 |
| - public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> { |
| 372 | + public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, useOpenPBR: boolean = false): Nullable<Promise<void>> { |
370 | 373 | return GLTFLoader.LoadExtensionAsync<IKHRMaterialsTransmission>(context, material, this.name, async (extensionContext, extension) => {
|
| 374 | + if (useOpenPBR) { |
| 375 | + const mod = await import("core/Materials/PBR/openPbrMaterial"); |
| 376 | + PBRMaterialClass = mod.OpenPBRMaterial; |
| 377 | + } else { |
| 378 | + const mod = await import("core/Materials/PBR/pbrMaterial"); |
| 379 | + PBRMaterialClass = mod.PBRMaterial; |
| 380 | + } |
371 | 381 | const promises = new Array<Promise<any>>();
|
372 | 382 | promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));
|
373 |
| - promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); |
| 383 | + promises.push(this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension, useOpenPBR)); |
374 | 384 | // eslint-disable-next-line github/no-then
|
375 | 385 | return await Promise.all(promises).then(() => {});
|
376 | 386 | });
|
377 | 387 | }
|
378 | 388 |
|
379 | 389 | // eslint-disable-next-line no-restricted-syntax, @typescript-eslint/promise-function-async
|
380 |
| - private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTransmission): Promise<void> { |
381 |
| - if (!(babylonMaterial instanceof PBRMaterial)) { |
| 390 | + private _loadTransparentPropertiesAsync( |
| 391 | + context: string, |
| 392 | + material: IMaterial, |
| 393 | + babylonMaterial: Material, |
| 394 | + extension: IKHRMaterialsTransmission, |
| 395 | + useOpenPBR: boolean |
| 396 | + ): Promise<void> { |
| 397 | + if (!(babylonMaterial instanceof PBRMaterialClass)) { |
382 | 398 | throw new Error(`${context}: Material type not supported`);
|
383 | 399 | }
|
384 |
| - const pbrMaterial = babylonMaterial; |
385 |
| - |
386 |
| - // Enables "refraction" texture which represents transmitted light. |
387 |
| - pbrMaterial.subSurface.isRefractionEnabled = true; |
388 |
| - |
389 |
| - // Since this extension models thin-surface transmission only, we must make IOR = 1.0 |
390 |
| - pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; |
391 | 400 |
|
392 |
| - // Albedo colour will tint transmission. |
393 |
| - pbrMaterial.subSurface.useAlbedoToTintRefraction = true; |
| 401 | + let transmissionWeight = 0.0; |
| 402 | + let transmissionWeightTexture: Nullable<BaseTexture> = null; |
394 | 403 |
|
| 404 | + const promises = new Array<Promise<any>>(); |
395 | 405 | if (extension.transmissionFactor !== undefined) {
|
396 |
| - pbrMaterial.subSurface.refractionIntensity = extension.transmissionFactor; |
397 |
| - const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; |
398 |
| - if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { |
399 |
| - new TransmissionHelper({}, pbrMaterial.getScene()); |
400 |
| - } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { |
401 |
| - // If the render target is not valid, recreate it. |
402 |
| - scene._transmissionHelper?._setupRenderTargets(); |
403 |
| - } |
| 406 | + transmissionWeight = extension.transmissionFactor; |
404 | 407 | } else {
|
405 |
| - pbrMaterial.subSurface.refractionIntensity = 0.0; |
406 |
| - pbrMaterial.subSurface.isRefractionEnabled = false; |
407 | 408 | return Promise.resolve();
|
408 | 409 | }
|
409 |
| - |
410 |
| - pbrMaterial.subSurface.minimumThickness = 0.0; |
411 |
| - pbrMaterial.subSurface.maximumThickness = 0.0; |
412 | 410 | if (extension.transmissionTexture) {
|
413 | 411 | (extension.transmissionTexture as ITextureInfo).nonColorData = true;
|
414 | 412 | // eslint-disable-next-line github/no-then
|
415 |
| - return this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, undefined).then((texture: BaseTexture) => { |
416 |
| - texture.name = `${babylonMaterial.name} (Transmission)`; |
417 |
| - pbrMaterial.subSurface.refractionIntensityTexture = texture; |
418 |
| - pbrMaterial.subSurface.useGltfStyleTextures = true; |
419 |
| - }); |
420 |
| - } else { |
421 |
| - return Promise.resolve(); |
| 413 | + promises.push( |
| 414 | + this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, (texture: BaseTexture) => { |
| 415 | + texture.name = `${babylonMaterial.name} (Transmission)`; |
| 416 | + transmissionWeightTexture = texture; |
| 417 | + }) |
| 418 | + ); |
422 | 419 | }
|
| 420 | + |
| 421 | + // eslint-disable-next-line github/no-then |
| 422 | + return Promise.all(promises).then(() => { |
| 423 | + if (useOpenPBR) { |
| 424 | + return; |
| 425 | + } |
| 426 | + const pbrMaterial = babylonMaterial as PBRMaterial; |
| 427 | + |
| 428 | + // Enables "refraction" texture which represents transmitted light. |
| 429 | + pbrMaterial.subSurface.isRefractionEnabled = transmissionWeight !== 0; |
| 430 | + |
| 431 | + // Since this extension models thin-surface transmission only, we must make IOR = 1.0 |
| 432 | + pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; |
| 433 | + |
| 434 | + // Albedo colour will tint transmission. |
| 435 | + pbrMaterial.subSurface.useAlbedoToTintRefraction = true; |
| 436 | + |
| 437 | + pbrMaterial.subSurface.refractionIntensity = transmissionWeight; |
| 438 | + |
| 439 | + if (transmissionWeight) { |
| 440 | + const scene = pbrMaterial.getScene() as unknown as ITransmissionHelperHolder; |
| 441 | + if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { |
| 442 | + new TransmissionHelper({}, pbrMaterial.getScene()); |
| 443 | + } else if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper?._isRenderTargetValid()) { |
| 444 | + // If the render target is not valid, recreate it. |
| 445 | + scene._transmissionHelper?._setupRenderTargets(); |
| 446 | + } |
| 447 | + } |
| 448 | + pbrMaterial.subSurface.minimumThickness = 0.0; |
| 449 | + pbrMaterial.subSurface.maximumThickness = 0.0; |
| 450 | + pbrMaterial.subSurface.refractionIntensityTexture = transmissionWeightTexture; |
| 451 | + pbrMaterial.subSurface.useGltfStyleTextures = true; |
| 452 | + }); |
423 | 453 | }
|
424 | 454 | }
|
425 | 455 |
|
|
0 commit comments