diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureExporter.cs
index cd7df68be..c80a0fd67 100644
--- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureExporter.cs
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureExporter.cs
@@ -21,9 +21,9 @@ namespace UniGLTF
///
///
/// gltf texture index
- public static int PushGltfTexture(this glTF gltf, int bufferIndex, Texture2D texture, Func getTextureBytes)
+ public static int PushGltfTexture(this glTF gltf, int bufferIndex, Texture2D texture, ColorSpace textureColorSpace, gltfExporter.GetBytesWithMimeFromTexture2D getTextureBytes)
{
- var bytesWithMime = getTextureBytes(texture);
+ var bytesWithMime = getTextureBytes(texture, textureColorSpace);
// add view
var view = gltf.buffers[bufferIndex].Append(bytesWithMime.bytes, glBufferTarget.NONE);
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs
index 4174e7ae2..b109dd140 100644
--- a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs
@@ -214,12 +214,21 @@ namespace UniGLTF
return false;
}
- public virtual void ExportExtensions(Func getTextureBytes)
+ public virtual void ExportExtensions(GetBytesWithMimeFromTexture2D getTextureBytes)
{
// do nothing
}
- public virtual void Export(MeshExportSettings meshExportSettings, Func useAsset, Func getTextureBytes)
+ ///
+ /// Texture2D から実際のバイト列を取得するデリゲート。
+ ///
+ /// textureColorSpace は Texture2D をコピーする際に用いる。
+ /// Texture2D 単体では、色空間を知ることができないため。
+ /// 一般には、その Texture2D がアサインされる glTF のプロパティの仕様が定める色空間と一致する。
+ ///
+ public delegate (byte[] bytes, string mime) GetBytesWithMimeFromTexture2D(Texture2D texture, ColorSpace textureColorSpace);
+
+ public virtual void Export(MeshExportSettings meshExportSettings, Func useAsset, GetBytesWithMimeFromTexture2D getTextureBytes)
{
var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
var bufferIndex = glTF.AddBuffer(bytesBuffer);
@@ -362,8 +371,8 @@ namespace UniGLTF
// Extension で Texture が増える場合があるので最後に呼ぶ
for (int i = 0; i < TextureManager.Exported.Count; ++i)
{
- var unityTexture = TextureManager.Exported[i];
- glTF.PushGltfTexture(bufferIndex, unityTexture, getTextureBytes);
+ var (unityTexture, colorSpace) = TextureManager.Exported[i];
+ glTF.PushGltfTexture(bufferIndex, unityTexture, colorSpace, getTextureBytes);
}
}
#endregion
diff --git a/Assets/UniGLTF/Tests/UniGLTF/TextureTests.cs b/Assets/UniGLTF/Tests/UniGLTF/TextureTests.cs
index 2ccb579e8..43232395c 100644
--- a/Assets/UniGLTF/Tests/UniGLTF/TextureTests.cs
+++ b/Assets/UniGLTF/Tests/UniGLTF/TextureTests.cs
@@ -26,7 +26,7 @@ namespace UniGLTF
var materialExporter = new MaterialExporter();
materialExporter.ExportMaterial(material, textureManager);
- var convTex0 = textureManager.Exported[0];
+ var (convTex0, colorSpace) = textureManager.Exported[0];
var sampler = TextureSamplerUtil.Export(convTex0);
Assert.AreEqual(glWrap.CLAMP_TO_EDGE, sampler.wrapS);
diff --git a/Assets/VRM/Runtime/IO/VRMExporter.cs b/Assets/VRM/Runtime/IO/VRMExporter.cs
index ed567d485..87b02bcce 100644
--- a/Assets/VRM/Runtime/IO/VRMExporter.cs
+++ b/Assets/VRM/Runtime/IO/VRMExporter.cs
@@ -3,6 +3,7 @@ using System.Linq;
using UniGLTF;
using UniJSON;
using UnityEngine;
+using ColorSpace = UniGLTF.ColorSpace;
namespace VRM
@@ -14,7 +15,7 @@ namespace VRM
return new VRMMaterialExporter();
}
- public static glTF Export(MeshExportSettings configuration, GameObject go, Func useAsset, Func getTextureBytes)
+ public static glTF Export(MeshExportSettings configuration, GameObject go, Func useAsset, GetBytesWithMimeFromTexture2D getTextureBytes)
{
var gltf = new glTF();
using (var exporter = new VRMExporter(gltf))
@@ -32,7 +33,7 @@ namespace VRM
gltf.extensionsUsed.Add(glTF_VRM_extensions.ExtensionName);
}
- public override void ExportExtensions(Func getTextureBytes)
+ public override void ExportExtensions(GetBytesWithMimeFromTexture2D getTextureBytes)
{
// avatar
var animator = Copy.GetComponent();
@@ -110,7 +111,7 @@ namespace VRM
VRM.meta.title = meta.Title;
if (meta.Thumbnail != null)
{
- VRM.meta.texture = glTF.PushGltfTexture(glTF.buffers.Count - 1, meta.Thumbnail, getTextureBytes);
+ VRM.meta.texture = glTF.PushGltfTexture(glTF.buffers.Count - 1, meta.Thumbnail, ColorSpace.sRGB, getTextureBytes);
}
VRM.meta.licenseType = meta.LicenseType;
diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs
index 042e72e5a..da0c5b722 100644
--- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs
+++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs
@@ -127,7 +127,7 @@ namespace UniVRM10
return new float[] { -v.x, v.y, v.z };
}
- public void Export(GameObject root, Model model, ModelExporter converter, ExportArgs option, Func getTextureBytes, VRM10MetaObject metaObject = null)
+ public void Export(GameObject root, Model model, ModelExporter converter, ExportArgs option, gltfExporter.GetBytesWithMimeFromTexture2D getTextureBytes, VRM10MetaObject metaObject = null)
{
ExportAsset(model);
@@ -180,8 +180,8 @@ namespace UniVRM10
// Extension で Texture が増える場合があるので最後に呼ぶ
for (int i = 0; i < m_textureExporter.Exported.Count; ++i)
{
- var unityTexture = m_textureExporter.Exported[i];
- Storage.Gltf.PushGltfTexture(0, unityTexture, getTextureBytes);
+ var (unityTexture, texColorSpace) = m_textureExporter.Exported[i];
+ Storage.Gltf.PushGltfTexture(0, unityTexture, texColorSpace, getTextureBytes);
}
if (thumbnailTextureIndex.HasValue)
@@ -775,7 +775,7 @@ namespace UniVRM10
///
///
///
- public static byte[] Export(GameObject go, Func getTextureBytes = null)
+ public static byte[] Export(GameObject go, gltfExporter.GetBytesWithMimeFromTexture2D getTextureBytes = null)
{
if (getTextureBytes == null)
{
diff --git a/Assets/VRMShaders/GLTF/IO/Editor/AssetTextureUtil.cs b/Assets/VRMShaders/GLTF/IO/Editor/AssetTextureUtil.cs
index c69ae48ed..b736e0d1c 100644
--- a/Assets/VRMShaders/GLTF/IO/Editor/AssetTextureUtil.cs
+++ b/Assets/VRMShaders/GLTF/IO/Editor/AssetTextureUtil.cs
@@ -2,6 +2,7 @@ using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
+using ColorSpace = UniGLTF.ColorSpace;
namespace VRMShaders
{
@@ -107,14 +108,14 @@ namespace VRMShaders
return false;
}
- public static (byte[], string) GetTextureBytesWithMime(Texture2D texture)
+ public static (byte[], string) GetTextureBytesWithMime(Texture2D texture, ColorSpace colorSpace)
{
if (TryGetBytesWithMime(texture, out byte[] bytes, out string mime))
{
return (bytes, mime);
}
- return TextureExporter.GetTextureBytesWithMime(texture);
+ return TextureExporter.GetTextureBytesWithMime(texture, colorSpace);
}
}
}
diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs b/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs
index 54ac445f9..67d0eb6f0 100644
--- a/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs
+++ b/Assets/VRMShaders/GLTF/IO/Runtime/TextureConverter.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using UnityEngine;
+using ColorSpace = UniGLTF.ColorSpace;
namespace VRMShaders
@@ -22,10 +23,27 @@ namespace VRMShaders
}
public static Texture2D CopyTexture(Texture src, TextureImportTypes textureType, Material material)
+ {
+ return CopyTexture(src, textureType.GetColorSpace(), material);
+ }
+
+ public static Texture2D CopyTexture(Texture src, ColorSpace colorSpace, Material material)
{
Texture2D dst = null;
- RenderTextureReadWrite colorSpace = textureType.GetColorSpace();
- var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, colorSpace);
+ RenderTextureReadWrite readWrite;
+ switch (colorSpace)
+ {
+ case ColorSpace.sRGB:
+ readWrite = RenderTextureReadWrite.sRGB;
+ break;
+ case ColorSpace.Linear:
+ readWrite = RenderTextureReadWrite.Linear;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(colorSpace), colorSpace, null);
+ }
+
+ var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, readWrite);
if (material != null)
{
@@ -36,7 +54,7 @@ namespace VRMShaders
Graphics.Blit(src, renderTexture);
}
- dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, colorSpace == RenderTextureReadWrite.Linear);
+ dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, readWrite == RenderTextureReadWrite.Linear);
dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0);
dst.name = src.name;
dst.anisoLevel = src.anisoLevel;
diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs b/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs
index 0a7b49f6e..8434e456e 100644
--- a/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs
+++ b/Assets/VRMShaders/GLTF/IO/Runtime/TextureExporter.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
+using ColorSpace = UniGLTF.ColorSpace;
namespace VRMShaders
@@ -55,7 +56,7 @@ namespace VRMShaders
///
///
///
- public readonly List Exported = new List();
+ public readonly List<(Texture2D, ColorSpace)> Exported = new List<(Texture2D, ColorSpace)>();
///
/// Texture の export index を得る
@@ -101,7 +102,7 @@ namespace VRMShaders
{
texture2D = TextureConverter.CopyTexture(src, TextureImportTypes.sRGB, null);
}
- Exported.Add(texture2D);
+ Exported.Add((texture2D, ColorSpace.sRGB));
m_exportMap.Add(new ExportKey(src, ConvertTypes.None), index);
return index;
@@ -114,7 +115,33 @@ namespace VRMShaders
///
public int ExportLinear(Texture src)
{
- throw new NotImplementedException();
+ if (src == null)
+ {
+ return -1;
+ }
+
+ var exportKey = new ExportKey(src, ConvertTypes.None);
+
+ // search cache
+ if (m_exportMap.TryGetValue(exportKey, out var index))
+ {
+ return index;
+ }
+
+ index = Exported.Count;
+ var texture2d = src as Texture2D;
+ if (m_useAsset(texture2d))
+ {
+ // do nothing
+ }
+ else
+ {
+ texture2d = TextureConverter.CopyTexture(src, TextureImportTypes.Linear, null);
+ }
+ Exported.Add((texture2d, ColorSpace.Linear));
+ m_exportMap.Add(exportKey, index);
+
+ return index;
}
///
@@ -147,7 +174,7 @@ namespace VRMShaders
index = Exported.Count;
var texture2D = OcclusionMetallicRoughnessConverter.Export(metallicSmoothTexture, smoothness, occlusionTexture);
- Exported.Add(texture2D);
+ Exported.Add((texture2D, ColorSpace.Linear));
if (metallicSmoothTexture != null)
{
m_exportMap.Add(new ExportKey(metallicSmoothTexture, ConvertTypes.OcclusionMetallicRoughness), index);
@@ -191,7 +218,7 @@ namespace VRMShaders
texture2D = NormalConverter.Export(src);
}
- Exported.Add(texture2D);
+ Exported.Add((texture2D, ColorSpace.Linear));
m_exportMap.Add(new ExportKey(src, ConvertTypes.Normal), index);
return index;
@@ -200,9 +227,7 @@ namespace VRMShaders
///
/// 画像のバイト列を得る
///
- ///
- ///
- public static (byte[] bytes, string mime) GetTextureBytesWithMime(Texture2D texture)
+ public static (byte[] bytes, string mime) GetTextureBytesWithMime(Texture2D texture, ColorSpace colorSpace)
{
try
{
@@ -211,22 +236,38 @@ namespace VRMShaders
{
return (png, "image/png");
}
+ else
+ {
+ // 単純に EncodeToPNG できないため、コピーしてから EncodeToPNG する。
+ return CopyTextureAndGetBytesWithMime(texture, colorSpace);
+ }
}
catch (ArgumentException ex)
{
// fail to EncodeToPng
// System.ArgumentException: not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.
+ // example, ".DDS" Texture object in Editor.
Debug.LogWarning(ex);
-
- // Read/Write が許可されていない Texture2D オブジェクトはこの関数に渡されるべきではない。
- // なぜなら Texture2D の色空間は、対応する glTF プロパティ指定の色空間と一致していなければならないが
- // Read/Write が許可されていない場合、その条件を守って変換することができないからである。
- // したがって、この関数に渡す前に glTF プロパティ指定の色空間を加味して Copy Texture して、それを渡すべきである。
- throw;
+ // 単純に EncodeToPNG できないため、コピーしてから EncodeToPNG する。
+ return CopyTextureAndGetBytesWithMime(texture, colorSpace);
+ }
+ }
+
+ private static (byte[] bytes, string mime) CopyTextureAndGetBytesWithMime(Texture2D texture, ColorSpace colorSpace)
+ {
+ var copiedTex = TextureConverter.CopyTexture(texture, colorSpace, null);
+ var bytes = copiedTex.EncodeToPNG();
+ if (Application.isPlaying)
+ {
+ UnityEngine.Object.Destroy(copiedTex);
+ }
+ else
+ {
+ UnityEngine.Object.DestroyImmediate(copiedTex);
}
- throw new ArgumentException("Invalid Texture2D");
+ return (bytes, "image/png");
}
}
}
diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/TextureImportTypes.cs b/Assets/VRMShaders/GLTF/IO/Runtime/TextureImportTypes.cs
index 4b928153b..c47f14a51 100644
--- a/Assets/VRMShaders/GLTF/IO/Runtime/TextureImportTypes.cs
+++ b/Assets/VRMShaders/GLTF/IO/Runtime/TextureImportTypes.cs
@@ -1,5 +1,6 @@
using System;
using UnityEngine;
+using ColorSpace = UniGLTF.ColorSpace;
namespace VRMShaders
{
@@ -31,16 +32,16 @@ namespace VRMShaders
public static class TextureImportTypesExtensions
{
- public static RenderTextureReadWrite GetColorSpace(this TextureImportTypes textureType)
+ public static ColorSpace GetColorSpace(this TextureImportTypes textureType)
{
switch (textureType)
{
case TextureImportTypes.sRGB:
- return RenderTextureReadWrite.sRGB;
+ return ColorSpace.sRGB;
case TextureImportTypes.Linear:
case TextureImportTypes.StandardMap:
case TextureImportTypes.NormalMap:
- return RenderTextureReadWrite.Linear;
+ return ColorSpace.Linear;
default:
throw new NotImplementedException();
}