Преглед изворни кода

Use RGBA format for KTX2 files that are not color data if ASTC/BC7 not available when transcoding an UASTC source picture

Popov72 пре 4 година
родитељ
комит
6d661b2510

+ 2 - 2
ktx2Decoder/src/ktx2Decoder.ts

@@ -54,7 +54,7 @@ export interface ICompressedFormatCapabilities {
 
 export interface IKTX2DecoderOptions {
     /** use RGBA format if ASTC and BC7 are not available as transcoded format */
-    useRGBAIfASTCBC7NotAvailable?: boolean;
+    useRGBAIfASTCBC7NotAvailableWhenUASTC?: boolean;
 
     /** force to always use RGBA for transcoded format */
     forceRGBA?: boolean;
@@ -131,7 +131,7 @@ export class KTX2Decoder {
         } else if (caps.bptc) {
             targetFormat = transcodeTarget.BC7_RGBA;
             transcodedFormat = COMPRESSED_RGBA_BPTC_UNORM_EXT;
-        } else if (options?.useRGBAIfASTCBC7NotAvailable) {
+        } else if (options?.useRGBAIfASTCBC7NotAvailableWhenUASTC && srcTexFormat === sourceTextureFormat.UASTC4x4) {
             targetFormat = transcodeTarget.RGBA32;
             transcodedFormat = RGBA8Format;
             roundToMultiple4 = false;

+ 4 - 5
loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts

@@ -2,7 +2,7 @@ import { Nullable } from "babylonjs/types";
 import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
 import { Material } from "babylonjs/Materials/material";
 
-import { IMaterial } from "../glTFLoaderInterfaces";
+import { IMaterial, TextureDataType } from "../glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { GLTFLoader } from "../glTFLoader";
 import { IKHRMaterialsClearcoat } from 'babylonjs-gltf2interface';
@@ -10,9 +10,8 @@ import { IKHRMaterialsClearcoat } from 'babylonjs-gltf2interface';
 const NAME = "KHR_materials_clearcoat";
 
 /**
- * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1677)
+ * [Specification](https://github.com/KhronosGroup/glTF/pull/1677)
  * [Playground Sample](https://www.babylonjs-playground.com/frame.html#7F7PN6#8)
- * !!! Experimental Extension Subject to Changes !!!
  */
 export class KHR_materials_clearcoat implements IGLTFLoaderExtension {
     /**
@@ -89,14 +88,14 @@ export class KHR_materials_clearcoat implements IGLTFLoaderExtension {
             promises.push(this._loader.loadTextureInfoAsync(`${context}/clearcoatRoughnessTexture`, properties.clearcoatRoughnessTexture, (texture) => {
                 texture.name = `${babylonMaterial.name} (ClearCoat Roughness)`;
                 babylonMaterial.clearCoat.textureRoughness = texture;
-            }));
+            }, TextureDataType.roughness));
         }
 
         if (properties.clearcoatNormalTexture) {
             promises.push(this._loader.loadTextureInfoAsync(`${context}/clearcoatNormalTexture`, properties.clearcoatNormalTexture, (texture) => {
                 texture.name = `${babylonMaterial.name} (ClearCoat Normal)`;
                 babylonMaterial.clearCoat.bumpTexture = texture;
-            }));
+            }, TextureDataType.normal));
 
             babylonMaterial.invertNormalMapX = !babylonMaterial.getScene().useRightHandedSystem;
             babylonMaterial.invertNormalMapY = babylonMaterial.getScene().useRightHandedSystem;

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

@@ -3,7 +3,7 @@ import { Color3 } from "babylonjs/Maths/math.color";
 import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
 import { Material } from "babylonjs/Materials/material";
 
-import { IMaterial } from "../glTFLoaderInterfaces";
+import { IMaterial, TextureDataType } from "../glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { GLTFLoader } from "../glTFLoader";
 import { IKHRMaterialsPbrSpecularGlossiness } from 'babylonjs-gltf2interface';
@@ -85,7 +85,7 @@ export class KHR_materials_pbrSpecularGlossiness implements IGLTFLoaderExtension
             promises.push(this._loader.loadTextureInfoAsync(`${context}/specularGlossinessTexture`, properties.specularGlossinessTexture, (texture) => {
                 texture.name = `${babylonMaterial.name} (Specular Glossiness)`;
                 babylonMaterial.reflectivityTexture = texture;
-            }));
+            }, TextureDataType.glossiness));
 
             babylonMaterial.reflectivityTexture.hasAlpha = true;
             babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;

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

@@ -2,7 +2,7 @@ import { Nullable } from "babylonjs/types";
 import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
 import { Material } from "babylonjs/Materials/material";
 
-import { IMaterial } from "../glTFLoaderInterfaces";
+import { IMaterial, TextureDataType } from "../glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { GLTFLoader } from "../glTFLoader";
 import { Color3 } from 'babylonjs/Maths/math.color';
@@ -88,7 +88,7 @@ export class KHR_materials_sheen implements IGLTFLoaderExtension {
             promises.push(this._loader.loadTextureInfoAsync(`${context}/sheenRoughnessTexture`, properties.sheenRoughnessTexture, (texture) => {
                 texture.name = `${babylonMaterial.name} (Sheen Roughness)`;
                 babylonMaterial.sheen.textureRoughness = texture;
-            }));
+            }, TextureDataType.roughness));
         }
 
         babylonMaterial.sheen.albedoScaling = true;

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

@@ -2,7 +2,7 @@ import { Nullable } from "babylonjs/types";
 import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
 import { Material } from "babylonjs/Materials/material";
 
-import { IMaterial } from "../glTFLoaderInterfaces";
+import { IMaterial, TextureDataType } from "../glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { GLTFLoader } from "../glTFLoader";
 import { Color3 } from 'babylonjs/Maths/math.color';
@@ -72,7 +72,7 @@ export class KHR_materials_specular implements IGLTFLoaderExtension {
             promises.push(this._loader.loadTextureInfoAsync(`${context}/specularTexture`, properties.specularTexture, (texture) => {
                 texture.name = `${babylonMaterial.name} (Specular F0 Color)`;
                 babylonMaterial.metallicReflectanceTexture = texture;
-            }));
+            }, TextureDataType.specular));
         }
 
         return Promise.all(promises).then(() => { });

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

@@ -2,7 +2,7 @@ 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 { IMaterial, TextureDataType } from "../glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { GLTFLoader } from "../glTFLoader";
 import { IKHRMaterialsTransmission } from 'babylonjs-gltf2interface';
@@ -324,7 +324,7 @@ export class KHR_materials_transmission implements IGLTFLoaderExtension {
         }
 
         if (extension.transmissionTexture) {
-            return this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture)
+            return this._loader.loadTextureInfoAsync(`${context}/transmissionTexture`, extension.transmissionTexture, undefined, TextureDataType.transmission)
                 .then((texture: BaseTexture) => {
                     pbrMaterial.subSurface.thicknessTexture = texture;
                     pbrMaterial.subSurface.useMaskFromThicknessTexture = true;

+ 3 - 3
loaders/src/glTF/2.0/Extensions/KHR_texture_basisu.ts

@@ -1,6 +1,6 @@
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { GLTFLoader, ArrayItem } from "../glTFLoader";
-import { ITexture } from "../glTFLoaderInterfaces";
+import { ITexture, TextureDataType } from "../glTFLoaderInterfaces";
 import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
 import { Nullable } from "babylonjs/types";
 import { IKHRTextureBasisU } from 'babylonjs-gltf2interface';
@@ -32,13 +32,13 @@ export class KHR_texture_basisu implements IGLTFLoaderExtension {
     }
 
     /** @hidden */
-    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {
+    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void, textureDataType: TextureDataType = TextureDataType.color): Nullable<Promise<BaseTexture>> {
         return GLTFLoader.LoadExtensionAsync<IKHRTextureBasisU, BaseTexture>(context, texture, this.name, (extensionContext, extension) => {
             const sampler = (texture.sampler == undefined ? GLTFLoader.DefaultSampler : ArrayItem.Get(`${context}/sampler`, this._loader.gltf.samplers, texture.sampler));
             const image = ArrayItem.Get(`${extensionContext}/source`, this._loader.gltf.images, extension.source);
             return this._loader._createTextureAsync(context, sampler, image, (babylonTexture) => {
                 assign(babylonTexture);
-            });
+            }, textureDataType === TextureDataType.color ? undefined : { useRGBAIfASTCBC7NotAvailableWhenUASTC: true });
         });
     }
 }

+ 3 - 3
loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts

@@ -2,7 +2,7 @@ import { Nullable } from "babylonjs/types";
 import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
 import { Texture } from "babylonjs/Materials/Textures/texture";
 
-import { ITextureInfo } from "../glTFLoaderInterfaces";
+import { ITextureInfo, TextureDataType } from "../glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { GLTFLoader } from "../glTFLoader";
 import { IKHRTextureTransform } from 'babylonjs-gltf2interface';
@@ -37,7 +37,7 @@ export class KHR_texture_transform implements IGLTFLoaderExtension {
     }
 
     /** @hidden */
-    public loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {
+    public loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void, textureDataType: TextureDataType = TextureDataType.color): Nullable<Promise<BaseTexture>> {
         return GLTFLoader.LoadExtensionAsync<IKHRTextureTransform, BaseTexture>(context, textureInfo, this.name, (extensionContext, extension) => {
             return this._loader.loadTextureInfoAsync(context, textureInfo, (babylonTexture) => {
                 if (!(babylonTexture instanceof Texture)) {
@@ -67,7 +67,7 @@ export class KHR_texture_transform implements IGLTFLoaderExtension {
                 }
 
                 assign(babylonTexture);
-            });
+            }, textureDataType);
         });
     }
 }

