Merge pull request #961 from Santarh/refactorTextureSerializer

Refactoring Serializing Textures
This commit is contained in:
ousttrue 2021-05-20 18:35:09 +09:00 committed by GitHub
commit c1930ca040
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 199 additions and 171 deletions

View File

@ -36,7 +36,7 @@ namespace MeshUtility
return;
}
var (tex, mime) = TextureExporter.GetTextureBytesWithMime(texture, sRGB ? ColorSpace.sRGB : ColorSpace.Linear);
var (tex, mime) = new EditorTextureSerializer().ExportBytesWithMime(texture, sRGB ? ColorSpace.sRGB : ColorSpace.Linear);
File.WriteAllBytes(path, tex);
Debug.Log($"save: {path}");

View File

@ -125,7 +125,7 @@ namespace UniGLTF
UseSparseAccessorForMorphTarget = m_settings.Sparse,
DivideVertexBuffer = m_settings.DivideVertexBuffer,
};
exporter.Export(settings, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(settings, new EditorTextureSerializer());
}
if (isGlb)

View File

@ -8,22 +8,22 @@ namespace UniGLTF
{
/// <summary>
/// gltf に texture を足す
///
///
/// * textures
/// * samplers
/// * images
/// * bufferViews
///
///
/// を更新し、textures の index を返す
///
///
/// </summary>
/// <param name="gltf"></param>
/// <param name="bufferIndex"></param>
/// <param name="texture"></param>
/// <returns>gltf texture index</returns>
public static int PushGltfTexture(this glTF gltf, int bufferIndex, Texture2D texture, ColorSpace textureColorSpace, gltfExporter.GetBytesWithMimeFromTexture2D getTextureBytes)
public static int PushGltfTexture(this glTF gltf, int bufferIndex, Texture2D texture, ColorSpace textureColorSpace, ITextureSerializer textureSerializer)
{
var bytesWithMime = getTextureBytes(texture, textureColorSpace);
var bytesWithMime = textureSerializer.ExportBytesWithMime(texture, textureColorSpace);
// add view
var view = gltf.buffers[bufferIndex].Append(bytesWithMime.bytes, glBufferTarget.NONE);

View File

@ -21,7 +21,7 @@ namespace UniGLTF
/// <summary>
/// Mesh毎に、元のBlendShapeIndex => ExportされたBlendShapeIndex の対応を記録する
///
///
/// BlendShape が空の場合にスキップするので
/// </summary>
/// <value></value>
@ -148,7 +148,7 @@ namespace UniGLTF
if (x.gameObject.activeInHierarchy)
{
var meshRenderer = x.GetComponent<MeshRenderer>();
if (meshRenderer != null)
{
var meshFilter = x.GetComponent<MeshFilter>();
@ -214,21 +214,12 @@ namespace UniGLTF
return false;
}
public virtual void ExportExtensions(GetBytesWithMimeFromTexture2D getTextureBytes)
public virtual void ExportExtensions(ITextureSerializer textureSerializer)
{
// do nothing
}
/// <summary>
/// Texture2D から実際のバイト列を取得するデリゲート。
///
/// textureColorSpace は Texture2D をコピーする際に用いる。
/// Texture2D 単体では、色空間を知ることができないため。
/// 一般には、その Texture2D がアサインされる glTF のプロパティの仕様が定める色空間と一致する。
/// </summary>
public delegate (byte[] bytes, string mime) GetBytesWithMimeFromTexture2D(Texture2D texture, ColorSpace textureColorSpace);
public virtual void Export(MeshExportSettings meshExportSettings, Func<Texture, bool> useAsset, GetBytesWithMimeFromTexture2D getTextureBytes)
public virtual void Export(MeshExportSettings meshExportSettings, ITextureSerializer textureSerializer)
{
var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
var bufferIndex = glTF.AddBuffer(bytesBuffer);
@ -247,7 +238,7 @@ namespace UniGLTF
#region Materials and Textures
Materials = uniqueUnityMeshes.SelectMany(x => x.Renderer.sharedMaterials).Where(x => x != null).Distinct().ToList();
TextureManager = new TextureExporter(useAsset);
TextureManager = new TextureExporter(textureSerializer);
var materialExporter = CreateMaterialExporter();
glTF.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureManager)).ToList();
@ -366,13 +357,13 @@ namespace UniGLTF
#endregion
#endif
ExportExtensions(getTextureBytes);
ExportExtensions(textureSerializer);
// Extension で Texture が増える場合があるので最後に呼ぶ
for (int i = 0; i < TextureManager.Exported.Count; ++i)
{
var (unityTexture, colorSpace) = TextureManager.Exported[i];
glTF.PushGltfTexture(bufferIndex, unityTexture, colorSpace, getTextureBytes);
glTF.PushGltfTexture(bufferIndex, unityTexture, colorSpace, textureSerializer);
}
}
#endregion

View File

@ -61,7 +61,7 @@ namespace UniGLTF
using (var exporter = new gltfExporter(gltf))
{
exporter.Prepare(root);
exporter.Export(MeshExportSettings.Default, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(MeshExportSettings.Default, new EditorTextureSerializer());
return gltf.ToGlbBytes();
}
}
@ -102,7 +102,7 @@ namespace UniGLTF
if (Skip.Contains(gltf.Directory.Parent.Name))
{
// Export issue:
// Export issue:
// skip
return;
}

View File

@ -18,7 +18,7 @@ namespace UniGLTF
filterMode = FilterMode.Bilinear,
};
var textureManager = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset );
var textureManager = new TextureExporter(new EditorTextureSerializer());
var srcMaterial = new Material(Shader.Find("Standard"));
var offset = new Vector2(0.3f, 0.2f);
@ -242,7 +242,7 @@ namespace UniGLTF
material.SetColor("_EmissionColor", new Color(0, 1, 2, 1));
material.EnableKeyword("_EMISSION");
var materialExporter = new MaterialExporter();
var textureExportManager = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset );
var textureExportManager = new TextureExporter(new EditorTextureSerializer());
var gltfMaterial = materialExporter.ExportMaterial(material, textureExportManager);
Assert.AreEqual(gltfMaterial.emissiveFactor, new float[] { 0, 0.5f, 1 });

