// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors // SPDX-License-Identifier: Apache-2.0 #if USING_URP using System; using GLTFast.Schema; #if UNITY_EDITOR using UnityEditor; #endif using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using Material = UnityEngine.Material; namespace GLTFast.Materials { public class UniversalRPMaterialGenerator : ShaderGraphMaterialGenerator { // Keywords const string k_TransmissionKeyword = "_TRANSMISSION"; static bool s_SupportsCameraOpaqueTexture; #if USING_URP_12_OR_NEWER #if UNITY_EDITOR /// Guid of the shader graph with clearcoat support const string k_MetallicClearcoatShaderGuid = "c18c97ae1ce021b4980c5d19a54f0d3c"; #endif /// Name of the shader graph with clearcoat support public const string MetallicClearcoatShader = "glTF-pbrMetallicRoughness-Clearcoat"; static bool s_MetallicClearcoatShaderQueried; static Shader s_MetallicClearcoatShader; #endif public UniversalRPMaterialGenerator(UniversalRenderPipelineAsset renderPipelineAsset) { s_SupportsCameraOpaqueTexture = renderPipelineAsset.supportsCameraOpaqueTexture; } #if USING_URP_12_OR_NEWER protected override void SetDoubleSided(MaterialBase gltfMaterial, Material material) { base.SetDoubleSided(gltfMaterial,material); material.SetFloat(MaterialProperty.Cull, (int)CullMode.Off); } protected override void SetAlphaModeMask(MaterialBase gltfMaterial, Material material) { base.SetAlphaModeMask(gltfMaterial, material); material.SetFloat(MaterialProperty.AlphaClip, 1); } protected override void SetShaderModeBlend(MaterialBase gltfMaterial, Material material) { material.SetOverrideTag(RenderTypeTag, TransparentRenderType); material.EnableKeyword(SurfaceTypeTransparentKeyword); material.EnableKeyword(DisableSsrTransparentKeyword); material.EnableKeyword(EnableFogOnTransparentKeyword); material.SetShaderPassEnabled(ShaderPassTransparentDepthPrepass, false); material.SetShaderPassEnabled(ShaderPassTransparentDepthPostpass, false); material.SetShaderPassEnabled(ShaderPassTransparentBackface, false); material.SetShaderPassEnabled(ShaderPassRayTracingPrepass, false); material.SetShaderPassEnabled(ShaderPassDepthOnlyPass, false); material.SetFloat(MaterialProperty.SrcBlend, (int) BlendMode.SrcAlpha);//5 material.SetFloat(MaterialProperty.DstBlend, (int)BlendMode.OneMinusSrcAlpha);//10 material.SetFloat(ZTestGBufferProperty, (int)CompareFunction.Equal); //3 material.SetFloat(AlphaDstBlendProperty, (int)BlendMode.OneMinusSrcAlpha);//10 material.SetFloat(MaterialProperty.Surface, 1); material.SetFloat(MaterialProperty.ZWrite, 0); } /// /// Picks the shader graph with clearcoat support, if any material feature requires it. /// /// Material features /// Shader capable of rendering the features protected override Shader GetMetallicShader(MetallicShaderFeatures features) { if ((features & MetallicShaderFeatures.ClearCoat) != 0) { if (!s_MetallicClearcoatShaderQueried) { #if UNITY_EDITOR s_MetallicClearcoatShader = LoadShaderByGuid(new GUID(k_MetallicClearcoatShaderGuid)); #else s_MetallicClearcoatShader = LoadShaderByName(MetallicClearcoatShader); #endif if (s_MetallicClearcoatShader == null) { // Fallback to regular shader graph s_MetallicClearcoatShader = base.GetMetallicShader(features); } s_MetallicClearcoatShaderQueried = true; } return s_MetallicClearcoatShader; } return base.GetMetallicShader(features); } #endif protected override ShaderMode? ApplyTransmissionShaderFeatures(MaterialBase gltfMaterial) { if (!s_SupportsCameraOpaqueTexture) { // Fall back to makeshift approximation via premultiply or blend return base.ApplyTransmissionShaderFeatures(gltfMaterial); } if (gltfMaterial?.Extensions?.KHR_materials_transmission != null && gltfMaterial.Extensions.KHR_materials_transmission.transmissionFactor > 0f) { return ShaderMode.Blend; } // No explicitly change in shader features return null; } protected override RenderQueue? ApplyTransmission( ref Color baseColorLinear, IGltfReadable gltf, Transmission transmission, Material material, RenderQueue? renderQueue ) { if (s_SupportsCameraOpaqueTexture) { if (transmission.transmissionFactor > 0f) { material.EnableKeyword(k_TransmissionKeyword); material.SetFloat(TransmissionFactorProperty, transmission.transmissionFactor); renderQueue = RenderQueue.Transparent; if (TrySetTexture( transmission.transmissionTexture, material, gltf, TransmissionTextureProperty // TransmissionTextureScaleTransformProperty, // TODO: add support in shader // TransmissionTextureRotationProperty, // TODO: add support in shader // TransmissionTextureUVChannelProperty // TODO: add support in shader )) { } } return renderQueue; } return base.ApplyTransmission( ref baseColorLinear, gltf, transmission, material, renderQueue ); } } } #endif // USING_URP