Forráskód Böngészése

Merge pull request #9191 from MiiBond/mbond/KHR_materials_translucency

glTF KHR_materials_translucency loading
sebavan 4 éve
szülő
commit
b1b789a64d

+ 11 - 0
dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts

@@ -1057,6 +1057,17 @@ declare module BABYLON.GLTF2 {
     }
 
     /**
+     * Interfaces from the KHR_materials_translucency extension
+     * !!! Experimental Extension Subject to Changes !!!
+     */
+
+    /** @hidden */
+    interface IKHRMaterialsTranslucency {
+        translucencyFactor?: number;
+        translucencyTexture?: ITextureInfo;
+    }
+
+    /**
      * Interfaces from the KHR_materials_variants extension
      * !!! Experimental Extension Subject to Changes !!!
      */

+ 1 - 0
dist/preview release/what's new.md

@@ -155,6 +155,7 @@
 - Added the `loadAllMaterials` property to the gLTF loader to load materials even if not used by any mesh ([Popov72](https://github.com/Popov72))
 - Added transmission prerender pass when using KHR_materials_transmission ([MiiBond](https://github.com/MiiBond/))
 - Fixed a bug when loading glTF with interleaved animation data. ([bghgary](https://github.com/bghgary))
+- Added support for KHR_materials_translucency for glTF loader. ([MiiBond](https://github.com/MiiBond/))
 
 ### Serializers
 

+ 1 - 0
inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx

@@ -139,6 +139,7 @@ export class GLTFComponent extends React.Component<IGLTFComponentProps> {
                     <CheckBoxLineComponent label="KHR_materials_unlit" isSelected={() => extensionStates["KHR_materials_unlit"].enabled} onSelect={(value) => (extensionStates["KHR_materials_unlit"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_materials_variants" isSelected={() => extensionStates["KHR_materials_variants"].enabled} onSelect={(value) => (extensionStates["KHR_materials_variants"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_materials_transmission" isSelected={() => extensionStates["KHR_materials_transmission"].enabled} onSelect={(value) => (extensionStates["KHR_materials_transmission"].enabled = value)} />
+                    <CheckBoxLineComponent label="KHR_materials_translucency" isSelected={() => extensionStates["KHR_materials_translucency"].enabled} onSelect={(value) => (extensionStates["KHR_materials_translucency"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_lights_punctual" isSelected={() => extensionStates["KHR_lights_punctual"].enabled} onSelect={(value) => (extensionStates["KHR_lights_punctual"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_texture_basisu" isSelected={() => extensionStates["KHR_texture_basisu"].enabled} onSelect={(value) => (extensionStates["KHR_texture_basisu"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_texture_transform" isSelected={() => extensionStates["KHR_texture_transform"].enabled} onSelect={(value) => (extensionStates["KHR_texture_transform"].enabled = value)} />

+ 1 - 0
inspector/src/components/globalState.ts

@@ -44,6 +44,7 @@ export class GlobalState {
         KHR_materials_unlit: { enabled: true },
         KHR_materials_variants: { enabled: true },
         KHR_materials_transmission: { enabled: true },
+        KHR_materials_translucency: { enabled: true },
         KHR_lights_punctual: { enabled: true },
         KHR_texture_basisu: { enabled: true },
         KHR_texture_transform: { enabled: true },

+ 97 - 0
loaders/src/glTF/2.0/Extensions/KHR_materials_translucency.ts

@@ -0,0 +1,97 @@
+import { Nullable } from "babylonjs/types";
+import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
+import { Material } from "babylonjs/Materials/material";
+import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
+import { IMaterial } from "../glTFLoaderInterfaces";
+import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
+import { GLTFLoader } from "../glTFLoader";
+import { IKHRMaterialsTranslucency } from 'babylonjs-gltf2interface';
+
+const NAME = "KHR_materials_translucency";
+
+/**
+ * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)
+ * !!! Experimental Extension Subject to Changes !!!
+ */
+export class KHR_materials_translucency implements IGLTFLoaderExtension {
+    /**
+     * The name of this extension.
+     */
+    public readonly name = NAME;
+
+    /**
+     * Defines whether this extension is enabled.
+     */
+    public enabled: boolean;
+
+    /**
+     * Defines a number that determines the order the extensions are applied.
+     */
+    public order = 175;
+
+    private _loader: GLTFLoader;
+
+    /** @hidden */
+    constructor(loader: GLTFLoader) {
+        this._loader = loader;
+        this.enabled = this._loader.isExtensionUsed(NAME);
+        if (this.enabled) {
+            loader.parent.transparencyAsCoverage = true;
+        }
+    }
+
+    /** @hidden */
+    public dispose() {
+        (this._loader as any) = null;
+    }
+
+    /** @hidden */
+    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
+        return GLTFLoader.LoadExtensionAsync<IKHRMaterialsTranslucency>(context, material, this.name, (extensionContext, extension) => {
+            const promises = new Array<Promise<any>>();
+            promises.push(this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
+            promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));
+            promises.push(this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension));
+            return Promise.all(promises).then(() => { });
+        });
+    }
+
+    private _loadTranslucentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IKHRMaterialsTranslucency): Promise<void> {
+        if (!(babylonMaterial instanceof PBRMaterial)) {
+            throw new Error(`${context}: Material type not supported`);
+        }
+        const pbrMaterial = babylonMaterial as PBRMaterial;
+
+        // Enables "translucency" texture which represents diffusely-transmitted light.
+        pbrMaterial.subSurface.isTranslucencyEnabled = true;
+
+        // Since this extension models thin-surface transmission only, we must make the
+        // internal IOR == 1.0 and set the thickness to 0.
+        pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0;
+        pbrMaterial.subSurface.minimumThickness = 0.0;
+        pbrMaterial.subSurface.maximumThickness = 0.0;
+
+        // Albedo colour will tint transmission.
+        pbrMaterial.subSurface.useAlbedoToTintRefraction = true;
+
+        if (extension.translucencyFactor !== undefined) {
+            pbrMaterial.subSurface.translucencyIntensity = extension.translucencyFactor;
+        } else {
+            pbrMaterial.subSurface.translucencyIntensity = 0.0;
+            pbrMaterial.subSurface.isTranslucencyEnabled = false;
+            return Promise.resolve();
+        }
+
+        if (extension.translucencyTexture) {
+            return this._loader.loadTextureInfoAsync(`${context}/translucencyTexture`, extension.translucencyTexture)
+                .then((texture: BaseTexture) => {
+                    pbrMaterial.subSurface.thicknessTexture = texture;
+                    pbrMaterial.subSurface.useMaskFromThicknessTextureGltf = true;
+                });
+        } else {
+            return Promise.resolve();
+        }
+    }
+}
+
+GLTFLoader.RegisterExtension(NAME, (loader) => new KHR_materials_translucency(loader));

+ 2 - 2
loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts

@@ -276,7 +276,7 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension {
         this._loader = loader;
         this.enabled = this._loader.isExtensionUsed(NAME);
         if (this.enabled) {
-            (loader as any)._parent.transparencyAsCoverage = true;
+            loader.parent.transparencyAsCoverage = true;
         }
     }
 
@@ -328,7 +328,7 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension {
             return this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, undefined)
                 .then((texture: BaseTexture) => {
                     pbrMaterial.subSurface.thicknessTexture = texture;
-                    pbrMaterial.subSurface.useMaskFromThicknessTexture = true;
+                    pbrMaterial.subSurface.useMaskFromThicknessTextureGltf = true;
                 });
         } else {
             return Promise.resolve();

+ 1 - 0
loaders/src/glTF/2.0/Extensions/index.ts

@@ -11,6 +11,7 @@ export * from "./KHR_materials_specular";
 export * from "./KHR_materials_ior";
 export * from "./KHR_materials_variants";
 export * from "./KHR_materials_transmission";
+export * from "./KHR_materials_translucency";
 export * from "./KHR_mesh_quantization";
 export * from "./KHR_texture_basisu";
 export * from "./KHR_texture_transform";

+ 1 - 0
src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts

@@ -115,6 +115,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
         defines.setValue("SS_TRANSLUCENCY", translucencyEnabled, true);
         defines.setValue("SS_THICKNESSANDMASK_TEXTURE", false, true);
         defines.setValue("SS_MASK_FROM_THICKNESS_TEXTURE", false, true);
+        defines.setValue("SS_MASK_FROM_THICKNESS_TEXTURE_GLTF", false, true);
     }
 
     /**

+ 1 - 0
src/Materials/PBR/pbrBaseMaterial.ts

@@ -279,6 +279,7 @@ export class PBRMaterialDefines extends MaterialDefines
     public SS_ALBEDOFORREFRACTIONTINT = false;
 
     public SS_MASK_FROM_THICKNESS_TEXTURE = false;
+    public SS_MASK_FROM_THICKNESS_TEXTURE_GLTF = false;
 
     public UNLIT = false;
 

+ 13 - 0
src/Materials/PBR/pbrSubSurfaceConfiguration.ts

@@ -38,6 +38,7 @@ export interface IMaterialSubSurfaceDefines {
     SS_ALBEDOFORREFRACTIONTINT: boolean;
 
     SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
+    SS_MASK_FROM_THICKNESS_TEXTURE_GLTF: boolean;
 
     /** @hidden */
     _areTexturesDirty: boolean;
@@ -242,6 +243,16 @@ export class PBRSubSurfaceConfiguration {
     public useMaskFromThicknessTexture: boolean = false;
 
     private _scene: Scene;
+    private _useMaskFromThicknessTextureGltf = false;
+    /**
+     * Stores the intensity of the different subsurface effects in the thickness texture. This variation
+     * matches the channel-packing that is used by glTF.
+     * * the red channel is the transmission/translucency intensity.
+     * * the green channel is the thickness.
+     */
+    @serialize()
+    @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+    public useMaskFromThicknessTextureGltf: boolean = false;
 
     /** @hidden */
     private _internalMarkAllSubMeshesAsTexturesDirty: () => void;
@@ -309,6 +320,7 @@ export class PBRSubSurfaceConfiguration {
             defines.SS_SCATTERING = this._isScatteringEnabled;
             defines.SS_THICKNESSANDMASK_TEXTURE = false;
             defines.SS_MASK_FROM_THICKNESS_TEXTURE = false;
+            defines.SS_MASK_FROM_THICKNESS_TEXTURE_GLTF = false;
             defines.SS_REFRACTION = false;
             defines.SS_REFRACTIONMAP_3D = false;
             defines.SS_GAMMAREFRACTION = false;
@@ -331,6 +343,7 @@ export class PBRSubSurfaceConfiguration {
                 }
 
                 defines.SS_MASK_FROM_THICKNESS_TEXTURE = this._useMaskFromThicknessTexture;
+                defines.SS_MASK_FROM_THICKNESS_TEXTURE_GLTF = this._useMaskFromThicknessTextureGltf;
             }
 
             if (this._isRefractionEnabled) {

+ 1 - 0
src/Shaders/ShadersInclude/pbrBlockFinalLitComponents.fx

@@ -34,6 +34,7 @@
     #endif
 
     #if defined(SS_TRANSLUCENCY)
+        finalIrradiance *= (1.0 - subSurfaceOut.transmittance);
         finalIrradiance += subSurfaceOut.refractionIrradiance;
     #endif
 

+ 7 - 0
src/Shaders/ShadersInclude/pbrBlockSubSurface.fx

@@ -127,6 +127,13 @@ struct subSurfaceOutParams
             #ifdef SS_TRANSLUCENCY
                 translucencyIntensity *= thicknessMap.b;
             #endif
+        #elif defined(SS_MASK_FROM_THICKNESS_TEXTURE_GLTF)
+            #ifdef SS_REFRACTION
+                refractionIntensity *= thicknessMap.r;
+            #elif defined(SS_TRANSLUCENCY)
+                translucencyIntensity *= thicknessMap.r;
+            #endif
+            thickness = thicknessMap.g * vThicknessParam.y + vThicknessParam.x;
         #endif
     #else
         float thickness = vThicknessParam.y;