add GltfURPMaterialDescriptorGenerator

This commit is contained in:
ousttrue
2021-08-31 18:55:53 +09:00
parent 916dbbab6c
commit e6450960d7
10 changed files with 264 additions and 7 deletions

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}
/// <summary>
/// glb をパースして、UnityObject化、さらにAsset化する
/// </summary>
/// <param name="scriptedImporter"></param>
/// <param name="context"></param>
/// <param name="reverseAxis"></param>
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())

View File

@@ -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);
}
}
}

View File

@@ -22,11 +22,12 @@ namespace UniGLTF
public ImporterContext(
GltfData data,
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> 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<SubAssetKey, UnityEngine.Object>();
textureDeserializer = textureDeserializer ?? new UnityTextureDeserializer();

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e25906189630c09469e8bdfcab01b754
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,169 @@
using UnityEngine;
using VRMShaders;
using ColorSpace = VRMShaders.ColorSpace;
namespace UniGLTF
{
/// <summary>
/// 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
/// </summary>
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08a0ae763ee70ed45809fad80ffe8e78
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using UnityEngine;
using VRMShaders;
namespace UniGLTF
{
/// <summary>
/// GLTF の MaterialImporter
/// </summary>
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}";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ae66bf5ee5e1cb44b7dc416727d3bc1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: