From fa5d1bd417b933e44c4269a042257928dfad9d1a Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Tue, 19 May 2026 13:24:21 +0200 Subject: [PATCH] Add shared KTX2 loader management utilities --- src/assets/ktx2-texture-support.ts | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/assets/ktx2-texture-support.ts diff --git a/src/assets/ktx2-texture-support.ts b/src/assets/ktx2-texture-support.ts new file mode 100644 index 00000000..a6a0e4b0 --- /dev/null +++ b/src/assets/ktx2-texture-support.ts @@ -0,0 +1,64 @@ +import { WebGLRenderer, type WebGLRendererParameters } from "three"; +import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader.js"; + +const KTX2_TRANSCODER_PATH = "/basis/"; + +let sharedKtx2Loader: KTX2Loader | null = null; +let sharedKtx2LoaderInitialized = false; +let fallbackRenderer: WebGLRenderer | null = null; + +function getErrorDetail(error: unknown): string { + if (error instanceof Error && error.message.trim().length > 0) { + return error.message.trim(); + } + + return "Unknown error."; +} + +function createSharedKtx2Loader(): KTX2Loader { + const loader = new KTX2Loader(); + loader.setTranscoderPath(KTX2_TRANSCODER_PATH); + return loader; +} + +export function getSharedKtx2LoaderIfInitialized(): KTX2Loader | null { + return sharedKtx2LoaderInitialized ? sharedKtx2Loader : null; +} + +export function initializeSharedKtx2Loader(renderer: WebGLRenderer): KTX2Loader { + if (sharedKtx2Loader === null) { + sharedKtx2Loader = createSharedKtx2Loader(); + } + + sharedKtx2Loader.detectSupport(renderer); + sharedKtx2LoaderInitialized = true; + return sharedKtx2Loader; +} + +function createFallbackRenderer(): WebGLRenderer { + const parameters: WebGLRendererParameters = { + antialias: false, + alpha: false, + powerPreference: "low-power" + }; + + return new WebGLRenderer(parameters); +} + +export function ensureSharedKtx2LoaderInitialized(): KTX2Loader { + if (sharedKtx2LoaderInitialized && sharedKtx2Loader !== null) { + return sharedKtx2Loader; + } + + try { + if (fallbackRenderer === null) { + fallbackRenderer = createFallbackRenderer(); + } + + return initializeSharedKtx2Loader(fallbackRenderer); + } catch (error) { + throw new Error( + `KTX2 texture support could not be initialized. WebGL compressed texture support is required to load KTX2 model textures. ${getErrorDetail(error)}` + ); + } +}