diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporter.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporter.cs index f14ff3e0b..bb996f84e 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporter.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GlbScriptedImporter.cs @@ -12,7 +12,7 @@ namespace UniGLTF { public override void OnImportAsset(AssetImportContext ctx) { - Import(this, ctx, m_reverseAxis.ToAxes()); + Import(this, ctx, m_reverseAxis.ToAxes(), m_useURPMaterial); } } } diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporter.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporter.cs index 2ab443cd6..1a6df70c2 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporter.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporter.cs @@ -12,7 +12,7 @@ namespace UniGLTF { public override void OnImportAsset(AssetImportContext ctx) { - Import(this, ctx, m_reverseAxis.ToAxes()); + Import(this, ctx, m_reverseAxis.ToAxes(), m_useURPMaterial); } } } diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs index cbb75086e..9ce13fe48 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/GltfScriptedImporterBase.cs @@ -2,6 +2,7 @@ using UnityEngine; using UnityEditor; using System.Linq; using VRMShaders; +using UnityEngine.Rendering; #if UNITY_2020_2_OR_NEWER using UnityEditor.AssetImporters; #else @@ -19,13 +20,28 @@ namespace UniGLTF [SerializeField] public ScriptedImporterAxes m_reverseAxis = default; + [SerializeField] + public bool m_useURPMaterial; + + static IMaterialDescriptorGenerator GetMaterialGenerator(bool useURPMaterial) + { + if (useURPMaterial) + { + return new GltfURPMaterialDescriptorGenerator(); + } + else + { + return new GltfMaterialDescriptorGenerator(); + } + } + /// /// glb をパースして、UnityObject化、さらにAsset化する /// /// /// /// - protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis) + protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis, bool useURPMaterial) { #if VRM_DEVELOP Debug.Log("OnImportAsset to " + scriptedImporter.assetPath); @@ -46,7 +62,9 @@ namespace UniGLTF .Where(x => x.Value != null) .ToDictionary(kv => new SubAssetKey(kv.Value.GetType(), kv.Key.name), kv => kv.Value); - using (var loader = new ImporterContext(data, extractedObjects)) + IMaterialDescriptorGenerator materialGenerator = GetMaterialGenerator(useURPMaterial); + + using (var loader = new ImporterContext(data, extractedObjects, materialGenerator: materialGenerator)) { // Configure TextureImporter to Extracted Textures. foreach (var textureInfo in loader.TextureDescriptorGenerator.Get().GetEnumerable()) diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ZipArchivedGltfScriptedImporter.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ZipArchivedGltfScriptedImporter.cs index 668cbe3a2..719b1995a 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ZipArchivedGltfScriptedImporter.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ZipArchivedGltfScriptedImporter.cs @@ -14,7 +14,7 @@ namespace UniGLTF { public override void OnImportAsset(AssetImportContext ctx) { - Import(this, ctx, m_reverseAxis.ToAxes()); + Import(this, ctx, m_reverseAxis.ToAxes(), m_useURPMaterial); } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 814eac7b2..d9ed0dba9 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -22,11 +22,12 @@ namespace UniGLTF public ImporterContext( GltfData data, IReadOnlyDictionary externalObjectMap = null, - ITextureDeserializer textureDeserializer = null) + ITextureDeserializer textureDeserializer = null, + IMaterialDescriptorGenerator materialGenerator = null) { Data = data; TextureDescriptorGenerator = new GltfTextureDescriptorGenerator(Data); - MaterialDescriptorGenerator = new GltfMaterialDescriptorGenerator(); + MaterialDescriptorGenerator = materialGenerator ?? new GltfMaterialDescriptorGenerator(); ExternalObjectMap = externalObjectMap ?? new Dictionary(); textureDeserializer = textureDeserializer ?? new UnityTextureDeserializer(); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP.meta new file mode 100644 index 000000000..a716bc76f --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e25906189630c09469e8bdfcab01b754 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfPbrURPMaterialImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfPbrURPMaterialImporter.cs new file mode 100644 index 000000000..7276126c7 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfPbrURPMaterialImporter.cs @@ -0,0 +1,169 @@ +using UnityEngine; +using VRMShaders; +using ColorSpace = VRMShaders.ColorSpace; + +namespace UniGLTF +{ + /// + /// glTF PBR to URP Lit. + /// + /// see: https://github.com/Unity-Technologies/Graphics/blob/v7.5.3/com.unity.render-pipelines.universal/Editor/UniversalRenderPipelineMaterialUpgrader.cs#L354-L379 + /// + public static class GltfPbrURPMaterialImporter + { + public const string ShaderName = "Universal Render Pipeline/Lit"; + + private enum BlendMode + { + Opaque, + Cutout, + Fade, + Transparent + } + + public static bool TryCreateParam(GltfData data, int i, out MaterialDescriptor matDesc) + { + if (i < 0 || i >= data.GLTF.materials.Count) + { + matDesc = default; + return false; + } + + var src = data.GLTF.materials[i]; + matDesc = new MaterialDescriptor(GltfMaterialDescriptorGenerator.GetMaterialName(i, src), ShaderName); + + var standardTexDesc = default(TextureDescriptor); + if (src.pbrMetallicRoughness != null || src.occlusionTexture != null) + { + if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null) + { + SubAssetKey key; + (key, standardTexDesc) = GltfPbrTextureImporter.StandardTexture(data, src); + } + + if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4) + { + // from _Color ! + matDesc.Colors.Add("_BaseColor", + src.pbrMetallicRoughness.baseColorFactor.ToColor4(ColorSpace.Linear, ColorSpace.sRGB) + ); + } + + if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1) + { + var (key, textureParam) = GltfPbrTextureImporter.BaseColorTexture(data, src); + // from _MainTex ! + matDesc.TextureSlots.Add("_BaseMap", textureParam); + } + + if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) + { + matDesc.Actions.Add(material => material.EnableKeyword("_METALLICGLOSSMAP")); + matDesc.TextureSlots.Add("_MetallicGlossMap", standardTexDesc); + // Set 1.0f as hard-coded. See: https://github.com/dwango/UniVRM/issues/212. + matDesc.FloatValues.Add("_Metallic", 1.0f); + matDesc.FloatValues.Add("_GlossMapScale", 1.0f); + // default value is 0.5 ! + matDesc.FloatValues.Add("_Smoothness", 1.0f); + } + else + { + matDesc.FloatValues.Add("_Metallic", src.pbrMetallicRoughness.metallicFactor); + // from _Glossiness ! + matDesc.FloatValues.Add("_Smoothness", 1.0f - src.pbrMetallicRoughness.roughnessFactor); + } + } + + if (src.normalTexture != null && src.normalTexture.index != -1) + { + matDesc.Actions.Add(material => material.EnableKeyword("_NORMALMAP")); + var (key, textureParam) = GltfPbrTextureImporter.NormalTexture(data, src); + matDesc.TextureSlots.Add("_BumpMap", textureParam); + matDesc.FloatValues.Add("_BumpScale", src.normalTexture.scale); + } + + if (src.occlusionTexture != null && src.occlusionTexture.index != -1) + { + matDesc.TextureSlots.Add("_OcclusionMap", standardTexDesc); + matDesc.FloatValues.Add("_OcclusionStrength", src.occlusionTexture.strength); + } + + if (src.emissiveFactor != null + || (src.emissiveTexture != null && src.emissiveTexture.index != -1)) + { + matDesc.Actions.Add(material => + { + material.EnableKeyword("_EMISSION"); + material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack; + }); + + if (src.emissiveFactor != null && src.emissiveFactor.Length == 3) + { + var emissiveFactor = src.emissiveFactor.ToColor3(ColorSpace.Linear, ColorSpace.Linear); + if (UniGLTF.Extensions.VRMC_materials_hdr_emissiveMultiplier.GltfDeserializer.TryGet(src.extensions, + out UniGLTF.Extensions.VRMC_materials_hdr_emissiveMultiplier.VRMC_materials_hdr_emissiveMultiplier ex)) + { + emissiveFactor *= ex.EmissiveMultiplier.Value; + } + matDesc.Colors.Add("_EmissionColor", emissiveFactor); + } + + if (src.emissiveTexture != null && src.emissiveTexture.index != -1) + { + var (key, textureParam) = GltfPbrTextureImporter.EmissiveTexture(data, src); + matDesc.TextureSlots.Add("_EmissionMap", textureParam); + } + } + + matDesc.Actions.Add(material => + { + BlendMode blendMode = BlendMode.Opaque; + // https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980 + switch (src.alphaMode) + { + case "BLEND": + blendMode = BlendMode.Fade; + material.SetOverrideTag("RenderType", "Transparent"); + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetInt("_ZWrite", 0); + material.DisableKeyword("_ALPHATEST_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = 3000; + break; + + case "MASK": + blendMode = BlendMode.Cutout; + material.SetOverrideTag("RenderType", "TransparentCutout"); + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + material.SetInt("_ZWrite", 1); + material.SetFloat("_Cutoff", src.alphaCutoff); + material.EnableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = 2450; + + break; + + default: // OPAQUE + blendMode = BlendMode.Opaque; + material.SetOverrideTag("RenderType", ""); + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + material.SetInt("_ZWrite", 1); + material.DisableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = -1; + break; + } + + material.SetFloat("_Mode", (float)blendMode); + }); + + return true; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfPbrURPMaterialImporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfPbrURPMaterialImporter.cs.meta new file mode 100644 index 000000000..3a87eaf63 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfPbrURPMaterialImporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08a0ae763ee70ed45809fad80ffe8e78 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfURPMaterialDescriptorGenerator.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfURPMaterialDescriptorGenerator.cs new file mode 100644 index 000000000..479ad31cb --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfURPMaterialDescriptorGenerator.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using UnityEngine; +using VRMShaders; + + +namespace UniGLTF +{ + /// + /// GLTF の MaterialImporter + /// + public sealed class GltfURPMaterialDescriptorGenerator : IMaterialDescriptorGenerator + { + public MaterialDescriptor Get(GltfData data, int i) + { + if (!GltfUnlitMaterialImporter.TryCreateParam(data, i, out var param)) + { + if (!GltfPbrURPMaterialImporter.TryCreateParam(data, i, out param)) + { + // fallback +#if VRM_DEVELOP + Debug.LogWarning($"material: {i} out of range. fallback"); +#endif + return new MaterialDescriptor(GetMaterialName(i, null), GltfPbrMaterialImporter.ShaderName); + } + } + + return param; + } + + public static string GetMaterialName(int index, glTFMaterial src) + { + if (src != null && !string.IsNullOrEmpty(src.name)) + { + return src.name; + } + return $"material_{index:00}"; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfURPMaterialDescriptorGenerator.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfURPMaterialDescriptorGenerator.cs.meta new file mode 100644 index 000000000..ba39444e7 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/GltfURPMaterialDescriptorGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ae66bf5ee5e1cb44b7dc416727d3bc1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: