From 8af4eaecf5e06365507e6d634146aab451fdc612 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Thu, 3 Nov 2022 02:01:47 +0900 Subject: [PATCH] Refactoring Material Exporters --- .../UniGLTF/ExportDialog/MaterialValidator.cs | 39 +- .../BuiltinRPFallbackMaterialExporter.cs | 22 ++ .../BuiltinRPFallbackMaterialExporter.cs.meta | 3 + .../BuiltinRPGenericUnlitMaterialExporter.cs | 72 ++++ ...ltinRPGenericUnlitMaterialExporter.cs.meta | 3 + .../BuiltinRPGltfMaterialExporter.cs | 46 +++ .../BuiltinRPGltfMaterialExporter.cs.meta} | 0 .../BuiltinRPStandardMaterialExporter.cs | 215 +++++++++++ .../BuiltinRPStandardMaterialExporter.cs.meta | 3 + .../BuiltinRPUniUnlitMaterialExporter.cs | 83 +++++ .../BuiltinRPUniUnlitMaterialExporter.cs.meta | 3 + .../IO/MaterialIO/MaterialExportUtils.cs | 20 ++ .../IO/MaterialIO/MaterialExportUtils.cs.meta | 3 + .../UniGLTF/IO/MaterialIO/MaterialExporter.cs | 339 ------------------ .../UniGLTF/IO/MaterialIO/glTFBlendMode.cs | 9 + .../IO/MaterialIO/glTFBlendMode.cs.meta | 3 + .../Runtime/UniGLTF/IO/gltfExporter.cs | 2 +- .../VRM/Editor/Format/VRMMaterialValidator.cs | 6 +- Assets/VRM/Runtime/IO/BuiltinRP.meta | 3 + .../BuiltinRPVrmMToonMaterialExporter.cs | 124 +++++++ .../BuiltinRPVrmMToonMaterialExporter.cs.meta | 3 + .../BuiltinRP/BuiltinRPVrmMaterialExporter.cs | 44 +++ .../BuiltinRPVrmMaterialExporter.cs.meta} | 0 .../VrmExtensionMaterialPropertyExporter.cs | 130 +++++++ ...mExtensionMaterialPropertyExporter.cs.meta | 3 + Assets/VRM/Runtime/IO/VRMExporter.cs | 4 +- Assets/VRM/Runtime/IO/VRMMaterialExporter.cs | 237 ------------ Assets/VRM/Tests/MToonTest.cs | 3 +- .../VRM/Tests/SampleTests/VRMMaterialTests.cs | 2 +- ...r.cs => BuiltinRPVrm10MaterialExporter.cs} | 2 +- ...=> BuiltinRPVrm10MaterialExporter.cs.meta} | 0 Assets/VRM10/Runtime/IO/Vrm10Exporter.cs | 2 +- 32 files changed, 812 insertions(+), 616 deletions(-) create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs.meta create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs.meta create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGltfMaterialExporter.cs rename Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/{MaterialExporter.cs.meta => BuiltinRP/BuiltinRPGltfMaterialExporter.cs.meta} (100%) create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs.meta create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs.meta create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs.meta delete mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs.meta create mode 100644 Assets/VRM/Runtime/IO/BuiltinRP.meta create mode 100644 Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs create mode 100644 Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs.meta create mode 100644 Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMaterialExporter.cs rename Assets/VRM/Runtime/IO/{VRMMaterialExporter.cs.meta => BuiltinRP/BuiltinRPVrmMaterialExporter.cs.meta} (100%) create mode 100644 Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs create mode 100644 Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs.meta delete mode 100644 Assets/VRM/Runtime/IO/VRMMaterialExporter.cs rename Assets/VRM10/Runtime/IO/{Vrm10MaterialExporter.cs => BuiltinRPVrm10MaterialExporter.cs} (86%) rename Assets/VRM10/Runtime/IO/{Vrm10MaterialExporter.cs.meta => BuiltinRPVrm10MaterialExporter.cs.meta} (100%) diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MaterialValidator.cs b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MaterialValidator.cs index b1c9f32a5..fabcb31ed 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MaterialValidator.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MaterialValidator.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace UniGLTF @@ -30,43 +31,23 @@ namespace UniGLTF { public virtual string GetGltfMaterialTypeFromUnityShaderName(string shaderName) { - if (shaderName == "Standard") + if (BuiltinRPGltfMaterialExporter.SupportedShaderNames.Contains(shaderName)) { - return "pbr"; - } - if (MaterialExporter.IsUnlit(shaderName)) - { - return "unlit"; + return "gltf"; } + return null; } public virtual IEnumerable<(string propertyName, Texture texture)> EnumerateTextureProperties(Material m) { - // main color - yield return (MaterialExporter.COLOR_TEXTURE_PROP, m.GetTexture(MaterialExporter.COLOR_TEXTURE_PROP)); - - if (GetGltfMaterialTypeFromUnityShaderName(m.shader.name) == "unlit") + foreach (var texturePropertyName in m.GetTexturePropertyNames()) { - yield break; - } - - // PBR - if (m.HasProperty(MaterialExporter.METALLIC_TEX_PROP)) - { - yield return (MaterialExporter.METALLIC_TEX_PROP, m.GetTexture(MaterialExporter.METALLIC_TEX_PROP)); - } - if (m.HasProperty(MaterialExporter.NORMAL_TEX_PROP)) - { - yield return (MaterialExporter.NORMAL_TEX_PROP, m.GetTexture(MaterialExporter.NORMAL_TEX_PROP)); - } - if (m.HasProperty(MaterialExporter.EMISSION_TEX_PROP)) - { - yield return (MaterialExporter.EMISSION_TEX_PROP, m.GetTexture(MaterialExporter.EMISSION_TEX_PROP)); - } - if (m.HasProperty(MaterialExporter.OCCLUSION_TEX_PROP)) - { - yield return (MaterialExporter.OCCLUSION_TEX_PROP, m.GetTexture(MaterialExporter.OCCLUSION_TEX_PROP)); + var tex = m.GetTexture(texturePropertyName); + if (tex != null) + { + yield return (texturePropertyName, tex); + } } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs new file mode 100644 index 000000000..a56560aa5 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs @@ -0,0 +1,22 @@ +using UnityEngine; +using VRMShaders; + +namespace UniGLTF +{ + /// + /// 非対応のシェーダでも空のマテリアルを出力する. + /// + public static class BuiltinRPFallbackMaterialExporter + { + public static glTFMaterial ExportMaterial(Material src, ITextureExporter textureExporter) + { + var dst = new glTFMaterial + { + name = src.name, + pbrMetallicRoughness = new glTFPbrMetallicRoughness(), + }; + + return dst; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs.meta new file mode 100644 index 000000000..1a9537e82 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPFallbackMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 983277a982364497b7491610ac4868f0 +timeCreated: 1667405705 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs new file mode 100644 index 000000000..7b6526ad8 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs @@ -0,0 +1,72 @@ +using System; +using UnityEngine; +using VRMShaders; +using ColorSpace = VRMShaders.ColorSpace; + +namespace UniGLTF +{ + /// + /// Built-in RP で一般的に用いられる Unlit Shader をエクスポートすることを試みる。 + /// + public static class BuiltinRPGenericUnlitMaterialExporter + { + private const string ColorFactorPropertyName = "_Color"; + private const string ColorTexturePropertyName = "_MainTex"; + private const string CutoffPropertyName = "_Cutoff"; + + public static bool TryExportMaterial(Material src, glTFBlendMode blendMode, ITextureExporter textureExporter, out glTFMaterial dst) + { + dst = glTF_KHR_materials_unlit.CreateDefault(); + dst.name = src.name; + + ExportRenderingSettings(src, blendMode, dst); + ExportBaseColor(src, blendMode, textureExporter, dst); + + return true; + } + + private static void ExportRenderingSettings(Material src, glTFBlendMode blendMode, glTFMaterial dst) + { + switch (blendMode) + { + case glTFBlendMode.OPAQUE: + dst.alphaMode = glTFBlendMode.OPAQUE.ToString(); + break; + case glTFBlendMode.MASK: + dst.alphaMode = glTFBlendMode.MASK.ToString(); + dst.alphaCutoff = src.GetFloat(CutoffPropertyName); + break; + case glTFBlendMode.BLEND: + dst.alphaMode = glTFBlendMode.BLEND.ToString(); + break; + default: + throw new ArgumentOutOfRangeException(nameof(blendMode), blendMode, null); + } + } + + private static void ExportBaseColor(Material src, glTFBlendMode blendMode, ITextureExporter textureExporter, glTFMaterial dst) + { + if (src.HasProperty(ColorFactorPropertyName)) + { + dst.pbrMetallicRoughness.baseColorFactor = src.GetColor(ColorFactorPropertyName).ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); + } + + if (src.HasProperty(ColorTexturePropertyName)) + { + // Don't export alpha channel if material was OPAQUE + var unnecessaryAlpha = blendMode == glTFBlendMode.OPAQUE; + + var index = textureExporter.RegisterExportingAsSRgb(src.GetTexture(ColorTexturePropertyName), !unnecessaryAlpha); + if (index != -1) + { + dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo() + { + index = index, + }; + + MaterialExportUtils.ExportTextureTransform(src, dst.pbrMetallicRoughness.baseColorTexture, ColorTexturePropertyName); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs.meta new file mode 100644 index 000000000..1893f96e1 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGenericUnlitMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0c4ed66ba3f44b28a1d303cdf073dc2b +timeCreated: 1667402621 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGltfMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGltfMaterialExporter.cs new file mode 100644 index 000000000..00bb00ff9 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGltfMaterialExporter.cs @@ -0,0 +1,46 @@ +using UnityEngine; +using VRMShaders; + +namespace UniGLTF +{ + public class BuiltinRPGltfMaterialExporter : IMaterialExporter + { + public static readonly string[] SupportedShaderNames = + { + BuiltinRPStandardMaterialExporter.TargetShaderName, + BuiltinRPUniUnlitMaterialExporter.TargetShaderName, + "Unlit/Color", + "Unlit/Texture", + "Unlit/Transparent", + "Unlit/Transparent Cutout", + }; + + public virtual glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings) + { + glTFMaterial dst; + switch (m.shader.name) + { + case BuiltinRPStandardMaterialExporter.TargetShaderName: + if (BuiltinRPStandardMaterialExporter.TryExportMaterial(m, textureExporter, out dst)) return dst; + break; + case BuiltinRPUniUnlitMaterialExporter.TargetShaderName: + if (BuiltinRPUniUnlitMaterialExporter.TryExportMaterial(m, textureExporter, out dst)) return dst; + break; + case "Unlit/Color": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(m, glTFBlendMode.OPAQUE, textureExporter, out dst)) return dst; + break; + case "Unlit/Texture": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(m, glTFBlendMode.OPAQUE, textureExporter, out dst)) return dst; + break; + case "Unlit/Transparent": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(m, glTFBlendMode.BLEND, textureExporter, out dst)) return dst; + break; + case "Unlit/Transparent Cutout": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(m, glTFBlendMode.MASK, textureExporter, out dst)) return dst; + break; + } + + return BuiltinRPFallbackMaterialExporter.ExportMaterial(m, textureExporter); + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGltfMaterialExporter.cs.meta similarity index 100% rename from Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs.meta rename to Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPGltfMaterialExporter.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs new file mode 100644 index 000000000..f79a0a30a --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs @@ -0,0 +1,215 @@ +using System; +using System.Linq; +using UnityEngine; +using VRMShaders; +using ColorSpace = VRMShaders.ColorSpace; + +namespace UniGLTF +{ + public static class BuiltinRPStandardMaterialExporter + { + public const string TargetShaderName = "Standard"; + + private const string ColorTexturePropertyName = "_MainTex"; + private const string MetallicGlossTexturePropertyName = "_MetallicGlossMap"; + private const string NormalTexturePropertyName = "_BumpMap"; + private const string EmissionTexturePropertyName = "_EmissionMap"; + private const string OcclusionTexturePropertyName = "_OcclusionMap"; + + public static bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst) + { + if (src.shader.name != TargetShaderName) + { + dst = default; + return false; + } + + dst = new glTFMaterial + { + name = src.name, + pbrMetallicRoughness = new glTFPbrMetallicRoughness(), + }; + + ExportRenderingSettings(src, dst); + ExportBaseColor(src, textureExporter, dst); + ExportEmission(src, textureExporter, dst); + ExportNormal(src, textureExporter, dst); + ExportOcclusionMetallicRoughness(src, textureExporter, dst); + + return true; + } + + private static void ExportRenderingSettings(Material src, glTFMaterial dst) + { + switch (src.GetTag("RenderType", true)) + { + case "Transparent": + dst.alphaMode = glTFBlendMode.BLEND.ToString(); + break; + + case "TransparentCutout": + dst.alphaMode = glTFBlendMode.MASK.ToString(); + dst.alphaCutoff = src.GetFloat("_Cutoff"); + break; + + default: + dst.alphaMode = glTFBlendMode.OPAQUE.ToString(); + break; + } + } + + private static void ExportBaseColor(Material src, ITextureExporter textureExporter, glTFMaterial dst) + { + if (src.HasProperty("_Color")) + { + dst.pbrMetallicRoughness.baseColorFactor = src.GetColor("_Color").ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); + } + + if (src.HasProperty(ColorTexturePropertyName)) + { + // Don't export alpha channel if material was OPAQUE + var unnecessaryAlpha = string.Equals(dst.alphaMode, "OPAQUE", StringComparison.Ordinal); + + var index = textureExporter.RegisterExportingAsSRgb(src.GetTexture(ColorTexturePropertyName), !unnecessaryAlpha); + if (index != -1) + { + dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo() + { + index = index, + }; + + ExportMainTextureTransform(src, dst.pbrMetallicRoughness.baseColorTexture); + } + } + } + + /// + /// Occlusion, Metallic, Roughness + /// + private static void ExportOcclusionMetallicRoughness(Material src, ITextureExporter textureExporter, glTFMaterial dst) + { + Texture metallicSmoothTexture = default; + float smoothness = 1.0f; + + var textuerNames = src.GetTexturePropertyNames(); + if (textuerNames.Contains(MetallicGlossTexturePropertyName)) + { + if (src.HasProperty("_GlossMapScale")) + { + smoothness = src.GetFloat("_GlossMapScale"); + } + metallicSmoothTexture = src.GetTexture(MetallicGlossTexturePropertyName); + } + + Texture occlusionTexture = default; + var occlusionStrength = 1.0f; + if (textuerNames.Contains(OcclusionTexturePropertyName)) + { + occlusionTexture = src.GetTexture(OcclusionTexturePropertyName); + if (occlusionTexture != null && src.HasProperty("_OcclusionStrength")) + { + occlusionStrength = src.GetFloat("_OcclusionStrength"); + } + } + + int index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures(metallicSmoothTexture, smoothness, occlusionTexture); + + if (index != -1 && metallicSmoothTexture != null) + { + dst.pbrMetallicRoughness.metallicRoughnessTexture = + new glTFMaterialMetallicRoughnessTextureInfo() + { + index = index, + }; + ExportMainTextureTransform(src, dst.pbrMetallicRoughness.metallicRoughnessTexture); + + // Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212. + dst.pbrMetallicRoughness.metallicFactor = 1.0f; + dst.pbrMetallicRoughness.roughnessFactor = 1.0f; + } + else + { + if (src.HasProperty("_Metallic")) + { + dst.pbrMetallicRoughness.metallicFactor = src.GetFloat("_Metallic"); + } + + if (src.HasProperty("_Glossiness")) + { + dst.pbrMetallicRoughness.roughnessFactor = 1.0f - src.GetFloat("_Glossiness"); + } + } + + if (index != -1 && occlusionTexture != null) + { + dst.occlusionTexture = new glTFMaterialOcclusionTextureInfo() + { + index = index, + strength = occlusionStrength, + }; + ExportMainTextureTransform(src, dst.occlusionTexture); + } + } + + private static void ExportNormal(Material src, ITextureExporter textureExporter, glTFMaterial dst) + { + if (src.HasProperty(NormalTexturePropertyName)) + { + var index = textureExporter.RegisterExportingAsNormal(src.GetTexture(NormalTexturePropertyName)); + if (index != -1) + { + dst.normalTexture = new glTFMaterialNormalTextureInfo() + { + index = index, + }; + + ExportMainTextureTransform(src, dst.normalTexture); + } + + if (index != -1 && src.HasProperty("_BumpScale")) + { + dst.normalTexture.scale = src.GetFloat("_BumpScale"); + } + } + } + + private static void ExportEmission(Material src, ITextureExporter textureExporter, glTFMaterial dst) + { + if (src.IsKeywordEnabled("_EMISSION") == false) + { + return; + } + + if (src.HasProperty("_EmissionColor")) + { + var color = src.GetColor("_EmissionColor"); + if (color.maxColorComponent > 1) + { + var maxColorComponent = color.maxColorComponent; + color /= maxColorComponent; + UniGLTF.glTF_KHR_materials_emissive_strength.Serialize(ref dst.extensions, maxColorComponent); + } + dst.emissiveFactor = color.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); + } + + if (src.HasProperty(EmissionTexturePropertyName)) + { + var index = textureExporter.RegisterExportingAsSRgb(src.GetTexture(EmissionTexturePropertyName), needsAlpha: false); + if (index != -1) + { + dst.emissiveTexture = new glTFMaterialEmissiveTextureInfo() + { + index = index, + }; + + ExportMainTextureTransform(src, dst.emissiveTexture); + } + } + } + + private static void ExportMainTextureTransform(Material src, glTFTextureInfo targetTextureInfo) + { + MaterialExportUtils.ExportTextureTransform(src, targetTextureInfo, ColorTexturePropertyName); + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs.meta new file mode 100644 index 000000000..14cf5d10b --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPStandardMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ec789661012740afbe8b5422aadc5fa0 +timeCreated: 1667399599 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs new file mode 100644 index 000000000..d401f08c2 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs @@ -0,0 +1,83 @@ +using System; +using UniGLTF.UniUnlit; +using UnityEngine; +using VRMShaders; +using ColorSpace = VRMShaders.ColorSpace; + +namespace UniGLTF +{ + public static class BuiltinRPUniUnlitMaterialExporter + { + public const string TargetShaderName = UniUnlit.UniUnlitUtil.ShaderName; + + public static bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst) + { + if (src.shader.name != TargetShaderName) + { + dst = default; + return false; + } + + dst = glTF_KHR_materials_unlit.CreateDefault(); + dst.name = src.name; + + ExportRenderingSettings(src, dst); + ExportBaseColor(src, textureExporter, dst); + + return true; + } + + private static void ExportRenderingSettings(Material src, glTFMaterial dst) + { + switch (UniUnlitUtil.GetRenderMode(src)) + { + case UniUnlitRenderMode.Opaque: + dst.alphaMode = glTFBlendMode.OPAQUE.ToString(); + break; + case UniUnlitRenderMode.Cutout: + dst.alphaMode = glTFBlendMode.MASK.ToString(); + dst.alphaCutoff = src.GetFloat(UniUnlitUtil.PropNameCutoff); + break; + case UniUnlitRenderMode.Transparent: + dst.alphaMode = glTFBlendMode.BLEND.ToString(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + switch (UniUnlitUtil.GetCullMode(src)) + { + case UniUnlitCullMode.Off: + dst.doubleSided = true; + break; + case UniUnlitCullMode.Back: + dst.doubleSided = false; + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + private static void ExportBaseColor(Material src, ITextureExporter textureExporter, glTFMaterial dst) + { + if (src.HasProperty(UniUnlitUtil.PropNameColor)) + { + dst.pbrMetallicRoughness.baseColorFactor = src.GetColor(UniUnlitUtil.PropNameColor).ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); + } + + if (src.HasProperty(UniUnlitUtil.PropNameMainTex)) + { + var index = textureExporter.RegisterExportingAsSRgb(src.GetTexture(UniUnlitUtil.PropNameMainTex), UniUnlitUtil.GetRenderMode(src) != UniUnlitRenderMode.Opaque); + if (index != -1) + { + dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo() + { + index = index, + }; + + MaterialExportUtils.ExportTextureTransform(src, dst.pbrMetallicRoughness.baseColorTexture, UniUnlitUtil.PropNameMainTex); + } + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs.meta new file mode 100644 index 000000000..5eb370ea2 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/BuiltinRP/BuiltinRPUniUnlitMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4a8ebb5c42054bd7be905f2dcb595457 +timeCreated: 1667403411 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs new file mode 100644 index 000000000..ff602a3f1 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs @@ -0,0 +1,20 @@ +using System; +using UnityEngine; + +namespace UniGLTF +{ + public static class MaterialExportUtils + { + public static void ExportTextureTransform(Material src, glTFTextureInfo dstTextureInfo, string targetTextureName) + { + if (dstTextureInfo != null && src.HasProperty(targetTextureName)) + { + var offset = src.GetTextureOffset(targetTextureName); + var scale = src.GetTextureScale(targetTextureName); + (scale, offset) = TextureTransform.VerticalFlipScaleOffset(scale, offset); + + glTF_KHR_texture_transform.Serialize(dstTextureInfo, (offset.x, offset.y), (scale.x, scale.y)); + } + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs.meta new file mode 100644 index 000000000..ca83166d1 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExportUtils.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4bbc9904e5fe4176b74d39eeb2318bd6 +timeCreated: 1667400475 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs deleted file mode 100644 index 92a95ff26..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs +++ /dev/null @@ -1,339 +0,0 @@ -using System; -using System.Linq; -using UniGLTF.UniUnlit; -using UnityEngine; -using VRMShaders; -using ColorSpace = VRMShaders.ColorSpace; - -namespace UniGLTF -{ - public enum glTFBlendMode - { - OPAQUE, - MASK, - BLEND - } - - public class MaterialExporter : IMaterialExporter - { - public virtual glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings) - { - var material = CreateMaterial(m); - - // common params - material.name = m.name; - Export_Color(m, textureExporter, material); - Export_Emission(m, textureExporter, material); - Export_Normal(m, textureExporter, material); - Export_OcclusionMetallicRoughness(m, textureExporter, material); - - return material; - } - - public const string COLOR_TEXTURE_PROP = "_MainTex"; - public const string METALLIC_TEX_PROP = "_MetallicGlossMap"; - public const string NORMAL_TEX_PROP = "_BumpMap"; - public const string EMISSION_TEX_PROP = "_EmissionMap"; - public const string OCCLUSION_TEX_PROP = "_OcclusionMap"; - - static void Export_Color(Material m, ITextureExporter textureManager, glTFMaterial material) - { - if (m.HasProperty("_Color")) - { - material.pbrMetallicRoughness.baseColorFactor = m.GetColor("_Color").ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); - } - - if (m.HasProperty(COLOR_TEXTURE_PROP)) - { - // Don't export alpha channel if material was OPAQUE - var unnecessaryAlpha = string.Equals(material.alphaMode, "OPAQUE", StringComparison.Ordinal); - - var index = textureManager.RegisterExportingAsSRgb(m.GetTexture(COLOR_TEXTURE_PROP), !unnecessaryAlpha); - if (index != -1) - { - material.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo() - { - index = index, - }; - - Export_MainTextureTransform(m, material.pbrMetallicRoughness.baseColorTexture); - } - } - } - - /// - /// Occlusion, Metallic, Roughness - /// - /// - /// - /// - static void Export_OcclusionMetallicRoughness(Material m, ITextureExporter textureExporter, glTFMaterial material) - { - Texture metallicSmoothTexture = default; - float smoothness = 1.0f; - - var textuerNames = m.GetTexturePropertyNames(); - if (textuerNames.Contains(METALLIC_TEX_PROP)) - { - if (m.HasProperty("_GlossMapScale")) - { - smoothness = m.GetFloat("_GlossMapScale"); - } - metallicSmoothTexture = m.GetTexture(METALLIC_TEX_PROP); - } - - Texture occlusionTexture = default; - var occlusionStrength = 1.0f; - if (textuerNames.Contains(OCCLUSION_TEX_PROP)) - { - occlusionTexture = m.GetTexture(OCCLUSION_TEX_PROP); - if (occlusionTexture != null && m.HasProperty("_OcclusionStrength")) - { - occlusionStrength = m.GetFloat("_OcclusionStrength"); - } - } - - int index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures(metallicSmoothTexture, smoothness, occlusionTexture); - - if (index != -1 && metallicSmoothTexture != null) - { - material.pbrMetallicRoughness.metallicRoughnessTexture = - new glTFMaterialMetallicRoughnessTextureInfo() - { - index = index, - }; - Export_MainTextureTransform(m, material.pbrMetallicRoughness.metallicRoughnessTexture); - - // Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212. - material.pbrMetallicRoughness.metallicFactor = 1.0f; - material.pbrMetallicRoughness.roughnessFactor = 1.0f; - } - else - { - if (m.HasProperty("_Metallic")) - { - material.pbrMetallicRoughness.metallicFactor = m.GetFloat("_Metallic"); - } - - if (m.HasProperty("_Glossiness")) - { - material.pbrMetallicRoughness.roughnessFactor = 1.0f - m.GetFloat("_Glossiness"); - } - } - - if (index != -1 && occlusionTexture != null) - { - material.occlusionTexture = new glTFMaterialOcclusionTextureInfo() - { - index = index, - strength = occlusionStrength, - }; - Export_MainTextureTransform(m, material.occlusionTexture); - } - } - - static void Export_Normal(Material m, ITextureExporter textureExporter, glTFMaterial material) - { - if (m.HasProperty(NORMAL_TEX_PROP)) - { - var index = textureExporter.RegisterExportingAsNormal(m.GetTexture(NORMAL_TEX_PROP)); - if (index != -1) - { - material.normalTexture = new glTFMaterialNormalTextureInfo() - { - index = index, - }; - - Export_MainTextureTransform(m, material.normalTexture); - } - - if (index != -1 && m.HasProperty("_BumpScale")) - { - material.normalTexture.scale = m.GetFloat("_BumpScale"); - } - } - } - - static void Export_Emission(Material m, ITextureExporter textureExporter, glTFMaterial material) - { - if (m.IsKeywordEnabled("_EMISSION") == false) - { - return; - } - - if (m.HasProperty("_EmissionColor")) - { - var color = m.GetColor("_EmissionColor"); - if (color.maxColorComponent > 1) - { - var maxColorComponent = color.maxColorComponent; - color /= maxColorComponent; - UniGLTF.glTF_KHR_materials_emissive_strength.Serialize(ref material.extensions, maxColorComponent); - } - material.emissiveFactor = color.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); - } - - if (m.HasProperty(EMISSION_TEX_PROP)) - { - var index = textureExporter.RegisterExportingAsSRgb(m.GetTexture(EMISSION_TEX_PROP), needsAlpha: false); - if (index != -1) - { - material.emissiveTexture = new glTFMaterialEmissiveTextureInfo() - { - index = index, - }; - - Export_MainTextureTransform(m, material.emissiveTexture); - } - } - } - - static void Export_MainTextureTransform(Material m, glTFTextureInfo textureInfo) - { - Export_TextureTransform(m, textureInfo, COLOR_TEXTURE_PROP); - } - - static void Export_TextureTransform(Material m, glTFTextureInfo textureInfo, string propertyName) - { - if (textureInfo != null && m.HasProperty(propertyName)) - { - var offset = m.GetTextureOffset(propertyName); - var scale = m.GetTextureScale(propertyName); - (scale, offset) = TextureTransform.VerticalFlipScaleOffset(scale, offset); - - glTF_KHR_texture_transform.Serialize(textureInfo, (offset.x, offset.y), (scale.x, scale.y)); - } - } - - public static bool IsUnlit(string shaderName) - { - switch (shaderName) - { - case "Unlit/Color": - case "Unlit/Texture": - case "Unlit/Transparent": - case "Unlit/Transparent Cutout": - case UniUnlit.UniUnlitUtil.ShaderName: - return true; - - default: - return false; - } - } - - protected virtual glTFMaterial CreateMaterial(Material m) - { - switch (m.shader.name) - { - case "Unlit/Color": - return Export_UnlitColor(m); - - case "Unlit/Texture": - return Export_UnlitTexture(m); - - case "Unlit/Transparent": - return Export_UnlitTransparent(m); - - case "Unlit/Transparent Cutout": - return Export_UnlitCutout(m); - - case UniUnlit.UniUnlitUtil.ShaderName: - return Export_UniUnlit(m); - - default: - return Export_Standard(m); - } - } - - static glTFMaterial Export_UnlitColor(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = glTFBlendMode.OPAQUE.ToString(); - return material; - } - - static glTFMaterial Export_UnlitTexture(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = glTFBlendMode.OPAQUE.ToString(); - return material; - } - - static glTFMaterial Export_UnlitTransparent(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = glTFBlendMode.BLEND.ToString(); - return material; - } - - static glTFMaterial Export_UnlitCutout(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = glTFBlendMode.MASK.ToString(); - material.alphaCutoff = m.GetFloat("_Cutoff"); - return material; - } - - private glTFMaterial Export_UniUnlit(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - - var renderMode = UniUnlit.UniUnlitUtil.GetRenderMode(m); - if (renderMode == UniUnlitRenderMode.Opaque) - { - material.alphaMode = glTFBlendMode.OPAQUE.ToString(); - } - else if (renderMode == UniUnlitRenderMode.Transparent) - { - material.alphaMode = glTFBlendMode.BLEND.ToString(); - } - else if (renderMode == UniUnlitRenderMode.Cutout) - { - material.alphaMode = glTFBlendMode.MASK.ToString(); - material.alphaCutoff = m.GetFloat("_Cutoff"); - } - else - { - material.alphaMode = glTFBlendMode.OPAQUE.ToString(); - } - - var cullMode = UniUnlit.UniUnlitUtil.GetCullMode(m); - if (cullMode == UniUnlitCullMode.Off) - { - material.doubleSided = true; - } - else - { - material.doubleSided = false; - } - - return material; - } - - static glTFMaterial Export_Standard(Material m) - { - var material = new glTFMaterial - { - pbrMetallicRoughness = new glTFPbrMetallicRoughness(), - }; - - switch (m.GetTag("RenderType", true)) - { - case "Transparent": - material.alphaMode = glTFBlendMode.BLEND.ToString(); - break; - - case "TransparentCutout": - material.alphaMode = glTFBlendMode.MASK.ToString(); - material.alphaCutoff = m.GetFloat("_Cutoff"); - break; - - default: - material.alphaMode = glTFBlendMode.OPAQUE.ToString(); - break; - } - - return material; - } - } -} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs new file mode 100644 index 000000000..bcd2e3205 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs @@ -0,0 +1,9 @@ +namespace UniGLTF +{ + public enum glTFBlendMode + { + OPAQUE, + MASK, + BLEND + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs.meta new file mode 100644 index 000000000..1f2bab03c --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/glTFBlendMode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 59e2e94f37164b3c87324eea9ba98006 +timeCreated: 1667402917 \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs index 8adeef7e1..d34a0d9ac 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs @@ -48,7 +48,7 @@ namespace UniGLTF protected virtual IMaterialExporter CreateMaterialExporter() { - return new MaterialExporter(); + return new BuiltinRPGltfMaterialExporter(); } protected ITextureExporter TextureExporter => _textureExporter; diff --git a/Assets/VRM/Editor/Format/VRMMaterialValidator.cs b/Assets/VRM/Editor/Format/VRMMaterialValidator.cs index d6c792e65..327951034 100644 --- a/Assets/VRM/Editor/Format/VRMMaterialValidator.cs +++ b/Assets/VRM/Editor/Format/VRMMaterialValidator.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using UnityEngine; namespace VRM @@ -10,10 +11,9 @@ namespace VRM { public override string GetGltfMaterialTypeFromUnityShaderName(string shaderName) { - var name = VRMMaterialExporter.VrmMaterialName(shaderName); - if (!string.IsNullOrEmpty(name)) + if (BuiltinRPVrmMaterialExporter.SupportedShaderNames.Contains(shaderName)) { - return name; + return "VRM0X"; } return base.GetGltfMaterialTypeFromUnityShaderName(shaderName); } diff --git a/Assets/VRM/Runtime/IO/BuiltinRP.meta b/Assets/VRM/Runtime/IO/BuiltinRP.meta new file mode 100644 index 000000000..422403d0a --- /dev/null +++ b/Assets/VRM/Runtime/IO/BuiltinRP.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c0d00129f7e844259bb416832e692737 +timeCreated: 1667405900 \ No newline at end of file diff --git a/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs b/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs new file mode 100644 index 000000000..76f31c2dd --- /dev/null +++ b/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs @@ -0,0 +1,124 @@ +using System; +using MToon; +using UniGLTF; +using UnityEngine; +using VRMShaders; +using ColorSpace = VRMShaders.ColorSpace; +using RenderMode = MToon.RenderMode; + +namespace VRM +{ + /// + /// VRM/MToon のマテリアル情報をエクスポートする。 + /// ただし VRM 0.x としては VRM extension 内の materialProperties に記録されているデータが正である。 + /// したがって、ここで出力するデータはあくまで VRM を表示できない glTF ビューワでの見た目をある程度保証するために作成するものである。 + /// + public static class BuiltinRPVrmMToonMaterialExporter + { + public const string TargetShaderName = MToon.Utils.ShaderName; + + public static bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst) + { + if (src.shader.name != TargetShaderName) + { + dst = default; + return false; + } + + var srcProps = MToon.Utils.GetMToonParametersFromMaterial(src); + + dst = glTF_KHR_materials_unlit.CreateDefault(); + dst.name = src.name; + ExportRenderingSettings(srcProps, dst); + ExportBaseColor(src, srcProps, textureExporter, dst); + ExportEmission(src, srcProps, textureExporter, dst); + + return true; + } + + private static void ExportRenderingSettings(MToonDefinition src, glTFMaterial dst) + { + switch (src.Rendering.RenderMode) + { + case RenderMode.Opaque: + dst.alphaMode = glTFBlendMode.OPAQUE.ToString(); + break; + case RenderMode.Cutout: + dst.alphaMode = glTFBlendMode.MASK.ToString(); + dst.alphaCutoff = src.Color.CutoutThresholdValue; + break; + case RenderMode.Transparent: + dst.alphaMode = glTFBlendMode.BLEND.ToString(); + break; + case RenderMode.TransparentWithZWrite: + // NOTE: Ambiguous but better. + dst.alphaMode = glTFBlendMode.BLEND.ToString(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + switch (src.Rendering.CullMode) + { + case CullMode.Off: + dst.doubleSided = true; + break; + case CullMode.Front: + // NOTE: Ambiguous but better. + dst.doubleSided = true; + break; + case CullMode.Back: + dst.doubleSided = false; + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + private static void ExportBaseColor(Material srcMaterial, MToonDefinition src, ITextureExporter textureExporter, glTFMaterial dst) + { + dst.pbrMetallicRoughness.baseColorFactor = src.Color.LitColor.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); + + if (src.Color.LitMultiplyTexture != null) + { + var index = textureExporter.RegisterExportingAsSRgb(src.Color.LitMultiplyTexture, src.Rendering.RenderMode != RenderMode.Opaque); + if (index != -1) + { + dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo() + { + index = index, + }; + ExportMainTextureTransform(srcMaterial, dst.pbrMetallicRoughness.baseColorTexture); + } + } + } + + private static void ExportEmission(Material srcMaterial, MToonDefinition src, ITextureExporter textureExporter, glTFMaterial dst) + { + var emissionFactor = src.Emission.EmissionColor; + if (emissionFactor.maxColorComponent > 1) + { + emissionFactor /= emissionFactor.maxColorComponent; + } + dst.emissiveFactor = emissionFactor.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); + + if (src.Emission.EmissionMultiplyTexture != null) + { + var index = textureExporter.RegisterExportingAsSRgb(src.Emission.EmissionMultiplyTexture, needsAlpha: false); + if (index != -1) + { + dst.emissiveTexture = new glTFMaterialEmissiveTextureInfo() + { + index = index, + }; + ExportMainTextureTransform(srcMaterial, dst.emissiveTexture); + } + } + } + + private static void ExportMainTextureTransform(Material src, glTFTextureInfo targetTextureInfo) + { + MaterialExportUtils.ExportTextureTransform(src, targetTextureInfo, MToon.Utils.PropMainTex); + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs.meta b/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs.meta new file mode 100644 index 000000000..ae1c2c4fb --- /dev/null +++ b/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMToonMaterialExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1afab05a32ff435082b4ae879730886d +timeCreated: 1667405966 \ No newline at end of file diff --git a/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMaterialExporter.cs b/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMaterialExporter.cs new file mode 100644 index 000000000..94d5f543b --- /dev/null +++ b/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMaterialExporter.cs @@ -0,0 +1,44 @@ +using System; +using UniGLTF; +using UnityEngine; +using VRMShaders; + +namespace VRM +{ + public class BuiltinRPVrmMaterialExporter : BuiltinRPGltfMaterialExporter + { + public static readonly string[] SupportedShaderNames = + { + BuiltinRPVrmMToonMaterialExporter.TargetShaderName, + "VRM/UnlitTexture", + "VRM/UnlitTransparent", + "VRM/UnlitCutout", + "VRM/UnlitTransparentZWrite", + }; + + public override glTFMaterial ExportMaterial(Material src, ITextureExporter textureExporter, GltfExportSettings settings) + { + glTFMaterial dst = default; + switch (src.shader.name) + { + case BuiltinRPVrmMToonMaterialExporter.TargetShaderName: + if (BuiltinRPVrmMToonMaterialExporter.TryExportMaterial(src, textureExporter, out dst)) return dst; + break; + case "VRM/UnlitTexture": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(src, glTFBlendMode.OPAQUE, textureExporter, out dst)) return dst; + break; + case "VRM/UnlitTransparent": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(src, glTFBlendMode.BLEND, textureExporter, out dst)) return dst; + break; + case "VRM/UnlitCutout": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(src, glTFBlendMode.MASK, textureExporter, out dst)) return dst; + break; + case "VRM/UnlitTransparentZWrite": + if (BuiltinRPGenericUnlitMaterialExporter.TryExportMaterial(src, glTFBlendMode.BLEND, textureExporter, out dst)) return dst; + break; + } + + return base.ExportMaterial(src, textureExporter, settings); + } + } +} diff --git a/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs.meta b/Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMaterialExporter.cs.meta similarity index 100% rename from Assets/VRM/Runtime/IO/VRMMaterialExporter.cs.meta rename to Assets/VRM/Runtime/IO/BuiltinRP/BuiltinRPVrmMaterialExporter.cs.meta diff --git a/Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs b/Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs new file mode 100644 index 000000000..cb88ac420 --- /dev/null +++ b/Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs @@ -0,0 +1,130 @@ +using System; +using UniGLTF; +using UniGLTF.ShaderPropExporter; +using UnityEngine; +using VRMShaders; +using ColorSpace = VRMShaders.ColorSpace; + +namespace VRM +{ + /// + /// VRM/MToon のマテリアル情報をエクスポートする。 + /// VRM extension 内の materialProperties に記録するデータを用意する。 + /// + public static class VrmExtensionMaterialPropertyExporter + { + private static readonly string[] ExportingTags = + { + "RenderType", + // "Queue", + }; + + public static glTF_VRM_Material ExportMaterial(Material m, ITextureExporter textureExporter) + { + var material = new glTF_VRM_Material + { + name = m.name, + shader = m.shader.name, + renderQueue = m.renderQueue, + }; + + if (m.shader.name != MToon.Utils.ShaderName) + { + material.shader = glTF_VRM_Material.VRM_USE_GLTFSHADER; + return material; + } + + var prop = PreShaderPropExporter.GetPropsForMToon(); + if (prop == null) + { + throw new Exception("arienai"); + } + else + { + foreach (var keyword in m.shaderKeywords) + { + material.keywordMap.Add(keyword, m.IsKeywordEnabled(keyword)); + } + + // get properties + //material.SetProp(prop); + foreach (var kv in prop.Properties) + { + switch (kv.ShaderPropertyType) + { + case ShaderPropertyType.Color: + { + // No color conversion. Because color property is serialized to raw float array. + var value = m.GetColor(kv.Key).ToFloat4(ColorSpace.Linear, ColorSpace.Linear); + material.vectorProperties.Add(kv.Key, value); + } + break; + + case ShaderPropertyType.Range: + case ShaderPropertyType.Float: + { + var value = m.GetFloat(kv.Key); + material.floatProperties.Add(kv.Key, value); + } + break; + + case ShaderPropertyType.TexEnv: + { + var texture = m.GetTexture(kv.Key); + if (texture != null) + { + var value = -1; + var isNormalMap = kv.Key == "_BumpMap"; + if (isNormalMap) + { + value = textureExporter.RegisterExportingAsNormal(texture); + } + else + { + var needsAlpha = kv.Key == "_MainTex"; + value = textureExporter.RegisterExportingAsSRgb(texture, needsAlpha); + } + if (value == -1) + { + Debug.LogFormat("not found {0}", texture.name); + } + else + { + material.textureProperties.Add(kv.Key, value); + } + } + + // offset & scaling + var offset = m.GetTextureOffset(kv.Key); + var scaling = m.GetTextureScale(kv.Key); + material.vectorProperties.Add(kv.Key, + new float[] { offset.x, offset.y, scaling.x, scaling.y }); + } + break; + + case ShaderPropertyType.Vector: + { + var value = m.GetVector(kv.Key).ToArray(); + material.vectorProperties.Add(kv.Key, value); + } + break; + + default: + throw new NotImplementedException(); + } + } + } + + foreach (var tag in ExportingTags) + { + var value = m.GetTag(tag, false); + if (!String.IsNullOrEmpty(value)) + { + material.tagMap.Add(tag, value); + } + } + + return material; + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs.meta b/Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs.meta new file mode 100644 index 000000000..7b78bd17d --- /dev/null +++ b/Assets/VRM/Runtime/IO/BuiltinRP/VrmExtensionMaterialPropertyExporter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 656dd5e643384d7489070cc3759d2f45 +timeCreated: 1667405286 \ No newline at end of file diff --git a/Assets/VRM/Runtime/IO/VRMExporter.cs b/Assets/VRM/Runtime/IO/VRMExporter.cs index edcdde0ef..84c49855e 100644 --- a/Assets/VRM/Runtime/IO/VRMExporter.cs +++ b/Assets/VRM/Runtime/IO/VRMExporter.cs @@ -43,7 +43,7 @@ namespace VRM protected override IMaterialExporter CreateMaterialExporter() { - return new VRMMaterialExporter(); + return new BuiltinRPVrmMaterialExporter(); } public override void ExportExtensions(ITextureSerializer textureSerializer) @@ -216,7 +216,7 @@ namespace VRM // materials foreach (var m in Materials) { - VRM.materialProperties.Add(VRMMaterialExporter.CreateFromMaterial(m, TextureExporter)); + VRM.materialProperties.Add(VrmExtensionMaterialPropertyExporter.ExportMaterial(m, TextureExporter)); } // Serialize VRM diff --git a/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs b/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs deleted file mode 100644 index 5b7c9035b..000000000 --- a/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Linq; -using UniGLTF; -using UniGLTF.ShaderPropExporter; -using UnityEngine; -using VRMShaders; -using ColorSpace = VRMShaders.ColorSpace; - -namespace VRM -{ - public class VRMMaterialExporter : MaterialExporter - { - public static string VrmMaterialName(string shaderName) - { - switch (shaderName) - { - case "VRM/UnlitTexture": - case "VRM/UnlitTransparent": - case "VRM/UnlitCutout": - case "VRM/UnlitTransparentZWrite": - return "KHR_materials_unlit"; - - case "VRM/MToon": - return "MToon"; - - default: - return null; - } - } - - protected override glTFMaterial CreateMaterial(Material m) - { - switch (m.shader.name) - { - case "VRM/UnlitTexture": - return Export_VRMUnlitTexture(m); - - case "VRM/UnlitTransparent": - return Export_VRMUnlitTransparent(m); - - case "VRM/UnlitCutout": - return Export_VRMUnlitCutout(m); - - case "VRM/UnlitTransparentZWrite": - return Export_VRMUnlitTransparentZWrite(m); - - case "VRM/MToon": - return Export_VRMMToon(m); - - default: - return base.CreateMaterial(m); - } - } - - static glTFMaterial Export_VRMUnlitTexture(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = "OPAQUE"; - return material; - } - static glTFMaterial Export_VRMUnlitTransparent(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = "BLEND"; - return material; - } - static glTFMaterial Export_VRMUnlitCutout(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = "MASK"; - return material; - } - static glTFMaterial Export_VRMUnlitTransparentZWrite(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - material.alphaMode = "BLEND"; - return material; - } - - static glTFMaterial Export_VRMMToon(Material m) - { - var material = glTF_KHR_materials_unlit.CreateDefault(); - - switch (m.GetTag("RenderType", true)) - { - case "Transparent": - material.alphaMode = "BLEND"; - break; - - case "TransparentCutout": - material.alphaMode = "MASK"; - material.alphaCutoff = m.GetFloat("_Cutoff"); - break; - - default: - material.alphaMode = "OPAQUE"; - break; - } - - switch ((int)m.GetFloat("_CullMode")) - { - case 0: - material.doubleSided = true; - break; - - case 1: - Debug.LogWarning("ignore cull front"); - break; - - case 2: - // cull back - break; - - default: - throw new NotImplementedException(); - } - - return material; - } - - #region CreateFromMaterial - - static readonly string[] TAGS = new string[]{ - "RenderType", - // "Queue", - }; - - public static glTF_VRM_Material CreateFromMaterial(Material m, ITextureExporter textureExporter) - { - var material = new glTF_VRM_Material - { - name = m.name, - shader = m.shader.name, - renderQueue = m.renderQueue, - }; - - if (m.shader.name != MToon.Utils.ShaderName) - { - material.shader = glTF_VRM_Material.VRM_USE_GLTFSHADER; - return material; - } - - var prop = PreShaderPropExporter.GetPropsForMToon(); - if (prop == null) - { - throw new Exception("arienai"); - } - else - { - foreach (var keyword in m.shaderKeywords) - { - material.keywordMap.Add(keyword, m.IsKeywordEnabled(keyword)); - } - - // get properties - //material.SetProp(prop); - foreach (var kv in prop.Properties) - { - switch (kv.ShaderPropertyType) - { - case ShaderPropertyType.Color: - { - // No color conversion. Because color property is serialized to raw float array. - var value = m.GetColor(kv.Key).ToFloat4(ColorSpace.Linear, ColorSpace.Linear); - material.vectorProperties.Add(kv.Key, value); - } - break; - - case ShaderPropertyType.Range: - case ShaderPropertyType.Float: - { - var value = m.GetFloat(kv.Key); - material.floatProperties.Add(kv.Key, value); - } - break; - - case ShaderPropertyType.TexEnv: - { - var texture = m.GetTexture(kv.Key); - if (texture != null) - { - var value = -1; - var isNormalMap = kv.Key == "_BumpMap"; - if (isNormalMap) - { - value = textureExporter.RegisterExportingAsNormal(texture); - } - else - { - var needsAlpha = kv.Key == "_MainTex"; - value = textureExporter.RegisterExportingAsSRgb(texture, needsAlpha); - } - if (value == -1) - { - Debug.LogFormat("not found {0}", texture.name); - } - else - { - material.textureProperties.Add(kv.Key, value); - } - } - - // offset & scaling - var offset = m.GetTextureOffset(kv.Key); - var scaling = m.GetTextureScale(kv.Key); - material.vectorProperties.Add(kv.Key, - new float[] { offset.x, offset.y, scaling.x, scaling.y }); - } - break; - - case ShaderPropertyType.Vector: - { - var value = m.GetVector(kv.Key).ToArray(); - material.vectorProperties.Add(kv.Key, value); - } - break; - - default: - throw new NotImplementedException(); - } - } - } - - foreach (var tag in TAGS) - { - var value = m.GetTag(tag, false); - if (!String.IsNullOrEmpty(value)) - { - material.tagMap.Add(tag, value); - } - } - - return material; - } - #endregion - } -} diff --git a/Assets/VRM/Tests/MToonTest.cs b/Assets/VRM/Tests/MToonTest.cs index dd4eec418..fe8507788 100644 --- a/Assets/VRM/Tests/MToonTest.cs +++ b/Assets/VRM/Tests/MToonTest.cs @@ -28,8 +28,7 @@ namespace VRM srcMaterial.mainTextureOffset = offset; srcMaterial.mainTextureScale = scale; - var materialExporter = new VRMMaterialExporter(); - var vrmMaterial = VRMMaterialExporter.CreateFromMaterial(srcMaterial, textureExporter); + var vrmMaterial = VrmExtensionMaterialPropertyExporter.ExportMaterial(srcMaterial, textureExporter); Assert.AreEqual(vrmMaterial.vectorProperties["_MainTex"], new float[] { 0.3f, 0.2f, 0.5f, 0.6f }); var materialImporter = new VRMMaterialDescriptorGenerator(new glTF_VRM_extensions diff --git a/Assets/VRM/Tests/SampleTests/VRMMaterialTests.cs b/Assets/VRM/Tests/SampleTests/VRMMaterialTests.cs index e79f78d3a..58af76c8e 100644 --- a/Assets/VRM/Tests/SampleTests/VRMMaterialTests.cs +++ b/Assets/VRM/Tests/SampleTests/VRMMaterialTests.cs @@ -10,7 +10,7 @@ namespace VRM.Samples static UniGLTF.glTFMaterial ExportLoaded(string resourceName) { var material = Resources.Load(resourceName); - var exporter = new VRMMaterialExporter(); + var exporter = new BuiltinRPVrmMaterialExporter(); var textureExporter = new TextureExporter(new EditorTextureSerializer()); var exported = exporter.ExportMaterial(material, textureExporter, new GltfExportSettings()); diff --git a/Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs b/Assets/VRM10/Runtime/IO/BuiltinRPVrm10MaterialExporter.cs similarity index 86% rename from Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs rename to Assets/VRM10/Runtime/IO/BuiltinRPVrm10MaterialExporter.cs index afbd6078b..b2e599f9e 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs +++ b/Assets/VRM10/Runtime/IO/BuiltinRPVrm10MaterialExporter.cs @@ -4,7 +4,7 @@ using VRMShaders; namespace UniVRM10 { - public class Vrm10MaterialExporter : MaterialExporter + public class BuiltinRPVrm10MaterialExporter : BuiltinRPGltfMaterialExporter { public override glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings) { diff --git a/Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs.meta b/Assets/VRM10/Runtime/IO/BuiltinRPVrm10MaterialExporter.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/IO/Vrm10MaterialExporter.cs.meta rename to Assets/VRM10/Runtime/IO/BuiltinRPVrm10MaterialExporter.cs.meta diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 270966a4a..43287523f 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -158,7 +158,7 @@ namespace UniVRM10 static IEnumerable ExportMaterials(Model model, ITextureExporter textureExporter, GltfExportSettings settings) { - var materialExporter = new Vrm10MaterialExporter(); + var materialExporter = new BuiltinRPVrm10MaterialExporter(); foreach (Material material in model.Materials) { yield return materialExporter.ExportMaterial(material, textureExporter, settings);