Browse Source

First support of KHR_materials_transmission

Michael Bond 5 years ago
parent
commit
5755673f57

+ 1 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx

@@ -252,6 +252,7 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                             <SliderLineComponent label="Index of Refraction" target={material.subSurface} propertyName="indexOfRefraction" minimum={1} maximum={2} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <SliderLineComponent label="Index of Refraction" target={material.subSurface} propertyName="indexOfRefraction" minimum={1} maximum={2} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <SliderLineComponent label="Tint at Distance" target={material.subSurface} propertyName="tintColorAtDistance" minimum={0} maximum={10} step={0.1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <SliderLineComponent label="Tint at Distance" target={material.subSurface} propertyName="tintColorAtDistance" minimum={0} maximum={10} step={0.1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <CheckBoxLineComponent label="Link refraction with transparency" target={material.subSurface} propertyName="linkRefractionWithTransparency" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <CheckBoxLineComponent label="Link refraction with transparency" target={material.subSurface} propertyName="linkRefractionWithTransparency" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <CheckBoxLineComponent label="Use albedo to tint surface transparency" target={material.subSurface} propertyName="useAlbedoToTintRefraction" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         </div>
                         </div>
                     }
                     }
 
 

+ 101 - 0
loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts

@@ -0,0 +1,101 @@
+import { Nullable } from "babylonjs/types";
+// import { Color3 } from "babylonjs/Maths/math";
+// import { Mesh } from "babylonjs/Meshes/mesh";
+// import { TransformNode } from "babylonjs/Meshes/transformNode";
+import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
+import { Material } from "babylonjs/Materials/material";
+import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
+
+// import { IChildRootProperty } from "babylonjs-gltf2interface";
+import { IMaterial, ITextureInfo } from "../glTFLoaderInterfaces";
+import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
+import { GLTFLoader } from "../glTFLoader";
+// import { PBRBaseMaterial } from 'babylonjs/Materials/PBR/pbrBaseMaterial';
+
+const NAME = "KHR_materials_transmission";
+
+interface IMaterialsTransmission {
+    transmissionFactor?: number;
+    transmissionTexture?: ITextureInfo;
+}
+
+/**
+ * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1698)
+ * !!! Experimental Extension Subject to Changes !!!
+ */
+export class KHR_materials_transmission 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 = 190;
+
+    private _loader: GLTFLoader;
+
+    /** @hidden */
+    constructor(loader: GLTFLoader) {
+        this._loader = loader;
+        (loader as any)._parent.transparencyAsCoverage = true;
+        this.enabled = this._loader.isExtensionUsed(NAME);
+    }
+
+    /** @hidden */
+    public dispose() {
+        delete this._loader;
+    }
+
+    /** @hidden */
+    public loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
+        return GLTFLoader.LoadExtensionAsync<IMaterialsTransmission>(context, material, this.name, (extensionContext, extension) => {
+            console.log(extensionContext);
+            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._loadTransparentPropertiesAsync(context, material, babylonMaterial, extension));
+            return Promise.all(promises).then(() => { });
+        });
+    }
+
+    private _loadTransparentPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material, extension: IMaterialsTransmission): Promise<void> {
+        if (!(babylonMaterial instanceof PBRMaterial)) {
+            throw new Error(`${context}: Material type not supported`);
+        }
+        let pbrMaterial = babylonMaterial as PBRMaterial;
+        
+        // Enables "refraction" texture which represents transmitted light.
+        pbrMaterial.subSurface.isRefractionEnabled = true;
+
+        // Since this extension models thin-surface transmission only, we must make IOR = 1.0
+        pbrMaterial.subSurface.indexOfRefraction = 1.0;
+
+        // Albedo colour will tint transmission.
+        pbrMaterial.subSurface.useAlbedoToTintRefraction = true;
+
+        if (extension.transmissionFactor !== undefined) {
+            pbrMaterial.subSurface.refractionIntensity = extension.transmissionFactor;
+        } else {
+            pbrMaterial.subSurface.refractionIntensity = 1.0;
+        }
+
+        if (extension.transmissionTexture) {
+            return this._loader.loadTextureInfoAsync(context, extension.transmissionTexture)
+                .then((texture: BaseTexture) => {
+                    pbrMaterial.subSurface.thicknessTexture = texture;
+                    pbrMaterial.subSurface.useMaskFromThicknessTexture = true;
+                });
+        } else {
+            return Promise.resolve();
+        }
+    }
+}
+
+GLTFLoader.RegisterExtension(NAME, (loader) => new KHR_materials_transmission(loader));

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

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

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