View File

@ -93,7 +93,7 @@ namespace UniGLTF
UseSparseAccessorForMorphTarget = false,
DivideVertexBuffer = false,
};
exporter.Export(settings, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(settings, new EditorTextureSerializer());
}
Assert.AreEqual(1, gltf.images.Count);
var exportedImage = gltf.images[0];

View File

@ -18,7 +18,7 @@ namespace UniGLTF
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Trilinear,
};
var textureManager = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset);
var textureManager = new TextureExporter(new EditorTextureSerializer());
var material = new Material(Shader.Find("Standard"));
material.mainTexture = tex0;

View File

@ -106,7 +106,7 @@ namespace UniGLTF
using (var exporter = new gltfExporter(gltf))
{
exporter.Prepare(go);
exporter.Export(MeshExportSettings.Default, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(MeshExportSettings.Default, new EditorTextureSerializer());
// remove empty buffer
gltf.buffers.Clear();
@ -298,7 +298,7 @@ namespace UniGLTF
using (var exporter = new gltfExporter(gltf))
{
exporter.Prepare(CreateSimpleScene());
exporter.Export(MeshExportSettings.Default, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(MeshExportSettings.Default, new EditorTextureSerializer());
}
var expected = gltf.ToJson().ParseAsJson();
@ -534,7 +534,7 @@ namespace UniGLTF
using (var exporter = new gltfExporter(gltf))
{
exporter.Prepare(go);
exporter.Export(UniGLTF.MeshExportSettings.Default, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(UniGLTF.MeshExportSettings.Default, new EditorTextureSerializer());
json = gltf.ToJson();
}
@ -618,7 +618,7 @@ namespace UniGLTF
using (var exporter = new gltfExporter(gltf))
{
exporter.Prepare(go);
exporter.Export(UniGLTF.MeshExportSettings.Default, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(UniGLTF.MeshExportSettings.Default, new EditorTextureSerializer());
json = gltf.ToJson();
}

View File

@ -170,7 +170,7 @@ namespace VRM.Samples
*/
importedJson.RemoveValue(Utf8String.From("/bufferViews/*/byteStride"));
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, context.Root, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, context.Root, new EditorTextureSerializer());
// TODO: Check contents in JSON
/*var exportJson = */

View File

@ -11,7 +11,7 @@ namespace VRM.Samples
{
var material = Resources.Load<Material>(resourceName);
var exporter = new VRMMaterialExporter();
var textureManager = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset );
var textureManager = new TextureExporter(new EditorTextureSerializer());
var exported = exporter.ExportMaterial(material, textureManager);
// parse glTFExtensionExport to glTFExtensionImport

View File

@ -96,7 +96,7 @@ namespace VRM.Samples
return;
}
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, m_model, (Texture _) => false, TextureExporter.GetTextureBytesWithMime);
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, m_model, new RuntimeTextureSerializer());
var bytes = vrm.ToGlbBytes();
File.WriteAllBytes(path, bytes);
Debug.LogFormat("export to {0}", path);

View File

@ -130,7 +130,7 @@ namespace VRM
}
/// <summary>
///
///
/// </summary>
/// <param name="path"></param>
/// <param name="settings"></param>
@ -225,7 +225,7 @@ namespace VRM
using (var exporter = new VRMExporter(gltf))
{
exporter.Prepare(target);
exporter.Export(settings.MeshExportSettings, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
exporter.Export(settings.MeshExportSettings, new EditorTextureSerializer());
}
var bytes = gltf.ToGlbBytes();
Debug.LogFormat("Export elapsed {0}", sw.Elapsed);

View File

@ -15,13 +15,13 @@ namespace VRM
return new VRMMaterialExporter();
}
public static glTF Export(MeshExportSettings configuration, GameObject go, Func<Texture, bool> useAsset, GetBytesWithMimeFromTexture2D getTextureBytes)
public static glTF Export(MeshExportSettings configuration, GameObject go, ITextureSerializer textureSerializer)
{
var gltf = new glTF();
using (var exporter = new VRMExporter(gltf))
{
exporter.Prepare(go);
exporter.Export(configuration, useAsset, getTextureBytes);
exporter.Export(configuration, textureSerializer);
}
return gltf;
}
@ -33,7 +33,7 @@ namespace VRM
gltf.extensionsUsed.Add(glTF_VRM_extensions.ExtensionName);
}
public override void ExportExtensions(GetBytesWithMimeFromTexture2D getTextureBytes)
public override void ExportExtensions(ITextureSerializer textureSerializer)
{
// avatar
var animator = Copy.GetComponent<Animator>();
@ -111,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, ColorSpace.sRGB, getTextureBytes);
VRM.meta.texture = glTF.PushGltfTexture(glTF.buffers.Count - 1, meta.Thumbnail, ColorSpace.sRGB, textureSerializer);
}
VRM.meta.licenseType = meta.LicenseType;