+ 16 - 15
loaders/src/glTF/2.0/glTFLoader.ts

@@ -24,7 +24,7 @@ import { MorphTargetManager } from "babylonjs/Morph/morphTargetManager";
 import { ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
 import { Scene } from "babylonjs/scene";
 import { IProperty, AccessorType, CameraType, AnimationChannelTargetPath, AnimationSamplerInterpolation, AccessorComponentType, MaterialAlphaMode, TextureMinFilter, TextureWrapMode, TextureMagFilter, MeshPrimitiveMode } from "babylonjs-gltf2interface";
-import { _IAnimationSamplerData, IGLTF, ISampler, INode, IScene, IMesh, IAccessor, ISkin, ICamera, IAnimation, IAnimationChannel, IAnimationSampler, IBuffer, IBufferView, IMaterialPbrMetallicRoughness, IMaterial, ITextureInfo, ITexture, IImage, IMeshPrimitive, IArrayItem as IArrItem, _ISamplerData } from "./glTFLoaderInterfaces";
+import { _IAnimationSamplerData, IGLTF, ISampler, INode, IScene, IMesh, IAccessor, ISkin, ICamera, IAnimation, IAnimationChannel, IAnimationSampler, IBuffer, IBufferView, IMaterialPbrMetallicRoughness, IMaterial, ITextureInfo, ITexture, IImage, IMeshPrimitive, IArrayItem as IArrItem, _ISamplerData, TextureDataType } from "./glTFLoaderInterfaces";
 import { IGLTFLoaderExtension } from "./glTFLoaderExtension";
 import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData, GLTFLoaderCoordinateSystemMode, GLTFLoaderAnimationStartMode, IImportMeshAsyncOutput } from "../glTFFileLoader";
 import { IAnimationKey, AnimationKeyInterpolation } from 'babylonjs/Animations/animationKey';
