Merge pull request #981 from Santarh/refact

Refactaring Material Import/Export
This commit is contained in:
ousttrue
2021-05-26 18:41:19 +09:00
committed by GitHub
20 changed files with 161 additions and 167 deletions

View File

@@ -32,23 +32,21 @@ namespace UniGLTF
#endregion
MaterialFactory m_materialFactory;
public MaterialFactory MaterialFactory => m_materialFactory;
public readonly GltfMaterialImporter GltfMaterialImporter = new GltfMaterialImporter();
TextureFactory m_textureFactory;
public TextureFactory TextureFactory => m_textureFactory;
public IMaterialImporter MaterialImporter { get; protected set; }
public TextureFactory TextureFactory { get; }
public MaterialFactory MaterialFactory { get; }
public ImporterContext(GltfParser parser, IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null)
{
m_parser = parser;
MaterialImporter = new GltfMaterialImporter();
externalObjectMap = externalObjectMap ?? new Dictionary<SubAssetKey, UnityEngine.Object>();
m_textureFactory = new TextureFactory(externalObjectMap
TextureFactory = new TextureFactory(externalObjectMap
.Where(x => x.Value is Texture)
.ToDictionary(x => x.Key, x => (Texture) x.Value));
m_materialFactory = new MaterialFactory(externalObjectMap
MaterialFactory = new MaterialFactory(externalObjectMap
.Where(x => x.Value is Material)
.ToDictionary(x => x.Key, x => (Material) x.Value));
}
@@ -183,14 +181,14 @@ namespace UniGLTF
if (m_parser.GLTF.materials == null || m_parser.GLTF.materials.Count == 0)
{
// no material. work around.
var param = GltfMaterialImporter.GetMaterialParam(m_parser, 0);
var param = MaterialImporter.GetMaterialParam(m_parser, 0);
var material = await MaterialFactory.LoadAsync(param, TextureFactory.GetTextureAsync);
}
else
{
for (int i = 0; i < m_parser.GLTF.materials.Count; ++i)
{
var param = GltfMaterialImporter.GetMaterialParam(m_parser, i);
var param = MaterialImporter.GetMaterialParam(m_parser, i);
var material = await MaterialFactory.LoadAsync(param, TextureFactory.GetTextureAsync);
}
}
@@ -293,8 +291,8 @@ namespace UniGLTF
}
Meshes.Clear();
m_materialFactory.Dispose();
m_textureFactory.Dispose();
MaterialFactory?.Dispose();
TextureFactory?.Dispose();
if (m_ownRoot && Root != null)
{

View File

@@ -5,27 +5,29 @@ using VRMShaders;
namespace UniGLTF
{
public delegate bool TryCreateMaterialParamFromGltf(GltfParser parser, int i, out MaterialImportParam param);
public class GltfMaterialImporter
/// <summary>
/// GLTF の MaterialImporter
/// </summary>
public sealed class GltfMaterialImporter : IMaterialImporter
{
/// <summary>
/// gltfMaterialを解釈する関数。
/// 拡張するには、先頭に挿入するべし。
/// </summary>
/// <typeparam name="TryCreateMaterialParamFromGltf"></typeparam>
/// <returns></returns>
public readonly List<TryCreateMaterialParamFromGltf> GltfMaterialParamProcessors = new List<TryCreateMaterialParamFromGltf>();
public GltfMaterialImporter()
public MaterialImportParam GetMaterialParam(GltfParser parser, int i)
{
// unlit を試し
GltfMaterialParamProcessors.Add(GltfUnlitMaterial.TryCreateParam);
// PBR を作成する(失敗しない)
GltfMaterialParamProcessors.Add(GltfPBRMaterial.TryCreateParam);
if (!GltfUnlitMaterialImporter.TryCreateParam(parser, i, out var param))
{
if (!GltfPbrMaterialImporter.TryCreateParam(parser, i, out param))
{
// fallback
#if VRM_DEVELOP
Debug.LogWarning($"material: {i} out of range. fallback");
#endif
return new MaterialImportParam(GetMaterialName(i, null), GltfPbrMaterialImporter.ShaderName);
}
}
return param;
}
public static string MaterialName(int index, glTFMaterial src)
public static string GetMaterialName(int index, glTFMaterial src)
{
if (src != null && !string.IsNullOrEmpty(src.name))
{
@@ -33,81 +35,5 @@ namespace UniGLTF
}
return $"material_{index:00}";
}
public MaterialImportParam GetMaterialParam(GltfParser parser, int i)
{
foreach (var tryCreate in GltfMaterialParamProcessors)
{
if (tryCreate(parser, i, out MaterialImportParam param))
{
return param;
}
}
// fallback
#if VRM_DEVELOP
Debug.LogWarning($"material: {i} out of range. fallback");
#endif
return new MaterialImportParam(MaterialName(i, null), GltfPBRMaterial.ShaderName);
}
public static (Vector2, Vector2) GetTextureOffsetAndScale(glTFTextureInfo textureInfo)
{
if (glTF_KHR_texture_transform.TryGet(textureInfo, out var textureTransform))
{
return GetTextureOffsetAndScale(textureTransform);
}
return (new Vector2(0, 0), new Vector2(1, 1));
}
public static (Vector2, Vector2) GetTextureOffsetAndScale(glTF_KHR_texture_transform textureTransform)
{
var offset = new Vector2(0, 0);
var scale = new Vector2(1, 1);
if (textureTransform != null)
{
if (textureTransform.offset != null && textureTransform.offset.Length == 2)
{
offset = new Vector2(textureTransform.offset[0], textureTransform.offset[1]);
}
if (textureTransform.scale != null && textureTransform.scale.Length == 2)
{
scale = new Vector2(textureTransform.scale[0], textureTransform.scale[1]);
}
// UV Coordinate Conversion: glTF(top-left origin) to Unity(bottom-left origin)
// Formula: https://github.com/vrm-c/UniVRM/issues/930
offset.y = 1.0f - offset.y - scale.y;
}
return (offset, scale);
}
/// <summary>
/// for unittest
/// </summary>
public static glTF CreateMaterialForTest(glTFMaterial material)
{
return new glTF
{
materials = new System.Collections.Generic.List<glTFMaterial> {
material
},
textures = new List<glTFTexture>{
new glTFTexture{
name = "texture_0"
}
},
images = new List<glTFImage>{
new glTFImage{
name = "image_0",
mimeType = "image/png",
}
},
};
}
}
}

View File

@@ -35,7 +35,7 @@ namespace UniGLTF
/// _ZWrite
///
/// </summary>
public static class GltfPBRMaterial
public static class GltfPbrMaterialImporter
{
public const string ShaderName = "Standard";
@@ -49,7 +49,7 @@ namespace UniGLTF
public static (SubAssetKey, TextureImportParam Param) BaseColorTexture(GltfParser parser, glTFMaterial src)
{
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
return GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
}
@@ -62,7 +62,7 @@ namespace UniGLTF
metallicFactor = src.pbrMetallicRoughness.metallicFactor;
roughnessFactor = src.pbrMetallicRoughness.roughnessFactor;
}
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture);
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture);
return GltfTextureImporter.CreateStandard(parser,
src.pbrMetallicRoughness?.metallicRoughnessTexture?.index,
src.occlusionTexture?.index,
@@ -73,13 +73,13 @@ namespace UniGLTF
public static (SubAssetKey, TextureImportParam Param) NormalTexture(GltfParser parser, glTFMaterial src)
{
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.normalTexture);
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.normalTexture);
return GltfTextureImporter.CreateNormal(parser, src.normalTexture.index, offset, scale);
}
public static (SubAssetKey, TextureImportParam Param) EmissiveTexture(GltfParser parser, glTFMaterial src)
{
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.emissiveTexture);
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.emissiveTexture);
return GltfTextureImporter.CreateSRGB(parser, src.emissiveTexture.index, offset, scale);
}
@@ -92,7 +92,7 @@ namespace UniGLTF
}
var src = parser.GLTF.materials[i];
param = new MaterialImportParam(GltfMaterialImporter.MaterialName(i, src), ShaderName);
param = new MaterialImportParam(GltfMaterialImporter.GetMaterialName(i, src), ShaderName);
var standardParam = default(TextureImportParam);
if (src.pbrMetallicRoughness != null || src.occlusionTexture != null)

View File

@@ -4,7 +4,7 @@ using VRMShaders;
namespace UniGLTF
{
public static class GltfUnlitMaterial
public static class GltfUnlitMaterialImporter
{
public const string ShaderName = "UniGLTF/UniUnlit";
@@ -22,13 +22,13 @@ namespace UniGLTF
param = default;
return false;
}
param = new MaterialImportParam(GltfMaterialImporter.MaterialName(i, src), ShaderName);
param = new MaterialImportParam(GltfMaterialImporter.GetMaterialName(i, src), ShaderName);
// texture
if (src.pbrMetallicRoughness.baseColorTexture != null)
{
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
var (key, textureParam) = GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
param.TextureSlots.Add("_MainTex", textureParam);
}

View File

@@ -0,0 +1,14 @@
using UnityEngine;
using VRMShaders;
namespace UniGLTF
{
/// <summary>
/// 指定の Unity Material から glTFMaterial を生成する。
/// glTFMaterial と Unity Material は 1:1 対応する。
/// </summary>
public interface IMaterialExporter
{
glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: afbe933c51a9404199ba1efe6d2f8c62
timeCreated: 1622015749

View File

@@ -0,0 +1,13 @@
using VRMShaders;
namespace UniGLTF
{
/// <summary>
/// 指定の index の glTFMaterial から Import できる Material の生成情報を生成する。
/// glTFMaterial と Unity Material は 1:1 対応する。
/// </summary>
public interface IMaterialImporter
{
MaterialImportParam GetMaterialParam(GltfParser parser, int i);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c309fb8ee8534a54b291d408511c9331
timeCreated: 1622015740

View File

@@ -13,11 +13,6 @@ namespace UniGLTF
BLEND
}
public interface IMaterialExporter
{
glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter);
}
public class MaterialExporter : IMaterialExporter
{
public virtual glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter)

View File

@@ -38,7 +38,7 @@ namespace UniGLTF
// base color
if (m.pbrMetallicRoughness?.baseColorTexture != null)
{
yield return GltfPBRMaterial.BaseColorTexture(parser, m);
yield return GltfPbrMaterialImporter.BaseColorTexture(parser, m);
}
// metallic roughness
@@ -51,13 +51,13 @@ namespace UniGLTF
// emission
if (m.emissiveTexture != null)
{
yield return GltfPBRMaterial.EmissiveTexture(parser, m);
yield return GltfPbrMaterialImporter.EmissiveTexture(parser, m);
}
// normal
if (m.normalTexture != null)
{
yield return GltfPBRMaterial.NormalTexture(parser, m);
yield return GltfPbrMaterialImporter.NormalTexture(parser, m);
}
// occlusion
@@ -70,7 +70,7 @@ namespace UniGLTF
// metallicSmooth and occlusion
if (metallicRoughnessTexture.HasValue || occlusionTexture.HasValue)
{
yield return GltfPBRMaterial.StandardTexture(parser, m);
yield return GltfPbrMaterialImporter.StandardTexture(parser, m);
}
}

View File

@@ -91,5 +91,39 @@ namespace UniGLTF
var param = new TextureImportParam(name, ".png", null, offset, scale, sampler, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, getMetallicRoughnessAsync, getOcclusionAsync, default, default, default, default);
return (param.SubAssetKey, param);
}
public static (Vector2, Vector2) GetTextureOffsetAndScale(glTFTextureInfo textureInfo)
{
if (glTF_KHR_texture_transform.TryGet(textureInfo, out var textureTransform))
{
return GetTextureOffsetAndScale(textureTransform);
}
return (new Vector2(0, 0), new Vector2(1, 1));
}
public static (Vector2, Vector2) GetTextureOffsetAndScale(glTF_KHR_texture_transform textureTransform)
{
var offset = new Vector2(0, 0);
var scale = new Vector2(1, 1);
if (textureTransform != null)
{
if (textureTransform.offset != null && textureTransform.offset.Length == 2)
{
offset = new Vector2(textureTransform.offset[0], textureTransform.offset[1]);
}
if (textureTransform.scale != null && textureTransform.scale.Length == 2)
{
scale = new Vector2(textureTransform.scale[0], textureTransform.scale[1]);
}
// UV Coordinate Conversion: glTF(top-left origin) to Unity(bottom-left origin)
// Formula: https://github.com/vrm-c/UniVRM/issues/930
offset.y = 1.0f - offset.y - scale.y;
}
return (offset, scale);
}
}
}