View File

@ -18,7 +18,7 @@ namespace VRM
filterMode = FilterMode.Bilinear,
};
var textureManager = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset);
var textureManager = new TextureExporter(new EditorTextureSerializer());
var srcMaterial = new Material(Shader.Find("VRM/MToon"));
var offset = new Vector2(0.3f, 0.2f);

View File

@ -106,7 +106,7 @@ namespace VRM
try
{
// export
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, go, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, go, new EditorTextureSerializer());
// re import
if (vrm != null)

View File

@ -49,12 +49,12 @@ namespace VRM
/// <summary>
/// positions: [
/// {1, 1, 0}
/// {1, 1, 1}
/// {1, 1, 2}
/// {1, 1, 3}
/// {1, 1, 4}
/// {1, 1, 5}
/// {1, 1, 0}
/// {1, 1, 1}
/// {1, 1, 2}
/// {1, 1, 3}
/// {1, 1, 4}
/// {1, 1, 5}
/// ]
/// submesh
/// 0 1 2
@ -73,7 +73,7 @@ namespace VRM
ExportOnlyBlendShapePosition = true,
ExportTangents = false,
UseSparseAccessorForMorphTarget = true,
}, loaded, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
}, loaded, new EditorTextureSerializer());
var bytes = exported.ToGlbBytes();
var divided = Load(bytes, path);

