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 BuiltInVrmMToonMaterialExporter { 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) { GltfMaterialExportUtils.ExportTextureTransform(src, targetTextureInfo, MToon.Utils.PropMainTex); } } }