@@ -1692,7 +1692,7 @@ export class GLTFLoader implements IGLTFLoader {
                 promises.push(this.loadTextureInfoAsync(`${context}/metallicRoughnessTexture`, properties.metallicRoughnessTexture, (texture) => {
                     texture.name = `${babylonMaterial.name} (Metallic Roughness)`;
                     babylonMaterial.metallicTexture = texture;
-                }));
+                }, TextureDataType.metallicRoughness));
 
                 babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
                 babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
@@ -1833,7 +1833,7 @@ export class GLTFLoader implements IGLTFLoader {
             promises.push(this.loadTextureInfoAsync(`${context}/normalTexture`, material.normalTexture, (texture) => {
                 texture.name = `${babylonMaterial.name} (Normal)`;
                 babylonMaterial.bumpTexture = texture;
-            }));
+            }, TextureDataType.normal));
 
             babylonMaterial.invertNormalMapX = !this._babylonScene.useRightHandedSystem;
             babylonMaterial.invertNormalMapY = this._babylonScene.useRightHandedSystem;
@@ -1848,7 +1848,7 @@ export class GLTFLoader implements IGLTFLoader {
             promises.push(this.loadTextureInfoAsync(`${context}/occlusionTexture`, material.occlusionTexture, (texture) => {
                 texture.name = `${babylonMaterial.name} (Occlusion)`;
                 babylonMaterial.ambientTexture = texture;
-            }));
+            }, TextureDataType.occlusion));
 
             babylonMaterial.useAmbientInGrayScale = true;
             if (material.occlusionTexture.strength != undefined) {
@@ -1911,10 +1911,11 @@ export class GLTFLoader implements IGLTFLoader {
      * @param context The context when loading the asset
      * @param textureInfo The glTF texture info property
      * @param assign A function called synchronously after parsing the glTF properties
+     * @param textureDataType type of data held by the texture
      * @returns A promise that resolves with the loaded Babylon texture when the load is complete
      */
-    public loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void = () => { }): Promise<BaseTexture> {
-        const extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
+    public loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void = () => { }, textureDataType: TextureDataType = TextureDataType.color): Promise<BaseTexture> {
+        const extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign, textureDataType);
         if (extensionPromise) {
             return extensionPromise;
         }
@@ -1931,7 +1932,7 @@ export class GLTFLoader implements IGLTFLoader {
             GLTFLoader.AddPointerMetadata(babylonTexture, context);
             this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
             assign(babylonTexture);
-        });
+        }, textureDataType);
 
         this.logClose();
 