View File

@ -166,7 +166,7 @@ namespace UniVRM10
protected override void OnLayout()
{
// m_settings, m_meshes.Meshes
// m_settings, m_meshes.Meshes
m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings);
}
@ -297,9 +297,9 @@ namespace UniVRM10
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false);
// export vrm-1.0
var exporter = new UniVRM10.Vrm10Exporter(AssetTextureUtil.IsTextureEditorAsset);
var exporter = new UniVRM10.Vrm10Exporter(new EditorTextureSerializer());
var option = new VrmLib.ExportArgs();
exporter.Export(root, model, converter, option, AssetTextureUtil.GetTextureBytesWithMime, Meta ? Meta : m_tmpMeta);
exporter.Export(root, model, converter, option, Meta ? Meta : m_tmpMeta);
var exportedBytes = exporter.Storage.ToBytes();

View File

@ -15,10 +15,16 @@ namespace UniVRM10
public readonly string VrmExtensionName = "VRMC_vrm";
ITextureSerializer m_textureSerializer;
TextureExporter m_textureExporter;
public Vrm10Exporter(Func<Texture, bool> useAsset)
public Vrm10Exporter(ITextureSerializer textureSerializer)
{
if (textureSerializer == null)
{
throw new ArgumentException(nameof(textureSerializer));
}
Storage.Gltf.extensionsUsed.Add(glTF_KHR_materials_unlit.ExtensionName);
Storage.Gltf.extensionsUsed.Add(glTF_KHR_texture_transform.ExtensionName);
Storage.Gltf.extensionsUsed.Add(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm.ExtensionName);
@ -30,7 +36,8 @@ namespace UniVRM10
});
m_textureExporter = new TextureExporter(useAsset);
m_textureSerializer = textureSerializer;
m_textureExporter = new TextureExporter(m_textureSerializer);
}
public void Dispose()
@ -127,7 +134,7 @@ namespace UniVRM10
return new float[] { -v.x, v.y, v.z };
}
public void Export(GameObject root, Model model, ModelExporter converter, ExportArgs option, gltfExporter.GetBytesWithMimeFromTexture2D getTextureBytes, VRM10MetaObject metaObject = null)
public void Export(GameObject root, Model model, ModelExporter converter, ExportArgs option, VRM10MetaObject metaObject = null)
{
ExportAsset(model);
@ -181,7 +188,7 @@ namespace UniVRM10
for (int i = 0; i < m_textureExporter.Exported.Count; ++i)
{
var (unityTexture, texColorSpace) = m_textureExporter.Exported[i];
Storage.Gltf.PushGltfTexture(0, unityTexture, texColorSpace, getTextureBytes);
Storage.Gltf.PushGltfTexture(0, unityTexture, texColorSpace, m_textureSerializer);
}
if (thumbnailTextureIndex.HasValue)
@ -631,7 +638,7 @@ namespace UniVRM10
vrm.Meta.CopyrightInformation = meta.CopyrightInformation;
vrm.Meta.ContactInformation = meta.ContactInformation;
vrm.Meta.References = meta.References.ToList();
// vrm.Meta.ThirdPartyLicenses =
// vrm.Meta.ThirdPartyLicenses =
vrm.Meta.AvatarPermission = meta.AllowedUser;
vrm.Meta.AllowExcessivelyViolentUsage = meta.ViolentUsage;
vrm.Meta.AllowExcessivelySexualUsage = meta.SexualUsage;
@ -775,14 +782,8 @@ namespace UniVRM10
/// <param name="go"></param>
/// <param name="getTextureBytes"></param>
/// <returns></returns>
public static byte[] Export(GameObject go, gltfExporter.GetBytesWithMimeFromTexture2D getTextureBytes = null)
public static byte[] Export(GameObject go, ITextureSerializer textureSerializer = null)
{
if (getTextureBytes == null)
{
// default for runtime export
getTextureBytes = TextureExporter.GetTextureBytesWithMime;
}
// ヒエラルキーからジオメトリーを収集
var converter = new UniVRM10.ModelExporter();
var model = converter.Export(go);
@ -791,11 +792,11 @@ namespace UniVRM10
VrmLib.ModelExtensionsForCoordinates.ConvertCoordinate(model, VrmLib.Coordinates.Vrm1);
// Model と go から VRM-1.0 にExport
var exporter10 = new Vrm10Exporter(_ => false);
var exporter10 = new Vrm10Exporter(textureSerializer ?? new RuntimeTextureSerializer());
var option = new VrmLib.ExportArgs
{
};
exporter10.Export(go, model, converter, option, getTextureBytes);
exporter10.Export(go, model, converter, option);
return exporter10.Storage.ToBytes();
}
}

