diff --git a/packages/dev/inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx b/packages/dev/inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx index 6464776fa01..3917a0c9a35 100644 --- a/packages/dev/inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx +++ b/packages/dev/inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx @@ -148,6 +148,11 @@ export class GLTFComponent extends React.Component { isSelected={() => extensionStates["EXT_texture_webp"].enabled} onSelect={(value) => (extensionStates["EXT_texture_webp"].enabled = value)} /> + extensionStates["EXT_texture_avif"].enabled} + onSelect={(value) => (extensionStates["EXT_texture_avif"].enabled = value)} + /> extensionStates["KHR_draco_mesh_compression"].enabled} diff --git a/packages/dev/inspector/src/components/globalState.ts b/packages/dev/inspector/src/components/globalState.ts index b31c1bf17d5..47e22428d50 100644 --- a/packages/dev/inspector/src/components/globalState.ts +++ b/packages/dev/inspector/src/components/globalState.ts @@ -61,6 +61,7 @@ export class GlobalState { EXT_lights_image_based: { enabled: true }, EXT_mesh_gpu_instancing: { enabled: true }, EXT_texture_webp: { enabled: true }, + EXT_texture_avif: { enabled: true }, }; public glTFLoaderDefaults: { [key: string]: any } = { diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_texture_avif.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_texture_avif.ts new file mode 100644 index 00000000000..01c082e78cd --- /dev/null +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/EXT_texture_avif.ts @@ -0,0 +1,58 @@ +import type { IGLTFLoaderExtension } from "../glTFLoaderExtension"; +import { GLTFLoader, ArrayItem } from "../glTFLoader"; +import type { ITexture } from "../glTFLoaderInterfaces"; +import type { BaseTexture } from "core/Materials/Textures/baseTexture"; +import type { Nullable } from "core/types"; +import type { IEXTTextureAVIF } from "babylonjs-gltf2interface"; + +const NAME = "EXT_texture_avif"; + +/** + * [glTF PR](https://github.com/KhronosGroup/glTF/pull/2235) + * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_texture_avif/README.md) + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export class EXT_texture_avif implements IGLTFLoaderExtension { + /** The name of this extension. */ + public readonly name = NAME; + + /** Defines whether this extension is enabled. */ + public enabled: boolean; + + private _loader: GLTFLoader; + + /** + * @internal + */ + constructor(loader: GLTFLoader) { + this._loader = loader; + this.enabled = loader.isExtensionUsed(NAME); + } + + /** @internal */ + public dispose() { + (this._loader as any) = null; + } + + /** + * @internal + */ + public _loadTextureAsync(context: string, texture: ITexture, assign: (babylonTexture: BaseTexture) => void): Nullable> { + return GLTFLoader.LoadExtensionAsync(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); + }, + undefined, + !texture._textureInfo.nonColorData + ); + }); + } +} + +GLTFLoader.RegisterExtension(NAME, (loader) => new EXT_texture_avif(loader)); diff --git a/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts b/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts index 36c11cf1050..923024e679b 100644 --- a/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts +++ b/packages/dev/loaders/src/glTF/2.0/Extensions/index.ts @@ -2,6 +2,7 @@ export * from "./EXT_lights_image_based"; export * from "./EXT_mesh_gpu_instancing"; export * from "./EXT_meshopt_compression"; export * from "./EXT_texture_webp"; +export * from "./EXT_texture_avif"; export * from "./KHR_draco_mesh_compression"; export * from "./KHR_lights_punctual"; export * from "./KHR_materials_pbrSpecularGlossiness"; diff --git a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts index 3d4d28340e4..1c37db9c5d5 100644 --- a/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts +++ b/packages/dev/serializers/src/glTF/2.0/glTFMaterialExporter.ts @@ -78,6 +78,8 @@ function getFileExtensionFromMimeType(mimeType: ImageMimeType): string { return ".png"; case ImageMimeType.WEBP: return ".webp"; + case ImageMimeType.AVIF: + return ".avif"; } } diff --git a/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts b/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts index 36736a19716..dd1b80847fb 100644 --- a/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts +++ b/packages/public/glTF2Interface/babylon.glTF2Interface.d.ts @@ -148,6 +148,10 @@ declare module BABYLON.GLTF2 { * WEBP Mime-type */ WEBP = "image/webp", + /** + * AVIF Mime-type + */ + AVIF = "image/avif", } /** @@ -1204,6 +1208,15 @@ declare module BABYLON.GLTF2 { source: number; } + /** + * Interfaces from the EXT_texture_avif extension + */ + + /** @internal */ + interface IEXTTextureAVIF { + source: number; + } + /** * Interfaces from the KHR_texture_transform extension */