From a0626c5634ccadf434c0d998b94db70d34816989 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 14 Mar 2024 22:52:31 +0900 Subject: [PATCH] Can load y-flipped KHR_texture_basisu texture at runtime. --- .../Importer/KtxTextureDeserializer.cs | 48 +++++++++++++++++ .../Importer/KtxTextureDeserializer.cs.meta | 3 ++ .../UnitySupportedImageTypeDeserializer.cs | 34 ++++++++++++ ...nitySupportedImageTypeDeserializer.cs.meta | 3 ++ .../Importer/UnityTextureDeserializer.cs | 53 ++++++------------- 5 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs create mode 100644 Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs.meta create mode 100644 Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs create mode 100644 Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs.meta diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs new file mode 100644 index 000000000..05f38d67b --- /dev/null +++ b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs @@ -0,0 +1,48 @@ +using System; +using System.Threading.Tasks; +using Unity.Collections; +using UnityEngine; +#if USE_COM_UNITY_CLOUD_KTX +using KtxUnity; +#endif + +namespace VRMShaders +{ + public sealed class KtxTextureDeserializer : ITextureDeserializer + { + public async Task LoadTextureAsync(DeserializingTextureInfo textureInfo, IAwaitCaller awaitCaller) + { +#if USE_COM_UNITY_CLOUD_KTX + if (textureInfo.ImageData == null) return null; + + // NOTE: IAwaitCaller を無視するので、同期読み込みを期待する環境で同期読み込みができない + try + { + var ktxTexture = new KtxTexture(); + using var nativeBytes = new NativeArray(textureInfo.ImageData, Allocator.Persistent); + var result = await ktxTexture.LoadFromBytes( + nativeBytes, + linear: textureInfo.ColorSpace == ColorSpace.Linear, + mipChain: textureInfo.UseMipmap + ); + if (result is { errorCode: ErrorCode.Success }) + { + result.texture.wrapModeU = textureInfo.WrapModeU; + result.texture.wrapModeV = textureInfo.WrapModeV; + result.texture.filterMode = textureInfo.FilterMode; + return result.texture; + } + + return null; + } + catch (Exception e) + { + Debug.LogException(e); + return null; + } +#else + return null; +#endif + } + } +} \ No newline at end of file diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs.meta b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs.meta new file mode 100644 index 000000000..42a0f9fa9 --- /dev/null +++ b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/KtxTextureDeserializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 76c69cc9d1f84e988ca6fb6391bee3cb +timeCreated: 1710422105 \ No newline at end of file diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs new file mode 100644 index 000000000..8952089a0 --- /dev/null +++ b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using UnityEngine; + +namespace VRMShaders +{ + /// + /// Unity の ImageConversion.LoadImage を用いて PNG/JPG の読み込みを実現する + /// + public sealed class UnitySupportedImageTypeDeserializer : ITextureDeserializer + { + public async Task LoadTextureAsync(DeserializingTextureInfo textureInfo, IAwaitCaller awaitCaller) + { + if (textureInfo.ImageData == null) return null; + + try + { + var texture = new Texture2D(2, 2, TextureFormat.ARGB32, textureInfo.UseMipmap, textureInfo.ColorSpace == ColorSpace.Linear); + texture.LoadImage(textureInfo.ImageData); + await awaitCaller.NextFrame(); + + texture.wrapModeU = textureInfo.WrapModeU; + texture.wrapModeV = textureInfo.WrapModeV; + texture.filterMode = textureInfo.FilterMode; + return texture; + } + catch (Exception e) + { + Debug.LogException(e); + return null; + } + } + } +} \ No newline at end of file diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs.meta b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs.meta new file mode 100644 index 000000000..183b845c8 --- /dev/null +++ b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnitySupportedImageTypeDeserializer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f9ea656b813c41caaa40318be35b9ed2 +timeCreated: 1710423586 \ No newline at end of file diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnityTextureDeserializer.cs b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnityTextureDeserializer.cs index 16fcdedb1..f3858d44a 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnityTextureDeserializer.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/UnityTextureDeserializer.cs @@ -1,51 +1,30 @@ -using System; -using System.Threading.Tasks; -using Unity.Collections; +using System.Threading.Tasks; using UnityEngine; -#if USE_COM_UNITY_CLOUD_KTX -using KtxUnity; -#endif namespace VRMShaders { /// - /// Unity の ImageConversion.LoadImage を用いて PNG/JPG の読み込みを実現する + /// Runtime での Texture2D 生成を実現するデフォルトの実装 /// public sealed class UnityTextureDeserializer : ITextureDeserializer { + private readonly UnitySupportedImageTypeDeserializer _unitySupportedDeserializer = new(); + private readonly KtxTextureDeserializer _ktxTextureDeserializer = new(); + public async Task LoadTextureAsync(DeserializingTextureInfo textureInfo, IAwaitCaller awaitCaller) { Texture2D texture = null; switch (textureInfo.DataMimeType) { case "image/png": - case "image/jpeg": - texture = new Texture2D(2, 2, TextureFormat.ARGB32, textureInfo.UseMipmap, textureInfo.ColorSpace == ColorSpace.Linear); - if (textureInfo.ImageData != null) - { - texture.LoadImage(textureInfo.ImageData); - await awaitCaller.NextFrame(); - } + texture = await _unitySupportedDeserializer.LoadTextureAsync(textureInfo, awaitCaller); + break; + case "image/jpeg": + texture = await _unitySupportedDeserializer.LoadTextureAsync(textureInfo, awaitCaller); + break; + case "image/ktx2": + texture = await _ktxTextureDeserializer.LoadTextureAsync(textureInfo, awaitCaller); break; -#if USE_COM_UNITY_CLOUD_KTX - case "image/ktx": - var ktxTexture = new KtxTexture(); - var nativeBytes = new NativeArray(textureInfo.ImageData, Allocator.Temp); - try - { - var nativeSlice = new NativeSlice(nativeBytes); - var result = await ktxTexture.LoadFromBytes(nativeSlice, textureInfo.ColorSpace == ColorSpace.Linear); - if (result != null && result.errorCode == ErrorCode.Success) - { - texture = result.texture; - } - break; - } - finally - { - nativeBytes.Dispose(); - } -#endif default: if (string.IsNullOrEmpty(textureInfo.DataMimeType)) { @@ -58,12 +37,12 @@ namespace VRMShaders break; } - if (texture != null) + if (texture == null) { - texture.wrapModeU = textureInfo.WrapModeU; - texture.wrapModeV = textureInfo.WrapModeV; - texture.filterMode = textureInfo.FilterMode; + Debug.Log($"Failed to load texture from image data."); + texture = new Texture2D(2, 2, TextureFormat.ARGB32, textureInfo.UseMipmap, textureInfo.ColorSpace == ColorSpace.Linear); } + return texture; } }