diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/NormalConverter.cs b/Assets/VRMShaders/GLTF/IO/Runtime/NormalConverter.cs index 6dad706b1..99b8f3281 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/NormalConverter.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/NormalConverter.cs @@ -36,14 +36,14 @@ namespace VRMShaders // ConvertToNormalValueFromRawColorWhenCompressionIsRequired public static Texture2D Import(Texture2D texture) { - return TextureConverter.Convert(texture, ColorSpace.Linear, null, Encoder); + return TextureConverter.CopyTexture(texture, ColorSpace.Linear, false, Encoder); } // Unity texture to GLTF data // ConvertToRawColorWhenNormalValueIsCompressed public static Texture2D Export(Texture texture) { - return TextureConverter.Convert(texture, ColorSpace.Linear, null, Decoder); + return TextureConverter.CopyTexture(texture, ColorSpace.Linear, false, Decoder); } } } diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/OcclusionMetallicRoughnessConverter.cs b/Assets/VRMShaders/GLTF/IO/Runtime/OcclusionMetallicRoughnessConverter.cs index 20483665c..83eaf32ec 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/OcclusionMetallicRoughnessConverter.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/OcclusionMetallicRoughnessConverter.cs @@ -26,11 +26,12 @@ namespace VRMShaders public static Texture2D Import(Texture2D metallicRoughnessTexture, float metallicFactor, float roughnessFactor, Texture2D occlusionTexture) { + // TODO: Replace with Shader implementation if (metallicRoughnessTexture != null && occlusionTexture != null) { if (metallicRoughnessTexture == occlusionTexture) { - var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, null); + var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, true, null); var metallicRoughnessPixels = copyMetallicRoughness.GetPixels32(); for (int i = 0; i < metallicRoughnessPixels.Length; ++i) { @@ -43,9 +44,9 @@ namespace VRMShaders } else { - var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, null); + var copyMetallicRoughness = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, true, null); var metallicRoughnessPixels = copyMetallicRoughness.GetPixels32(); - var copyOcclusion = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, null); + var copyOcclusion = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, false, null); var occlusionPixels = copyOcclusion.GetPixels32(); if (metallicRoughnessPixels.Length != occlusionPixels.Length) { @@ -58,12 +59,13 @@ namespace VRMShaders copyMetallicRoughness.SetPixels32(metallicRoughnessPixels); copyMetallicRoughness.Apply(); copyMetallicRoughness.name = metallicRoughnessTexture.name; + DestroyTexture(copyOcclusion); return copyMetallicRoughness; } } else if (metallicRoughnessTexture != null) { - var copyTexture = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, null); + var copyTexture = TextureConverter.CopyTexture(metallicRoughnessTexture, ColorSpace.Linear, true, null); copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ImportPixel(x, metallicFactor, roughnessFactor, default)).ToArray()); copyTexture.Apply(); copyTexture.name = metallicRoughnessTexture.name; @@ -71,7 +73,7 @@ namespace VRMShaders } else if (occlusionTexture != null) { - var copyTexture = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, null); + var copyTexture = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, true, null); copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ImportPixel(default, metallicFactor, roughnessFactor, x)).ToArray()); copyTexture.Apply(); copyTexture.name = occlusionTexture.name; @@ -98,22 +100,26 @@ namespace VRMShaders public static Texture2D Export(Texture metallicSmoothTexture, float smoothness, Texture occlusionTexture) { + // TODO: Replace with Shader implementation if (metallicSmoothTexture != null && occlusionTexture != null) { if (metallicSmoothTexture == occlusionTexture) { - var copyTexture = TextureConverter.CopyTexture(metallicSmoothTexture, ColorSpace.Linear, null); - copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ExportPixel(x, smoothness, x)).ToArray()); - copyTexture.Apply(); - copyTexture.name = metallicSmoothTexture.name; - return copyTexture; + var dst = TextureConverter.CreateEmptyTextureWithSettings(metallicSmoothTexture, ColorSpace.Linear, false); + var linearTexture = TextureConverter.CopyTexture(metallicSmoothTexture, ColorSpace.Linear, true, null); + dst.SetPixels32(linearTexture.GetPixels32().Select(x => ExportPixel(x, smoothness, x)).ToArray()); + dst.Apply(); + dst.name = metallicSmoothTexture.name; + DestroyTexture(linearTexture); + return dst; } else { - var copyMetallicSmooth = TextureConverter.CopyTexture(metallicSmoothTexture, ColorSpace.Linear, null); - var metallicSmoothPixels = copyMetallicSmooth.GetPixels32(); - var copyOcclusion = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, null); - var occlusionPixels = copyOcclusion.GetPixels32(); + var dst = TextureConverter.CreateEmptyTextureWithSettings(metallicSmoothTexture, ColorSpace.Linear, false); + var linearMetallicSmooth = TextureConverter.CopyTexture(metallicSmoothTexture, ColorSpace.Linear, true, null); + var metallicSmoothPixels = linearMetallicSmooth.GetPixels32(); + var linearOcclusion = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, false, null); + var occlusionPixels = linearOcclusion.GetPixels32(); if (metallicSmoothPixels.Length != occlusionPixels.Length) { throw new NotImplementedException(); @@ -122,27 +128,33 @@ namespace VRMShaders { metallicSmoothPixels[i] = ExportPixel(metallicSmoothPixels[i], smoothness, occlusionPixels[i]); } - copyMetallicSmooth.SetPixels32(metallicSmoothPixels); - copyMetallicSmooth.Apply(); - copyMetallicSmooth.name = metallicSmoothTexture.name; - return copyMetallicSmooth; + dst.SetPixels32(metallicSmoothPixels); + dst.Apply(); + dst.name = metallicSmoothTexture.name; + DestroyTexture(linearMetallicSmooth); + DestroyTexture(linearOcclusion); + return dst; } } else if (metallicSmoothTexture) { - var copyTexture = TextureConverter.CopyTexture(metallicSmoothTexture, ColorSpace.Linear, null); - copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ExportPixel(x, smoothness, default)).ToArray()); - copyTexture.Apply(); - copyTexture.name = metallicSmoothTexture.name; - return copyTexture; + var dst = TextureConverter.CreateEmptyTextureWithSettings(metallicSmoothTexture, ColorSpace.Linear, false); + var linearMetallicSmooth = TextureConverter.CopyTexture(metallicSmoothTexture, ColorSpace.Linear, true, null); + dst.SetPixels32(linearMetallicSmooth.GetPixels32().Select(x => ExportPixel(x, smoothness, default)).ToArray()); + dst.Apply(); + dst.name = metallicSmoothTexture.name; + DestroyTexture(linearMetallicSmooth); + return dst; } else if (occlusionTexture) { - var copyTexture = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, null); - copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => ExportPixel(default, smoothness, x)).ToArray()); - copyTexture.Apply(); - copyTexture.name = occlusionTexture.name; - return copyTexture; + var dst = TextureConverter.CreateEmptyTextureWithSettings(metallicSmoothTexture, ColorSpace.Linear, false); + var linearOcclusion = TextureConverter.CopyTexture(occlusionTexture, ColorSpace.Linear, false, null); + dst.SetPixels32(linearOcclusion.GetPixels32().Select(x => ExportPixel(default, smoothness, x)).ToArray()); + dst.Apply(); + dst.name = occlusionTexture.name; + DestroyTexture(linearOcclusion); + return dst; } else { @@ -162,5 +174,17 @@ namespace VRMShaders return dst; } + + private static void DestroyTexture(Texture obj) + { + if (Application.isPlaying) + { + UnityEngine.Object.Destroy(obj); + } + else + { + UnityEngine.Object.DestroyImmediate(obj); + } + } } } diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/RuntimeTextureSerializer.cs b/Assets/VRMShaders/GLTF/IO/Runtime/RuntimeTextureSerializer.cs index d90f830b0..526e95368 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/RuntimeTextureSerializer.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/RuntimeTextureSerializer.cs @@ -41,7 +41,8 @@ namespace UniGLTF private static (byte[] bytes, string mime) CopyTextureAndGetBytesWithMime(Texture2D texture, ColorSpace colorSpace) { - var copiedTex = TextureConverter.CopyTexture(texture, colorSpace, null); + var needsAlpha = texture.format != TextureFormat.RGB24; + var copiedTex = TextureConverter.CopyTexture(texture, colorSpace, needsAlpha, null); var bytes = copiedTex.EncodeToPNG(); if (Application.isPlaying) { diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs b/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs index 1b46ecc0c..d9d19b82f 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs @@ -8,23 +8,24 @@ namespace VRMShaders { public static class TextureConverter { - public delegate Color32 ColorConversion(Color32 color); - - public static Texture2D Convert(Texture texture, ColorSpace dstColorSpace, ColorConversion colorConversion, Material convertMaterial) + public static Texture2D CreateEmptyTextureWithSettings(Texture src, ColorSpace dstColorSpace, bool dstNeedsAlpha) { - var copyTexture = CopyTexture(texture, dstColorSpace, convertMaterial); - if (colorConversion != null) - { - copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => colorConversion(x)).ToArray()); - copyTexture.Apply(); - } - copyTexture.name = texture.name; - return copyTexture; + var texFormat = dstNeedsAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24; + var dst = new Texture2D(src.width, src.height, texFormat, src.HasMipMap(), dstColorSpace == ColorSpace.Linear); + dst.name = src.name; + dst.anisoLevel = src.anisoLevel; + dst.filterMode = src.filterMode; + dst.mipMapBias = src.mipMapBias; + dst.wrapMode = src.wrapMode; + dst.wrapModeU = src.wrapModeU; + dst.wrapModeV = src.wrapModeV; + dst.wrapModeW = src.wrapModeW; + + return dst; } - public static Texture2D CopyTexture(Texture src, ColorSpace dstColorSpace, Material material) + public static Texture2D CopyTexture(Texture src, ColorSpace dstColorSpace, bool dstNeedsAlpha, Material material) { - Texture2D dst = null; RenderTextureReadWrite readWrite; switch (dstColorSpace) { @@ -49,16 +50,8 @@ namespace VRMShaders Graphics.Blit(src, renderTexture); } - dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, src.HasMipMap(), readWrite == RenderTextureReadWrite.Linear); + var dst = CreateEmptyTextureWithSettings(src, dstColorSpace, dstNeedsAlpha); dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0); - dst.name = src.name; - dst.anisoLevel = src.anisoLevel; - dst.filterMode = src.filterMode; - dst.mipMapBias = src.mipMapBias; - dst.wrapMode = src.wrapMode; - dst.wrapModeU = src.wrapModeU; - dst.wrapModeV = src.wrapModeV; - dst.wrapModeW = src.wrapModeW; dst.Apply(); RenderTexture.active = null; diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs b/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs index dd07e350d..4c46755d8 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs @@ -79,7 +79,7 @@ namespace VRMShaders } else { - texture2D = TextureConverter.CopyTexture(src, ColorSpace.sRGB, null); + texture2D = TextureConverter.CopyTexture(src, ColorSpace.sRGB, true, null); } m_exported.Add((texture2D, ColorSpace.sRGB)); m_exportMap.Add(new ExportKey(src, ExportTypes.Srgb), index); @@ -110,7 +110,7 @@ namespace VRMShaders } else { - texture2d = TextureConverter.CopyTexture(src, ColorSpace.Linear, null); + texture2d = TextureConverter.CopyTexture(src, ColorSpace.Linear, false, null); } m_exported.Add((texture2d, ColorSpace.Linear)); m_exportMap.Add(exportKey, index); diff --git a/Assets/VRMShaders/GLTF/IO/Tests/CopyTextureTests.cs b/Assets/VRMShaders/GLTF/IO/Tests/CopyTextureTests.cs index 0a9321402..7d7fa051d 100644 --- a/Assets/VRMShaders/GLTF/IO/Tests/CopyTextureTests.cs +++ b/Assets/VRMShaders/GLTF/IO/Tests/CopyTextureTests.cs @@ -36,7 +36,7 @@ namespace VRMShaders { var nonReadableTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable.png"); Assert.False(nonReadableTex.isReadable); - var copiedTex = TextureConverter.CopyTexture(nonReadableTex, ColorSpace.sRGB, null); + var copiedTex = TextureConverter.CopyTexture(nonReadableTex, ColorSpace.sRGB, true, null); var pixels = copiedTex.GetPixels32(miplevel: 0); Assert.AreEqual(pixels.Length, PngTextureValues.Length); for (var idx = 0; idx < pixels.Length; ++idx) @@ -50,7 +50,7 @@ namespace VRMShaders { var compressedTex = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable_compressed.dds"); Assert.False(compressedTex.isReadable); - var copiedTex = TextureConverter.CopyTexture(compressedTex, ColorSpace.sRGB, null); + var copiedTex = TextureConverter.CopyTexture(compressedTex, ColorSpace.sRGB, true, null); var pixels = copiedTex.GetPixels32(miplevel: 0); Assert.AreEqual(pixels.Length, DdsTextureValues.Length); for (var idx = 0; idx < pixels.Length; ++idx) @@ -58,5 +58,25 @@ namespace VRMShaders Assert.AreEqual(DdsTextureValues[idx], pixels[idx]); } } + + [Test] + public void CopyAttributes() + { + var src = AssetDatabase.LoadAssetAtPath($"{AssetPath}/4x4_non_readable.png"); + var dst = TextureConverter.CopyTexture(src, ColorSpace.sRGB, false, null); + Assert.AreEqual(src.name, dst.name); + Assert.AreEqual(src.anisoLevel, dst.anisoLevel); + Assert.AreEqual(src.filterMode, dst.filterMode); + Assert.AreEqual(src.mipMapBias, dst.mipMapBias); + Assert.AreEqual(src.wrapMode, dst.wrapMode); + Assert.AreEqual(src.wrapModeU, dst.wrapModeU); + Assert.AreEqual(src.wrapModeV, dst.wrapModeV); + Assert.AreEqual(src.wrapModeW, dst.wrapModeW); + Assert.AreEqual(src.mipmapCount, dst.mipmapCount); + Assert.AreEqual(src.width, dst.width); + Assert.AreEqual(src.height, dst.height); + Assert.AreEqual(src.format, dst.format); + Assert.AreEqual(src.imageContentsHash, dst.imageContentsHash); + } } }