View File

@@ -27,8 +27,7 @@ namespace VRM
if (glTF_VRM_extensions.TryDeserialize(GLTF.extensions, out glTF_VRM_extensions vrm))
{
VRM = vrm;
// override material importer
GltfMaterialImporter.GltfMaterialParamProcessors.Insert(0, new VRMMaterialImporter(VRM).TryCreateParam);
MaterialImporter = new VRMMaterialImporter(VRM);
}
else
{

View File

@@ -6,7 +6,7 @@ using VRMShaders;
namespace VRM
{
public class VRMMaterialImporter
public sealed class VRMMaterialImporter : IMaterialImporter
{
readonly glTF_VRM_extensions m_vrm;
public VRMMaterialImporter(glTF_VRM_extensions vrm)
@@ -100,10 +100,17 @@ namespace VRM
if (!TryCreateParam(parser, i, out MaterialImportParam param))
{
// unlit
if (!GltfUnlitMaterial.TryCreateParam(parser, i, out param))
if (!GltfUnlitMaterialImporter.TryCreateParam(parser, i, out param))
{
// pbr
GltfPBRMaterial.TryCreateParam(parser, i, out param);
if (!GltfPbrMaterialImporter.TryCreateParam(parser, i, out param))
{
// fallback
#if VRM_DEVELOP
Debug.LogWarning($"material: {i} out of range. fallback");
#endif
return new MaterialImportParam(GltfMaterialImporter.GetMaterialName(i, null), GltfPbrMaterialImporter.ShaderName);
}
}
}
return param;

View File

@@ -20,17 +20,17 @@ namespace UniVRM10
{
yield return (MToon.Utils.PropEmissionMap, emissiveTex);
}
if (TryGetNormalTexture(parser, material, out var normalTex))
{
yield return ("_BumpMap", normalTex);
}
if (TryGetShadeMultiplyTexture(parser, mToon, out var shadeTex))
{
yield return (MToon.Utils.PropShadeTexture, shadeTex);
}
if (TryGetShadingShiftTexture(parser, mToon, out var shadeShiftTex))
{
Debug.LogWarning("Need VRM 1.0 MToon implementation.");
@@ -62,7 +62,7 @@ namespace UniVRM10
{
try
{
pair = GltfPBRMaterial.BaseColorTexture(parser, src);
pair = GltfPbrMaterialImporter.BaseColorTexture(parser, src);
return true;
}
catch (NullReferenceException)
@@ -81,7 +81,7 @@ namespace UniVRM10
{
try
{
pair = GltfPBRMaterial.EmissiveTexture(parser, src);
pair = GltfPbrMaterialImporter.EmissiveTexture(parser, src);
return true;
}
catch (NullReferenceException)
@@ -94,14 +94,14 @@ namespace UniVRM10
pair = default;
return false;
}
}
private static bool TryGetNormalTexture(GltfParser parser, glTFMaterial src, out (SubAssetKey, TextureImportParam) pair)
{
try
{
pair = GltfPBRMaterial.NormalTexture(parser, src);
pair = GltfPbrMaterialImporter.NormalTexture(parser, src);
return true;
}
catch (NullReferenceException)
@@ -189,7 +189,7 @@ namespace UniVRM10
{
if (glTF_KHR_texture_transform.TryGet(textureInfo, out var textureTransform))
{
return GltfMaterialImporter.GetTextureOffsetAndScale(textureTransform);
return GltfTextureImporter.GetTextureOffsetAndScale(textureTransform);
}
return (new Vector2(0, 0), new Vector2(1, 1));
}
@@ -202,7 +202,7 @@ namespace UniVRM10
public Vrm10TextureInfo(TextureInfo info)
{
if (info == null) return;
index = info.Index ?? -1;
texCoord = info.TexCoord ?? -1;
extensions = info.Extensions as glTFExtension;
@@ -212,7 +212,7 @@ namespace UniVRM10
public Vrm10TextureInfo(ShadingShiftTextureInfo info)
{
if (info == null) return;
index = info.Index ?? -1;
texCoord = info.TexCoord ?? -1;
extensions = info.Extensions as glTFExtension;
@@ -220,4 +220,4 @@ namespace UniVRM10
}
}
}
}
}

View File

@@ -24,6 +24,8 @@ namespace UniVRM10
public Vrm10Importer(UniGLTF.GltfParser parser, IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null)
: base(parser, externalObjectMap)
{
MaterialImporter = new Vrm10MaterialImporter();
m_externalMap = externalObjectMap;
if (m_externalMap == null)
{
@@ -31,9 +33,6 @@ namespace UniVRM10
}
m_model = ModelReader.Read(parser);
// for `VRMC_materials_mtoon`
this.GltfMaterialImporter.GltfMaterialParamProcessors.Insert(0, Vrm10MaterialImporter.TryCreateParam);
if (!UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out m_vrm))
{
throw new Exception("VRMC_vrm is not found");

View File

@@ -4,16 +4,34 @@ using VRMShaders;
namespace UniVRM10
{
public static class Vrm10MaterialImporter
public sealed class Vrm10MaterialImporter : IMaterialImporter
{
public MaterialImportParam GetMaterialParam(GltfParser parser, int i)
{
// mtoon
if (!TryCreateMToonParam(parser, i, out MaterialImportParam param))
{
// unlit
if (!GltfUnlitMaterialImporter.TryCreateParam(parser, i, out param))
{
// pbr
if (!GltfPbrMaterialImporter.TryCreateParam(parser, i, out param))
{
// fallback
#if VRM_DEVELOP
Debug.LogWarning($"material: {i} out of range. fallback");
#endif
return new MaterialImportParam(GltfMaterialImporter.GetMaterialName(i, null), GltfPbrMaterialImporter.ShaderName);
}
}
}
return param;
}
/// <summary>
/// VMRC_materials_mtoon の場合にマテリアル生成情報を作成する
/// </summary>
/// <param name="parser"></param>
/// <param name="i"></param>
/// <param name="param"></param>
/// <returns></returns>
public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportParam param)
public bool TryCreateMToonParam(GltfParser parser, int i, out MaterialImportParam param)
{
var m = parser.GLTF.materials[i];
if (!UniGLTF.Extensions.VRMC_materials_mtoon.GltfDeserializer.TryGet(m.extensions,
@@ -48,7 +66,7 @@ namespace UniVRM10
}
param.RenderQueue = Vrm10MToonMaterialParameterImporter.TryGetRenderQueue(m, mtoon);
param.Actions.Add(material =>
{
// Set hidden properties, keywords from float properties.
@@ -57,20 +75,5 @@ namespace UniVRM10
return true;
}
public static MaterialImportParam GetMaterialParam(GltfParser parser, int i)
{
// mtoon
if (!TryCreateParam(parser, i, out MaterialImportParam param))
{
// unlit
if (!GltfUnlitMaterial.TryCreateParam(parser, i, out param))
{
// pbr
GltfPBRMaterial.TryCreateParam(parser, i, out param);
}
}
return param;
}
}
}

View File

@@ -25,7 +25,7 @@ namespace UniVRM10
var parser = new GltfParser();
parser.Parse(AliciaPath, migratedBytes);
var materialParam = Vrm10MaterialImporter.GetMaterialParam(parser, 0);
var materialParam = new Vrm10MaterialImporter().GetMaterialParam(parser, 0);
Assert.AreEqual("VRM/MToon", materialParam.ShaderName);
Assert.AreEqual("Alicia_body", materialParam.TextureSlots["_MainTex"].UnityObjectName);