diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs new file mode 100644 index 000000000..2d09f28a5 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs @@ -0,0 +1,10 @@ +namespace UniGLTF +{ + public enum UrpLitBlendMode + { + Alpha = 0, + Premultiply = 1, + Additive = 2, + Multiply = 3, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs.meta new file mode 100644 index 000000000..81c0e8029 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/URP/ShaderUtil/Lit/UrpLitBlendMode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 307c409e09f74fed8caaaedfdf794ef9 +timeCreated: 1722351228 \ 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 2d07220d9..f34d7e7fc 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 @@ -1,8 +1,20 @@ -using UnityEngine; +using System; +using UnityEngine; using UnityEngine.Rendering; namespace UniGLTF { + /// + /// "Universal Render Pipeline/Lit" シェーダーのプロパティを操作するためのクラス + /// + /// glTF との読み書きに必要な機能だけ実装する + /// + /// 非対応項目 + /// - Detail Texture + /// - Specular Highlights Toggle + /// - Environment Reflections Toggle + /// - Sorting Priority + /// public sealed class UrpLitContext { private readonly Material _mat; @@ -10,6 +22,7 @@ namespace UniGLTF private static readonly int WorkflowMode = Shader.PropertyToID("_WorkflowMode"); private static readonly int Surface = Shader.PropertyToID("_Surface"); private static readonly int AlphaClip = Shader.PropertyToID("_AlphaClip"); + private static readonly int Blend = Shader.PropertyToID("_Blend"); private static readonly int Cull = Shader.PropertyToID("_Cull"); private static readonly int BaseColorProp = Shader.PropertyToID("_BaseColor"); private static readonly int BaseMap = Shader.PropertyToID("_BaseMap"); @@ -19,7 +32,7 @@ namespace UniGLTF private static readonly int ParallaxMap = Shader.PropertyToID("_ParallaxMap"); private static readonly int CutoffProp = Shader.PropertyToID("_Cutoff"); private static readonly int SmoothnessProp = Shader.PropertyToID("_Smoothness"); - private static readonly int SmoothnessTextureChannel = Shader.PropertyToID("_SmoothnessTextureChannel"); + private static readonly int SmoothnessTextureChannelProp = Shader.PropertyToID("_SmoothnessTextureChannel"); private static readonly int MetallicProp = Shader.PropertyToID("_Metallic"); private static readonly int MetallicGlossMapProp = Shader.PropertyToID("_MetallicGlossMap"); private static readonly int SpecColorProp = Shader.PropertyToID("_SpecColor"); @@ -27,6 +40,9 @@ namespace UniGLTF private static readonly int BumpScaleProp = Shader.PropertyToID("_BumpScale"); private static readonly int BumpMapProp = Shader.PropertyToID("_BumpMap"); private static readonly int EmissionEnabled = Shader.PropertyToID("_EmissionEnabled"); + private static readonly int ZWrite = Shader.PropertyToID("_ZWrite"); + private static readonly int SrcBlend = Shader.PropertyToID("_SrcBlend"); + private static readonly int DstBlend = Shader.PropertyToID("_DstBlend"); private static readonly string SpecularSetupKeyword = "_SPECULAR_SETUP"; private static readonly string MetallicSpecGlossMapKeyword = "_METALLICSPECGLOSSMAP"; @@ -36,6 +52,11 @@ namespace UniGLTF private static readonly string EmissionKeyword = "_EMISSION"; private static readonly string OcclusionMapKeyword = "_OCCLUSIONMAP"; private static readonly string ParallaxMapKeyword = "_PARALLAXMAP"; + private static readonly string AlphaTestOnKeyword = "_ALPHATEST_ON"; + private static readonly string AlphaPremultiplyOnKeyword = "_ALPHAPREMULTIPLY_ON"; + private static readonly string AlphaModulateOnKeyword = "_ALPHAMODULATE_ON"; + private static readonly int OcclusionStrengthProp = Shader.PropertyToID("_OcclusionStrength"); + private static readonly int ParallaxProp = Shader.PropertyToID("_Parallax"); public UrpLitContext(Material material) { @@ -48,12 +69,7 @@ namespace UniGLTF set { _mat.SetFloat(WorkflowMode, (float)value); - var isSpecularSetup = value == UrpLitWorkflowType.Specular; - _mat.SetKeyword(SpecularSetupKeyword, isSpecularSetup); - - var glossMapName = isSpecularSetup ? SpecGlossMapProp : MetallicGlossMapProp; - var hasGlossMap = _mat.GetTexture(glossMapName) != null; - _mat.SetKeyword(MetallicSpecGlossMapKeyword, hasGlossMap); + ValidateShaderKeywords(); } } @@ -63,20 +79,38 @@ namespace UniGLTF set { _mat.SetFloat(Surface, (float)value); - _mat.SetKeyword(SurfaceTypeTransparentKeyword, value != UrpLitSurfaceType.Opaque); + ValidateShaderKeywords(); } } - public bool AlphaClipping + public UrpLitBlendMode BlendMode + { + get => (UrpLitBlendMode)_mat.GetFloat(Blend); + set + { + _mat.SetFloat(Blend, (float)value); + ValidateShaderKeywords(); + } + } + + public bool IsAlphaClipEnabled { get => _mat.GetFloat(AlphaClip) >= 0.5f; - set => _mat.SetFloat(AlphaClip, value ? 1.0f : 0.0f); + set + { + _mat.SetFloat(AlphaClip, value ? 1.0f : 0.0f); + ValidateShaderKeywords(); + } } public CullMode CullMode { get => (CullMode)_mat.GetFloat(Cull); - set => _mat.SetFloat(Cull, (float)value); + set + { + _mat.SetFloat(Cull, (float)value); + _mat.doubleSidedGI = value != CullMode.Back; + } } public Color BaseColorSrgb @@ -88,16 +122,19 @@ namespace UniGLTF public Texture BaseTexture { get => _mat.GetTexture(BaseMap); + set => _mat.SetTexture(BaseMap, value); } public Vector2 BaseTextureOffset { get => _mat.GetTextureOffset(BaseMap); + set => _mat.SetTextureOffset(BaseMap, value); } public Vector2 BaseTextureScale { get => _mat.GetTextureScale(BaseMap); + set => _mat.SetTextureScale(BaseMap, value); } public float Cutoff @@ -112,15 +149,14 @@ namespace UniGLTF set => _mat.SetFloat(SmoothnessProp, value); } - public UrpLitSmoothnessMapChannel SmoothnessMapChannel + public UrpLitSmoothnessMapChannel SmoothnessTextureChannel { // NOTE: Float Prop 以外に条件があるので、Keyword から読み取った方が確実 get => _mat.IsKeywordEnabled(SmoothnessTextureAlbedoChannelAKeyword) ? UrpLitSmoothnessMapChannel.AlbedoAlpha : UrpLitSmoothnessMapChannel.SpecularMetallicAlpha; set { - _mat.SetFloat(SmoothnessTextureChannel, (float)value); - var isOpaque = SurfaceType == UrpLitSurfaceType.Opaque; - _mat.SetKeyword(SmoothnessTextureAlbedoChannelAKeyword, isOpaque && value == UrpLitSmoothnessMapChannel.AlbedoAlpha); + _mat.SetFloat(SmoothnessTextureChannelProp, (float)value); + ValidateShaderKeywords(); } } @@ -188,6 +224,12 @@ namespace UniGLTF get => _mat.GetTexture(EmissionMap); } + public float OcclusionStrength + { + get => _mat.GetFloat(OcclusionStrengthProp); + set => _mat.SetFloat(OcclusionStrengthProp, value); + } + public Texture OcclusionTexture { get => _mat.GetTexture(OcclusionMap); @@ -198,6 +240,12 @@ namespace UniGLTF } } + public float Parallax + { + get => _mat.GetFloat(ParallaxProp); + set => _mat.SetFloat(ParallaxProp, value); + } + public Texture ParallaxTexture { get => _mat.GetTexture(ParallaxMap); @@ -207,5 +255,72 @@ namespace UniGLTF _mat.SetKeyword(ParallaxMapKeyword, value != null); } } + + /// + /// 複数のプロパティに関連して設定されるキーワードを更新する。 + /// + public void ValidateShaderKeywords() + { + // Workflow + var workflowType = (UrpLitWorkflowType)_mat.GetFloat(WorkflowMode); + var isSpecularSetup = workflowType == UrpLitWorkflowType.Specular; + _mat.SetKeyword(SpecularSetupKeyword, isSpecularSetup); + + // GlossMap + var glossMapName = isSpecularSetup ? SpecGlossMapProp : MetallicGlossMapProp; + var hasGlossMap = _mat.GetTexture(glossMapName) != null; + _mat.SetKeyword(MetallicSpecGlossMapKeyword, hasGlossMap); + + // Surface Type + var surfaceType = (UrpLitSurfaceType)_mat.GetFloat(Surface); + _mat.SetKeyword(SurfaceTypeTransparentKeyword, surfaceType != UrpLitSurfaceType.Opaque); + + // Render Settings + var alphaClip = _mat.GetFloat(AlphaClip) >= 0.5f; + var blendMode = (UrpLitBlendMode)_mat.GetFloat(Blend); + var zWrite = surfaceType == UrpLitSurfaceType.Opaque; + _mat.SetKeyword(AlphaTestOnKeyword, alphaClip); + _mat.SetKeyword(AlphaPremultiplyOnKeyword, blendMode == UrpLitBlendMode.Premultiply); + _mat.SetKeyword(AlphaModulateOnKeyword, blendMode == UrpLitBlendMode.Additive); + _mat.SetFloat(ZWrite, zWrite ? 1.0f : 0.0f); + _mat.SetShaderPassEnabled("DepthOnly", zWrite); + _mat.SetFloat(SrcBlend, (surfaceType, blendMode) switch + { + (UrpLitSurfaceType.Opaque, _) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Alpha) => (float)UnityEngine.Rendering.BlendMode.SrcAlpha, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Premultiply) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Additive) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Multiply) => (float)UnityEngine.Rendering.BlendMode.DstColor, + _ => (float)UnityEngine.Rendering.BlendMode.One, + }); + _mat.SetFloat(DstBlend, (surfaceType, blendMode) switch + { + (UrpLitSurfaceType.Opaque, _) => (float)UnityEngine.Rendering.BlendMode.Zero, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Alpha) => (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Premultiply) => (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Additive) => (float)UnityEngine.Rendering.BlendMode.One, + (UrpLitSurfaceType.Transparent, UrpLitBlendMode.Multiply) => (float)UnityEngine.Rendering.BlendMode.Zero, + _ => (float) UnityEngine.Rendering.BlendMode.Zero, + }); + _mat.SetOverrideTag("RenderType", (surfaceType, alphaClip) switch + { + (UrpLitSurfaceType.Opaque, false) => "Opaque", + (UrpLitSurfaceType.Opaque, true) => "TransparentCutout", + (UrpLitSurfaceType.Transparent, _) => "Transparent", + _ => "Opaque", + }); + _mat.renderQueue = (surfaceType, alphaClip) switch + { + (UrpLitSurfaceType.Opaque, false) => (int)RenderQueue.Geometry, + (UrpLitSurfaceType.Opaque, true) => (int)RenderQueue.AlphaTest, + (UrpLitSurfaceType.Transparent, _) => (int)RenderQueue.Transparent, + _ => _mat.shader.renderQueue, + }; + + // SmoothnessTextureChannel + var isOpaque = surfaceType == UrpLitSurfaceType.Opaque; + var smoothnessMapChannel = (UrpLitSmoothnessMapChannel)_mat.GetFloat(SmoothnessTextureChannelProp); + _mat.SetKeyword(SmoothnessTextureAlbedoChannelAKeyword, isOpaque && smoothnessMapChannel == UrpLitSmoothnessMapChannel.AlbedoAlpha); + } } } \ No newline at end of file