@@ -1939,8 +1940,8 @@ export class GLTFLoader implements IGLTFLoader {
     }
 
     /** @hidden */
-    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void = () => { }): Promise<BaseTexture> {
-        const extensionPromise = this._extensionsLoadTextureAsync(context, texture, assign);
+    public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void = () => { }, textureDataType: TextureDataType = TextureDataType.color): Promise<BaseTexture> {
+        const extensionPromise = this._extensionsLoadTextureAsync(context, texture, assign, textureDataType);
         if (extensionPromise) {
             return extensionPromise;
         }
@@ -1957,7 +1958,7 @@ export class GLTFLoader implements IGLTFLoader {
     }
 
     /** @hidden */
-    public _createTextureAsync(context: string, sampler: ISampler, image: IImage, assign: (babylonTexture: BaseTexture) => void = () => { }): Promise<BaseTexture> {
+    public _createTextureAsync(context: string, sampler: ISampler, image: IImage, assign: (babylonTexture: BaseTexture) => void = () => { }, textureLoaderOptions?: any): Promise<BaseTexture> {
         const samplerData = this._loadSampler(`/samplers/${sampler.index}`, sampler);
 
         const promises = new Array<Promise<any>>();
@@ -1972,7 +1973,7 @@ export class GLTFLoader implements IGLTFLoader {
             if (!this._disposed) {
                 deferred.reject(new Error(`${context}: ${(exception && exception.message) ? exception.message : message || "Failed to load texture"}`));
             }
-        }, undefined, undefined, undefined, image.mimeType);
+        }, undefined, undefined, undefined, image.mimeType, textureLoaderOptions);
         this._babylonScene._blockEntityCollection = false;
         promises.push(deferred.promise);
 