@@ -230,7 +230,7 @@ export class PBRMaterialDefines extends MaterialDefines
 
 
     public SS_REFRACTION = false;
     public SS_REFRACTION = false;
     public SS_TRANSLUCENCY = false;
     public SS_TRANSLUCENCY = false;
-    public SS_SCATERRING = false;
+    public SS_SCATTERING = false;
 
 
     public SS_THICKNESSANDMASK_TEXTURE = false;
     public SS_THICKNESSANDMASK_TEXTURE = false;
     public SS_THICKNESSANDMASK_TEXTUREDIRECTUV = 0;
     public SS_THICKNESSANDMASK_TEXTUREDIRECTUV = 0;
@@ -242,6 +242,7 @@ export class PBRMaterialDefines extends MaterialDefines
     public SS_RGBDREFRACTION = false;
     public SS_RGBDREFRACTION = false;
     public SS_LINEARSPECULARREFRACTION = false;
     public SS_LINEARSPECULARREFRACTION = false;
     public SS_LINKREFRACTIONTOTRANSPARENCY = false;
     public SS_LINKREFRACTIONTOTRANSPARENCY = false;
+    public SS_ALBEDOFORREFRACTIONTINT = false;
 
 
     public SS_MASK_FROM_THICKNESS_TEXTURE = false;
     public SS_MASK_FROM_THICKNESS_TEXTURE = false;
 
 

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

