mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-08-28 22:04:56 -05:00
Refactoring Material Exporters
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// 非対応のシェーダでも空のマテリアルを出力する.
|
||||
/// </summary>
|
||||
public static class BuiltinRPFallbackMaterialExporter
|
||||
{
|
||||
public static glTFMaterial ExportMaterial(Material src, ITextureExporter textureExporter)
|
||||
{
|
||||
var dst = new glTFMaterial
|
||||
{
|
||||
name = src.name,
|
||||
pbrMetallicRoughness = new glTFPbrMetallicRoughness(),
|
||||
};
|
||||
|
||||
return dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 983277a982364497b7491610ac4868f0
|
||||
timeCreated: 1667405705
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
using ColorSpace = VRMShaders.ColorSpace;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// Built-in RP で一般的に用いられる Unlit Shader をエクスポートすることを試みる。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c4ed66ba3f44b28a1d303cdf073dc2b
|
||||
timeCreated: 1667402621
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occlusion, Metallic, Roughness
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec789661012740afbe8b5422aadc5fa0
|
||||
timeCreated: 1667399599
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a8ebb5c42054bd7be905f2dcb595457
|
||||
timeCreated: 1667403411
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4bbc9904e5fe4176b74d39eeb2318bd6
|
||||
timeCreated: 1667400475
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occlusion, Metallic, Roughness
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <param name="textureExporter"></param>
|
||||
/// <param name="material"></param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace UniGLTF
|
||||
{
|
||||
public enum glTFBlendMode
|
||||
{
|
||||
OPAQUE,
|
||||
MASK,
|
||||
BLEND
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59e2e94f37164b3c87324eea9ba98006
|
||||
timeCreated: 1667402917
|
||||
@@ -48,7 +48,7 @@ namespace UniGLTF
|
||||
|
||||
protected virtual IMaterialExporter CreateMaterialExporter()
|
||||
{
|
||||
return new MaterialExporter();
|
||||
return new BuiltinRPGltfMaterialExporter();
|
||||
}
|
||||
|
||||
protected ITextureExporter TextureExporter => _textureExporter;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
3
Assets/VRM/Runtime/IO/BuiltinRP.meta
Normal file
3
Assets/VRM/Runtime/IO/BuiltinRP.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0d00129f7e844259bb416832e692737
|
||||
timeCreated: 1667405900
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using MToon;
|
||||
using UniGLTF;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
using ColorSpace = VRMShaders.ColorSpace;
|
||||
using RenderMode = MToon.RenderMode;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// VRM/MToon のマテリアル情報をエクスポートする。
|
||||
/// ただし VRM 0.x としては VRM extension 内の materialProperties に記録されているデータが正である。
|
||||
/// したがって、ここで出力するデータはあくまで VRM を表示できない glTF ビューワでの見た目をある程度保証するために作成するものである。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1afab05a32ff435082b4ae879730886d
|
||||
timeCreated: 1667405966
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using UniGLTF;
|
||||
using UniGLTF.ShaderPropExporter;
|
||||
using UnityEngine;
|
||||
using VRMShaders;
|
||||
using ColorSpace = VRMShaders.ColorSpace;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// VRM/MToon のマテリアル情報をエクスポートする。
|
||||
/// VRM extension 内の materialProperties に記録するデータを用意する。
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 656dd5e643384d7489070cc3759d2f45
|
||||
timeCreated: 1667405286
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace VRM.Samples
|
||||
static UniGLTF.glTFMaterial ExportLoaded(string resourceName)
|
||||
{
|
||||
var material = Resources.Load<Material>(resourceName);
|
||||
var exporter = new VRMMaterialExporter();
|
||||
var exporter = new BuiltinRPVrmMaterialExporter();
|
||||
var textureExporter = new TextureExporter(new EditorTextureSerializer());
|
||||
var exported = exporter.ExportMaterial(material, textureExporter, new GltfExportSettings());
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -158,7 +158,7 @@ namespace UniVRM10
|
||||
|
||||
static IEnumerable<glTFMaterial> 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);
|
||||
|
||||
Reference in New Issue
Block a user