@@ -2317,12 +2318,12 @@ export class GLTFLoader implements IGLTFLoader {
         return this._applyExtensions(material, "loadMaterialProperties", (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial));
     }
 
-    private _extensionsLoadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {
-        return this._applyExtensions(textureInfo, "loadTextureInfo", (extension) => extension.loadTextureInfoAsync && extension.loadTextureInfoAsync(context, textureInfo, assign));
+    private _extensionsLoadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void, textureDataType: TextureDataType): Nullable<Promise<BaseTexture>> {
+        return this._applyExtensions(textureInfo, "loadTextureInfo", (extension) => extension.loadTextureInfoAsync && extension.loadTextureInfoAsync(context, textureInfo, assign, textureDataType));
     }
 
-    private _extensionsLoadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {
-        return this._applyExtensions(texture, "loadTexture", (extension) => extension._loadTextureAsync && extension._loadTextureAsync(context, texture, assign));
+    private _extensionsLoadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void, textureDataType: TextureDataType): Nullable<Promise<BaseTexture>> {
+        return this._applyExtensions(texture, "loadTexture", (extension) => extension._loadTextureAsync && extension._loadTextureAsync(context, texture, assign, textureDataType));
     }
 
     private _extensionsLoadAnimationAsync(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>> {

+ 5 - 3
loaders/src/glTF/2.0/glTFLoaderExtension.ts

@@ -8,7 +8,7 @@ import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
 import { Mesh } from "babylonjs/Meshes/mesh";
 import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
 import { IDisposable } from "babylonjs/scene";
-import { IScene, INode, IMesh, ISkin, ICamera, IMeshPrimitive, IMaterial, ITextureInfo, IAnimation, ITexture, IBufferView, IBuffer } from "./glTFLoaderInterfaces";
+import { IScene, INode, IMesh, ISkin, ICamera, IMeshPrimitive, IMaterial, ITextureInfo, IAnimation, ITexture, IBufferView, IBuffer, TextureDataType } from "./glTFLoaderInterfaces";
 import { IGLTFLoaderExtension as IGLTFBaseLoaderExtension } from "../glTFFileLoader";
 import { IProperty } from 'babylonjs-gltf2interface';
 
@@ -107,9 +107,10 @@ export interface IGLTFLoaderExtension extends IGLTFBaseLoaderExtension, IDisposa
      * @param context The context when loading the asset
      * @param textureInfo The glTF texture info property
      * @param assign A function called synchronously after parsing the glTF properties
+     * @param textureDataType type of data held by the texture
      * @returns A promise that resolves with the loaded Babylon texture when the load is complete or null if not handled
      */
-    loadTextureInfoAsync?(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>>;
+    loadTextureInfoAsync?(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void, textureDataType: TextureDataType): Nullable<Promise<BaseTexture>>;
 
     /**
      * @hidden
@@ -117,9 +118,10 @@ export interface IGLTFLoaderExtension extends IGLTFBaseLoaderExtension, IDisposa
      * @param context The context when loading the asset
      * @param texture The glTF texture property
      * @param assign A function called synchronously after parsing the glTF properties
+     * @param textureDataType type of data held by the texture
      * @returns A promise that resolves with the loaded Babylon texture when the load is complete or null if not handled
      */
-    _loadTextureAsync?(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>>;
+    _loadTextureAsync?(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void, textureDataType: TextureDataType): Nullable<Promise<BaseTexture>>;
 
     /**
      * Define this method to modify the default behavior when loading animations.

+ 14 - 0
loaders/src/glTF/2.0/glTFLoaderInterfaces.ts

@@ -208,6 +208,20 @@ export interface ISkin extends GLTF2.ISkin, IArrayItem {
 }
 
 /**
+ * Type of data held by a texture
+ */
+export const enum TextureDataType {
+    color,
+    roughness,
+    normal,
+    glossiness,
+    specular,
+    transmission,
+    metallicRoughness,
+    occlusion
+}
+
+/**
  * Loader interface with additional members.
  */
 export interface ITexture extends GLTF2.ITexture, IArrayItem {