View File

@ -48,7 +48,7 @@ namespace UniVRM10.Test
Debug.Log(go);
// export
var vrmBytes = Vrm10Exporter.Export(go, AssetTextureUtil.GetTextureBytesWithMime);
var vrmBytes = Vrm10Exporter.Export(go, new EditorTextureSerializer());
Debug.Log($"export {vrmBytes.Length} bytes");
}

View File

@ -1,53 +1,25 @@
using System.IO;
using System.Reflection;
using UniGLTF;
using UnityEditor;
using UnityEngine;
using ColorSpace = UniGLTF.ColorSpace;
namespace VRMShaders
{
public static class AssetTextureUtil
public sealed class EditorTextureSerializer : ITextureSerializer
{
/// <summary>
/// TextureImporter.maxTextureSize が オリジナルの画像Sizeより小さいか
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public static bool IsMaxTextureSizeSmallerThanOriginalTextureSize(Texture2D src)
{
var path = AssetDatabase.GetAssetPath(src);
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
// private メソッド TextureImporter.GetWidthAndHeight を無理やり呼ぶ
var getSizeMethod = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
if (textureImporter != null && getSizeMethod != null)
{
var args = new object[2] { 0, 0 };
getSizeMethod.Invoke(textureImporter, args);
var originalWidth = (int)args[0];
var originalHeight = (int)args[1];
var originalSize = Mathf.Max(originalWidth, originalHeight);
if (textureImporter.maxTextureSize < originalSize)
{
return true;
}
}
return false;
}
private readonly RuntimeTextureSerializer m_runtimeSerializer = new RuntimeTextureSerializer();
/// <summary>
/// Export するときに オリジナルのテクスチャーアセット(png/jpg)を使用するか否か。
/// 条件は、
///
///
/// * TextureAsset が存在する
/// * TextureImporter の maxSize
///
///
/// </summary>
/// <param name="src"></param>
/// <param name="texture2D"></param>
/// <returns></returns>
public static bool IsTextureEditorAsset(Texture texture)
public bool CanExportAsEditorAssetFile(Texture texture)
{
if (texture is Texture2D texture2D && !string.IsNullOrEmpty(UnityEditor.AssetDatabase.GetAssetPath(texture2D)))
{
@ -70,13 +42,20 @@ namespace VRMShaders
return false;
}
public (byte[] bytes, string mime) ExportBytesWithMime(Texture2D texture, ColorSpace textureColorSpace)
{
if (TryGetBytesWithMime(texture, out byte[] bytes, out string mime))
{
return (bytes, mime);
}
return m_runtimeSerializer.ExportBytesWithMime(texture, textureColorSpace);
}
/// <summary>
/// Assetから画像のバイト列を得る
/// </summary>
/// <param name="bytes"></param>
/// <param name="texture"></param>
/// <returns></returns>
public static bool TryGetBytesWithMime(Texture2D texture, out byte[] bytes, out string mime)
private bool TryGetBytesWithMime(Texture2D texture, out byte[] bytes, out string mime)
{
var path = AssetDatabase.GetAssetOrScenePath(texture);
if (string.IsNullOrEmpty(path))
@ -108,14 +87,30 @@ namespace VRMShaders
return false;
}
public static (byte[], string) GetTextureBytesWithMime(Texture2D texture, ColorSpace colorSpace)
/// <summary>
/// TextureImporter.maxTextureSize が オリジナルの画像Sizeより小さいか
/// </summary>
private bool IsMaxTextureSizeSmallerThanOriginalTextureSize(Texture2D src)
{
if (TryGetBytesWithMime(texture, out byte[] bytes, out string mime))
var path = AssetDatabase.GetAssetPath(src);
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
// private メソッド TextureImporter.GetWidthAndHeight を無理やり呼ぶ
var getSizeMethod = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
if (textureImporter != null && getSizeMethod != null)
{
return (bytes, mime);
var args = new object[2] { 0, 0 };
getSizeMethod.Invoke(textureImporter, args);
var originalWidth = (int)args[0];
var originalHeight = (int)args[1];
var originalSize = Mathf.Max(originalWidth, originalHeight);
if (textureImporter.maxTextureSize < originalSize)
{
return true;
}
}
return TextureExporter.GetTextureBytesWithMime(texture, colorSpace);
return false;
}
}
}

View File

@ -0,0 +1,22 @@
using UnityEngine;
namespace UniGLTF
{
public interface ITextureSerializer
{
/// <summary>
/// Texture をファイルのバイト列そのまま出力してよいかどうか判断するデリゲート。
///
/// Runtime 出力では常に false が望ましい。
/// </summary>
bool CanExportAsEditorAssetFile(Texture texture);
/// <summary>
/// Texture2D から実際のバイト列を取得するデリゲート。
///
/// textureColorSpace はその Texture2D がアサインされる glTF プロパティの仕様が定める色空間を指定する。
/// 具体的には Texture2D をコピーする際に、コピー先の Texture2D の色空間を決定するために使用する。
/// </summary>
(byte[] bytes, string mime) ExportBytesWithMime(Texture2D texture, ColorSpace textureColorSpace);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 949143040e6a4a9d987d405d90107d7c
timeCreated: 1621499560

View File

@ -0,0 +1,58 @@
using System;
using UnityEngine;
using VRMShaders;
namespace UniGLTF
{
public sealed class RuntimeTextureSerializer : ITextureSerializer
{
public bool CanExportAsEditorAssetFile(Texture texture)
{
return false;
}
public (byte[] bytes, string mime) ExportBytesWithMime(Texture2D texture, ColorSpace textureColorSpace)
{
try
{
var png = texture.EncodeToPNG();
if (png != null)
{
return (png, "image/png");
}
else
{
// Failed, because texture is compressed.
// ex. ".DDS" file, or Compression is enabled in Texture Import Settings.
return CopyTextureAndGetBytesWithMime(texture, textureColorSpace);
}
}
catch (ArgumentException ex)
{
// System.ArgumentException: not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.
// Failed, because texture is not readable.
Debug.LogWarning(ex);
// 単純に EncodeToPNG できないため、コピーしてから EncodeToPNG する。
return CopyTextureAndGetBytesWithMime(texture, textureColorSpace);
}
}
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);
}
return (bytes, "image/png");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 57623966155c423ba30bf76d64a66760
timeCreated: 1621500488

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using UniGLTF;
using UnityEngine;
using ColorSpace = UniGLTF.ColorSpace;
@ -12,11 +13,11 @@ namespace VRMShaders
/// </summary>
public class TextureExporter : IDisposable
{
Func<Texture, bool> m_useAsset;
private ITextureSerializer m_textureSerializer;
public TextureExporter(Func<Texture, bool> useAsset)
public TextureExporter(ITextureSerializer textureSerializer)
{
m_useAsset = useAsset;
m_textureSerializer = textureSerializer;
}
public void Dispose()
@ -94,9 +95,9 @@ namespace VRMShaders
// get Texture2D
index = Exported.Count;
var texture2D = src as Texture2D;
if (m_useAsset(texture2D))
if (m_textureSerializer.CanExportAsEditorAssetFile(texture2D))
{
// do nothing
// do nothing
}
else
{
@ -119,7 +120,7 @@ namespace VRMShaders
{
return -1;
}
var exportKey = new ExportKey(src, ConvertTypes.None);
// search cache
@ -130,7 +131,7 @@ namespace VRMShaders
index = Exported.Count;
var texture2d = src as Texture2D;
if (m_useAsset(texture2d))
if (m_textureSerializer.CanExportAsEditorAssetFile(texture2d))
{
// do nothing
}
@ -208,7 +209,7 @@ namespace VRMShaders
// get Texture2D
index = Exported.Count;
var texture2D = src as Texture2D;
if (m_useAsset(texture2D))
if (m_textureSerializer.CanExportAsEditorAssetFile(texture2D))
{
// EditorAsset を使うので変換不要
}
@ -223,52 +224,5 @@ namespace VRMShaders
return index;
}
/// <summary>
/// 画像のバイト列を得る
/// </summary>
public static (byte[] bytes, string mime) GetTextureBytesWithMime(Texture2D texture, ColorSpace colorSpace)
{
try
{
var png = texture.EncodeToPNG();
if (png != null)
{
return (png, "image/png");
}
else
{
// Failed, because texture is compressed.
// ex. ".DDS" file, or Compression is enabled in Texture Import Settings.
return CopyTextureAndGetBytesWithMime(texture, colorSpace);
}
}
catch (ArgumentException ex)
{
// System.ArgumentException: not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.
// Failed, because texture is not readable.
Debug.LogWarning(ex);
// 単純に 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);
}
return (bytes, "image/png");
}
}
}

View File

@ -93,20 +93,21 @@ namespace VRMShaders
[Test]
public void ExportMetallicSmoothnessOcclusion_Test()
{
var textureSerializer = new EditorTextureSerializer();
var metallic = new Texture2D(4, 4, TextureFormat.ARGB32, false, true);
var occlusion = new Texture2D(4, 4, TextureFormat.ARGB32, false, true);
{
var exporter = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset );
var exporter = new TextureExporter(new EditorTextureSerializer());
Assert.AreEqual(-1, exporter.ExportMetallicSmoothnessOcclusion(null, 0, null));
}
{
var exporter = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset );
var exporter = new TextureExporter(new EditorTextureSerializer());
Assert.AreEqual(0, exporter.ExportMetallicSmoothnessOcclusion(null, 0, occlusion));
Assert.AreEqual(1, exporter.ExportMetallicSmoothnessOcclusion(metallic, 0, null));
}
{
var exporter = new TextureExporter(AssetTextureUtil.IsTextureEditorAsset );
var exporter = new TextureExporter(new EditorTextureSerializer());
Assert.AreEqual(0, exporter.ExportMetallicSmoothnessOcclusion(metallic, 0, occlusion));
Assert.AreEqual(0, exporter.ExportMetallicSmoothnessOcclusion(null, 0, occlusion));
Assert.AreEqual(0, exporter.ExportMetallicSmoothnessOcclusion(metallic, 0, null));

View File

@ -14,7 +14,7 @@ namespace VRMShaders
{
var nonReadableTex = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/4x4_non_readable.png");
Assert.False(nonReadableTex.isReadable);
var (bytes, mime) = AssetTextureUtil.GetTextureBytesWithMime(nonReadableTex, ColorSpace.sRGB);
var (bytes, mime) = new EditorTextureSerializer().ExportBytesWithMime(nonReadableTex, ColorSpace.sRGB);
Assert.NotNull(bytes);
}
@ -23,7 +23,7 @@ namespace VRMShaders
{
var readonlyTexture = AssetDatabase.LoadAssetAtPath<Texture2D>($"{AssetPath}/4x4_non_readable_compressed.dds");
Assert.False(readonlyTexture.isReadable);
var (bytes, mime) = AssetTextureUtil.GetTextureBytesWithMime(readonlyTexture, ColorSpace.sRGB);
var (bytes, mime) = new EditorTextureSerializer().ExportBytesWithMime(readonlyTexture, ColorSpace.sRGB);
Assert.NotNull(bytes);
}
}