@@ -23,7 +23,7 @@ export interface IMaterialSubSurfaceDefines {
 
 
     SS_REFRACTION: boolean;
     SS_REFRACTION: boolean;
     SS_TRANSLUCENCY: boolean;
     SS_TRANSLUCENCY: boolean;
-    SS_SCATERRING: boolean;
+    SS_SCATTERING: boolean;
 
 
     SS_THICKNESSANDMASK_TEXTURE: boolean;
     SS_THICKNESSANDMASK_TEXTURE: boolean;
     SS_THICKNESSANDMASK_TEXTUREDIRECTUV: number;
     SS_THICKNESSANDMASK_TEXTUREDIRECTUV: number;
@@ -35,6 +35,7 @@ export interface IMaterialSubSurfaceDefines {
     SS_RGBDREFRACTION: boolean;
     SS_RGBDREFRACTION: boolean;
     SS_LINEARSPECULARREFRACTION: boolean;
     SS_LINEARSPECULARREFRACTION: boolean;
     SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
     SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
+    SS_ALBEDOFORREFRACTIONTINT: boolean;
 
 
     SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
     SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
 
 
@@ -94,6 +95,12 @@ export class PBRSubSurfaceConfiguration {
     @serialize()
     @serialize()
     public scatteringIntensity: number = 1;
     public scatteringIntensity: number = 1;
 
 
+    /**
+     * When enabled, transparent surfaces will be tinted with the albedo colour (independent of thickness)
+     */
+    @serialize()
+    public useAlbedoToTintRefraction: boolean = false;
+
     private _thicknessTexture: Nullable<BaseTexture> = null;
     private _thicknessTexture: Nullable<BaseTexture> = null;
     /**
     /**
      * Stores the average thickness of a mesh in a texture (The texture is holding the values linearly).
      * Stores the average thickness of a mesh in a texture (The texture is holding the values linearly).
@@ -242,7 +249,7 @@ export class PBRSubSurfaceConfiguration {
             defines.SUBSURFACE = false;
             defines.SUBSURFACE = false;
 
 
             defines.SS_TRANSLUCENCY = this._isTranslucencyEnabled;
             defines.SS_TRANSLUCENCY = this._isTranslucencyEnabled;
-            defines.SS_SCATERRING = this._isScatteringEnabled;
+            defines.SS_SCATTERING = this._isScatteringEnabled;
             defines.SS_THICKNESSANDMASK_TEXTURE = false;
             defines.SS_THICKNESSANDMASK_TEXTURE = false;
             defines.SS_MASK_FROM_THICKNESS_TEXTURE = false;
             defines.SS_MASK_FROM_THICKNESS_TEXTURE = false;
             defines.SS_REFRACTION = false;
             defines.SS_REFRACTION = false;
@@ -253,6 +260,7 @@ export class PBRSubSurfaceConfiguration {
             defines.SS_REFRACTIONMAP_OPPOSITEZ = false;
             defines.SS_REFRACTIONMAP_OPPOSITEZ = false;
             defines.SS_LODINREFRACTIONALPHA = false;
             defines.SS_LODINREFRACTIONALPHA = false;
             defines.SS_LINKREFRACTIONTOTRANSPARENCY = false;
             defines.SS_LINKREFRACTIONTOTRANSPARENCY = false;
+            defines.SS_ALBEDOFORREFRACTIONTINT = false;
 
 
             if (this._isRefractionEnabled || this._isTranslucencyEnabled || this._isScatteringEnabled) {
             if (this._isRefractionEnabled || this._isTranslucencyEnabled || this._isScatteringEnabled) {
                 defines.SUBSURFACE = true;
                 defines.SUBSURFACE = true;
@@ -280,6 +288,7 @@ export class PBRSubSurfaceConfiguration {
                         defines.SS_REFRACTIONMAP_OPPOSITEZ = refractionTexture.invertZ;
                         defines.SS_REFRACTIONMAP_OPPOSITEZ = refractionTexture.invertZ;
                         defines.SS_LODINREFRACTIONALPHA = refractionTexture.lodLevelInAlpha;
                         defines.SS_LODINREFRACTIONALPHA = refractionTexture.lodLevelInAlpha;
                         defines.SS_LINKREFRACTIONTOTRANSPARENCY = this._linkRefractionWithTransparency;
                         defines.SS_LINKREFRACTIONTOTRANSPARENCY = this._linkRefractionWithTransparency;
+                        defines.SS_ALBEDOFORREFRACTIONTINT = this.useAlbedoToTintRefraction;
                     }
                     }
                 }
                 }
             }
             }
@@ -496,8 +505,8 @@ export class PBRSubSurfaceConfiguration {
      * @returns the new fallback rank.
      * @returns the new fallback rank.
      */
      */
     public static AddFallbacks(defines: IMaterialSubSurfaceDefines, fallbacks: EffectFallbacks, currentRank: number): number {
     public static AddFallbacks(defines: IMaterialSubSurfaceDefines, fallbacks: EffectFallbacks, currentRank: number): number {
-        if (defines.SS_SCATERRING) {
-            fallbacks.addFallback(currentRank++, "SS_SCATERRING");
+        if (defines.SS_SCATTERING) {
+            fallbacks.addFallback(currentRank++, "SS_SCATTERING");
         }
         }
         if (defines.SS_TRANSLUCENCY) {
         if (defines.SS_TRANSLUCENCY) {
             fallbacks.addFallback(currentRank++, "SS_TRANSLUCENCY");
             fallbacks.addFallback(currentRank++, "SS_TRANSLUCENCY");

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

@@ -270,6 +270,11 @@ struct subSurfaceOutParams
             refractionTransmittance *= cocaLambert(volumeAlbedo, vThicknessParam.y);
             refractionTransmittance *= cocaLambert(volumeAlbedo, vThicknessParam.y);
         #endif
         #endif
 
 
+        #ifdef SS_ALBEDOFORREFRACTIONTINT
+            // Tint the transmission with albedo.
+            environmentRefraction.rgb *= surfaceAlbedo.rgb;
+        #endif
+
         // Decrease Albedo Contribution
         // Decrease Albedo Contribution
         outParams.surfaceAlbedo = surfaceAlbedo * (1. - refractionIntensity);
         outParams.surfaceAlbedo = surfaceAlbedo * (1. - refractionIntensity);