From 76ec8e3f98077a375e5ca60d7925d991e18e5b46 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 31 Jul 2024 04:48:43 +0900 Subject: [PATCH] Implements URP/Lit material exporter --- .../Materials/UrpLitMaterialExporter.cs | 174 ++++++++++++++++-- .../URP/ShaderUtil/Lit/UrpLitContext.cs | 4 +- 2 files changed, 158 insertions(+), 20 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs index 54f34e7f3..98563c555 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/Export/Materials/UrpLitMaterialExporter.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using UnityEngine; +using UnityEngine.Rendering; namespace UniGLTF { @@ -34,13 +36,21 @@ namespace UniGLTF }; var context = new UrpLitContext(src); - if (!Validate(context, out var errorMessage)) + foreach (var validation in EnumerateValidation(context)) { - Debug.LogError(errorMessage, src); - throw new UniGLTFNotSupportedException(errorMessage); + if (!validation.CanExport) + { + Debug.LogError(validation.Message, src); + throw new UniGLTFNotSupportedException(validation.Message); + } } + ExportSurfaceSettings(context, dst, textureExporter); ExportBaseColor(context, dst, textureExporter); + ExportMetallicSmoothness(context, dst, textureExporter); + ExportOcclusion(context, dst, textureExporter); + ExportNormal(context, dst, textureExporter); + ExportEmission(context, dst, textureExporter); return true; } @@ -51,6 +61,20 @@ namespace UniGLTF } } + public static void ExportSurfaceSettings(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + dst.alphaMode = (context.SurfaceType, context.IsAlphaClipEnabled) switch + { + (UrpLitSurfaceType.Opaque, false) => glTFBlendMode.OPAQUE.ToString(), + (UrpLitSurfaceType.Opaque, true) => glTFBlendMode.MASK.ToString(), + (UrpLitSurfaceType.Transparent, false) => glTFBlendMode.BLEND.ToString(), + (UrpLitSurfaceType.Transparent, true) => glTFBlendMode.BLEND.ToString(), // NOTE: not supported in glTF + _ => throw new ArgumentOutOfRangeException() + }; + dst.alphaCutoff = context.Cutoff; + dst.doubleSided = context.CullMode != CullMode.Back; // NOTE: cull front not supported in glTF + } + public static void ExportBaseColor(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) { dst.pbrMetallicRoughness.baseColorFactor = context.BaseColorSrgb.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear); @@ -65,35 +89,147 @@ namespace UniGLTF index = index, texCoord = 0, }; - GltfMaterialExportUtils.ExportTextureTransform( - context.BaseTextureOffset, - context.BaseTextureScale, - dst.pbrMetallicRoughness.baseColorTexture - ); + ExportBaseTexTransform(context, dst.pbrMetallicRoughness.baseColorTexture); } } } - public static bool Validate(UrpLitContext context, out string errorMessage) + public static void ExportMetallicSmoothness(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) { - if (context.WorkflowType != UrpLitWorkflowType.Metallic) - { - errorMessage = "Specular workflow is not supported."; - return false; - } + // NOTE: maybe KHR_materials_specular + if (context.WorkflowType != UrpLitWorkflowType.Metallic) return; + // Metallic-Roughness + dst.pbrMetallicRoughness.metallicRoughnessTexture = null; + dst.pbrMetallicRoughness.metallicFactor = context.Metallic; + dst.pbrMetallicRoughness.roughnessFactor = 1.0f - context.Smoothness; + if (context.MetallicGlossMap != null) + { + var index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures( + context.MetallicGlossMap, + context.Smoothness, + context.OcclusionTexture + ); + if (index >= 0) + { + dst.pbrMetallicRoughness.metallicRoughnessTexture = new glTFMaterialMetallicRoughnessTextureInfo + { + index = index, + texCoord = 0, + }; + ExportBaseTexTransform(context, dst.pbrMetallicRoughness.metallicRoughnessTexture); + dst.pbrMetallicRoughness.metallicFactor = 1.0f; + dst.pbrMetallicRoughness.roughnessFactor = 1.0f; + } + } + } + + public void ExportOcclusion(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + if (context.WorkflowType != UrpLitWorkflowType.Metallic) return; + + // Occlusion if (context.OcclusionTexture != null) { - Debug.LogWarning("Occlusion texture is not supported."); + var index = textureExporter.RegisterExportingAsCombinedGltfPbrParameterTextureFromUnityStandardTextures( + context.MetallicGlossMap, + context.Smoothness, + context.OcclusionTexture + ); + if (index >= 0) + { + dst.occlusionTexture = new glTFMaterialOcclusionTextureInfo + { + index = index, + texCoord = 0, + strength = context.OcclusionStrength, + }; + ExportBaseTexTransform(context, dst.occlusionTexture); + } } + } - if (context.ParallaxTexture != null) + public void ExportNormal(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + if (context.BumpMap == null) return; + + var index = textureExporter.RegisterExportingAsNormal(context.BumpMap); + if (index >= 0) { - Debug.LogWarning("Parallax texture is not supported."); + dst.normalTexture = new glTFMaterialNormalTextureInfo + { + index = index, + texCoord = 0, + scale = context.BumpScale, + }; + ExportBaseTexTransform(context, dst.normalTexture); + } + } + + public void ExportEmission(UrpLitContext context, glTFMaterial dst, ITextureExporter textureExporter) + { + if (!context.IsEmissionEnabled) return; + + dst.emissiveFactor = context.EmissionColorLinear.ToFloat3(ColorSpace.Linear, ColorSpace.Linear); + if (context.EmissionTexture != null) + { + var index = textureExporter.RegisterExportingAsSRgb(context.EmissionTexture, true); + if (index >= 0) + { + dst.emissiveTexture = new glTFMaterialEmissiveTextureInfo + { + index = index, + texCoord = 0, + }; + ExportBaseTexTransform(context, dst.emissiveTexture); + } + } + } + + private static void ExportBaseTexTransform(UrpLitContext context, glTFTextureInfo dst) + { + GltfMaterialExportUtils.ExportTextureTransform( + context.BaseTextureOffset, + context.BaseTextureScale, + dst + ); + } + + public static IEnumerable EnumerateValidation(UrpLitContext context) + { + var validationContext = ValidationContext.Create(context.Material); + + // Surface Settings + if (context.WorkflowType != UrpLitWorkflowType.Metallic) yield return Error(ValidationMessage.WorkflowTypeNotSupported); + if (context.SurfaceType == UrpLitSurfaceType.Transparent && context.IsAlphaClipEnabled) yield return Warning(ValidationMessage.TransparentAlphaClipNotSupported); + if (context.CullMode == CullMode.Front) yield return Error(ValidationMessage.BackFaceRenderingNotSupported); + if (context.BlendMode == UrpLitBlendMode.Additive) yield return Error(ValidationMessage.AdditiveBlendModeNotSupported); + if (context.BlendMode == UrpLitBlendMode.Multiply) yield return Error(ValidationMessage.MultiplyBlendModeNotSupported); + + // Etc Textures + if (context.ParallaxTexture != null) yield return Warning(ValidationMessage.ParallaxTextureNotSupported); + + yield break; + + Validation Error(ValidationMessage message) + { + return Validation.Error(message.ToString(), validationContext); } - errorMessage = null; - return true; + Validation Warning(ValidationMessage message) + { + return Validation.Warning(message.ToString(), validationContext); + } + } + + public enum ValidationMessage + { + WorkflowTypeNotSupported, + TransparentAlphaClipNotSupported, + BackFaceRenderingNotSupported, + ParallaxTextureNotSupported, + AdditiveBlendModeNotSupported, + MultiplyBlendModeNotSupported, } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs index 574d90cb9..bc5fd3d7b 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitContext.cs @@ -63,6 +63,8 @@ namespace UniGLTF _mat = material; } + public Material Material => _mat; + /// /// これが有効な場合、Validate() 関数が呼ばれるべき場合でも自動的に呼ばれなくなります。 /// @@ -221,7 +223,7 @@ namespace UniGLTF } } - public Color EmissionLinear + public Color EmissionColorLinear { get => _mat.GetColor(EmissionColor); set => _mat.SetColor(EmissionColor, value);