using System;
using TriLibCore.General;
using TriLibCore.Utils;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace TriLibCore.Mappers
{
/// Represents a Material Mapper that converts TriLib Materials into Unity HDRP Materials.
[Serializable]
[CreateAssetMenu(menuName = "TriLib/Mappers/Material/HDRP Material Mapper", fileName = "HDRPMaterialMapper")]
#if UNITY_EDITOR
[InitializeOnLoad]
#endif
public class HDRPMaterialMapper : MaterialMapper
{
static HDRPMaterialMapper()
{
AddToRegisteredMappers();
}
[RuntimeInitializeOnLoadMethod]
private static void AddToRegisteredMappers()
{
if (RegisteredMappers.Contains("HDRPMaterialMapper"))
{
return;
}
RegisteredMappers.Add("HDRPMaterialMapper");
}
public override Material MaterialPreset => Resources.Load("Materials/HDRP/TriLibHDRP");
public override Material AlphaMaterialPreset => Resources.Load("Materials/HDRP/TriLibHDRPAlphaCutout");
public override Material AlphaMaterialPreset2 => Resources.Load("Materials/HDRP/TriLibHDRPAlpha");
public override Material SpecularMaterialPreset => Resources.Load("Materials/HDRP/TriLibHDRP");
public override Material SpecularAlphaMaterialPreset => Resources.Load("Materials/HDRP/TriLibHDRPAlphaCutout");
public override Material SpecularAlphaMaterialPreset2 => Resources.Load("Materials/HDRP/TriLibHDRPAlpha");
public override Material LoadingMaterial => Resources.Load("Materials/HDRP/TriLibHDRPLoading");
///
public override bool IsCompatible(MaterialMapperContext materialMapperContext)
{
return GraphicsSettingsUtils.IsUsingHDRPPipeline;
}
///
public override void Map(MaterialMapperContext materialMapperContext)
{
materialMapperContext.VirtualMaterial = new HDRPVirtualMaterial();
CheckDiffuseMapTexture(materialMapperContext);
}
private void CheckDiffuseMapTexture(MaterialMapperContext materialMapperContext)
{
var diffuseTexturePropertyName = materialMapperContext.Material.GetGenericPropertyName(GenericMaterialProperty.DiffuseTexture);
if (materialMapperContext.Material.HasProperty(diffuseTexturePropertyName))
{
LoadTexture(materialMapperContext, TextureType.Diffuse, materialMapperContext.Material.GetTextureValue(diffuseTexturePropertyName), ApplyDiffuseMapTexture);
}
else
{
ApplyDiffuseMapTexture(materialMapperContext, TextureType.Diffuse, null);
}
}
private void ApplyDiffuseMapTexture(MaterialMapperContext materialMapperContext, TextureType textureType, Texture texture)
{
materialMapperContext.VirtualMaterial.SetProperty("_BaseColorMap", texture);
CheckGlossinessValue(materialMapperContext);
}
private void CheckGlossinessValue(MaterialMapperContext materialMapperContext)
{
var value = materialMapperContext.Material.GetGenericPropertyValueMultiplied(GenericMaterialProperty.Glossiness, materialMapperContext.Material.GetGenericFloatValue(GenericMaterialProperty.Glossiness));
materialMapperContext.VirtualMaterial.SetProperty("_Smoothness", value);
CheckMetallicValue(materialMapperContext);
}
private void CheckMetallicValue(MaterialMapperContext materialMapperContext)
{
var value = materialMapperContext.Material.GetGenericFloatValue(GenericMaterialProperty.Metallic);
materialMapperContext.VirtualMaterial.SetProperty("_Metallic", value);
CheckEmissionMapTexture(materialMapperContext);
}
private void CheckEmissionMapTexture(MaterialMapperContext materialMapperContext)
{
var emissionTexturePropertyName = materialMapperContext.Material.GetGenericPropertyName(GenericMaterialProperty.EmissionTexture);
if (materialMapperContext.Material.HasProperty(emissionTexturePropertyName))
{
LoadTexture(materialMapperContext, TextureType.Emission, materialMapperContext.Material.GetTextureValue(emissionTexturePropertyName), ApplyEmissionMapTexture);
}
else
{
ApplyEmissionMapTexture(materialMapperContext, TextureType.Emission, null);
}
}
private void ApplyEmissionMapTexture(MaterialMapperContext materialMapperContext, TextureType textureType, Texture texture)
{
materialMapperContext.VirtualMaterial.SetProperty("_EmissiveColorMap", texture);
if (texture)
{
materialMapperContext.VirtualMaterial.EnableKeyword("_EMISSIVE_COLOR_MAP");
materialMapperContext.VirtualMaterial.GlobalIlluminationFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive;
materialMapperContext.VirtualMaterial.SetProperty("_EmissiveIntensity", materialMapperContext.Material.GetGenericPropertyValueMultiplied(GenericMaterialProperty.EmissionColor, 1f));
}
else
{
materialMapperContext.VirtualMaterial.DisableKeyword("_EMISSIVE_COLOR_MAP");
materialMapperContext.VirtualMaterial.GlobalIlluminationFlags = MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
CheckNormalMapTexture(materialMapperContext);
}
private void CheckNormalMapTexture(MaterialMapperContext materialMapperContext)
{
var normalMapTexturePropertyName = materialMapperContext.Material.GetGenericPropertyName(GenericMaterialProperty.NormalTexture);
if (materialMapperContext.Material.HasProperty(normalMapTexturePropertyName))
{
LoadTexture(materialMapperContext, TextureType.NormalMap, materialMapperContext.Material.GetTextureValue(normalMapTexturePropertyName), ApplyNormalMapTexture);
}
else
{
ApplyNormalMapTexture(materialMapperContext, TextureType.NormalMap, null);
}
}
private void ApplyNormalMapTexture(MaterialMapperContext materialMapperContext, TextureType textureType, Texture texture)
{
materialMapperContext.VirtualMaterial.SetProperty("_NormalMap", texture);
if (texture != null)
{
materialMapperContext.VirtualMaterial.EnableKeyword("_NORMALMAP");
materialMapperContext.VirtualMaterial.EnableKeyword("_NORMALMAP_TANGENT_SPACE");
materialMapperContext.VirtualMaterial.SetProperty("_NormalScale", materialMapperContext.Material.GetGenericPropertyValueMultiplied(GenericMaterialProperty.NormalTexture, 1f));
}
else
{
materialMapperContext.VirtualMaterial.DisableKeyword("_NORMALMAP");
materialMapperContext.VirtualMaterial.DisableKeyword("_NORMALMAP_TANGENT_SPACE");
}
CheckSpecularTexture(materialMapperContext);
}
private void CheckSpecularTexture(MaterialMapperContext materialMapperContext)
{
var specularTexturePropertyName = materialMapperContext.Material.GetGenericPropertyName(GenericMaterialProperty.SpecularTexture);
if (materialMapperContext.Material.HasProperty(specularTexturePropertyName))
{
LoadTexture(materialMapperContext, TextureType.Specular, materialMapperContext.Material.GetTextureValue(specularTexturePropertyName), ApplySpecGlossMapTexture);
}
else
{
ApplySpecGlossMapTexture(materialMapperContext, TextureType.Specular, null);
}
}
private void ApplySpecGlossMapTexture(MaterialMapperContext materialMapperContext, TextureType textureType, Texture texture)
{
((HDRPVirtualMaterial)materialMapperContext.VirtualMaterial).SmoothnessTexture = texture;
CheckOcclusionMapTexture(materialMapperContext);
}
private void CheckOcclusionMapTexture(MaterialMapperContext materialMapperContext)
{
var occlusionMapTextureName = materialMapperContext.Material.GetGenericPropertyName(GenericMaterialProperty.OcclusionTexture);
if (materialMapperContext.Material.HasProperty(occlusionMapTextureName))
{
LoadTexture(materialMapperContext, TextureType.Occlusion, materialMapperContext.Material.GetTextureValue(occlusionMapTextureName), ApplyOcclusionMapTexture);
}
else
{
ApplyOcclusionMapTexture(materialMapperContext, TextureType.Occlusion, null);
}
}
private void ApplyOcclusionMapTexture(MaterialMapperContext materialMapperContext, TextureType textureType, Texture texture)
{
((HDRPVirtualMaterial)materialMapperContext.VirtualMaterial).OcclusionTexture = texture;
CheckParallaxMapTexture(materialMapperContext);
}
private void CheckParallaxMapTexture(MaterialMapperContext materialMapperContext)
{
var parallaxMapTextureName = materialMapperContext.Material.GetGenericPropertyName(GenericMaterialProperty.ParallaxMap);
if (materialMapperContext.Material.HasProperty(parallaxMapTextureName))
{
LoadTexture(materialMapperContext, TextureType.Parallax, materialMapperContext.Material.GetTextureValue(parallaxMapTextureName), ApplyParallaxMapTexture);
}
else
{
ApplyParallaxMapTexture(materialMapperContext, TextureType.Parallax, null);
}
}
private void ApplyParallaxMapTexture(MaterialMapperContext materialMapperContext, TextureType textureType, Texture texture)
{
CheckMetallicGlossMapTexture(materialMapperContext);
}
private void CheckMetallicGlossMapTexture(MaterialMapperContext materialMapperContext)
{
var metallicGlossMapTextureName = materialMapperContext.Material.GetGenericPropertyName(GenericMaterialProperty.MetallicGlossMap);
if (materialMapperContext.Material.HasProperty(metallicGlossMapTextureName))
{
LoadTexture(materialMapperContext, TextureType.Metalness, materialMapperContext.Material.GetTextureValue(metallicGlossMapTextureName), ApplyMetallicGlossMapTexture);
}
else
{
ApplyMetallicGlossMapTexture(materialMapperContext, TextureType.Metalness, null);
}
}
private void ApplyMetallicGlossMapTexture(MaterialMapperContext materialMapperContext, TextureType textureType, Texture texture)
{
((HDRPVirtualMaterial)materialMapperContext.VirtualMaterial).MetallicTexture = texture;
CheckEmissionColor(materialMapperContext);
}
private void CheckEmissionColor(MaterialMapperContext materialMapperContext)
{
var value = materialMapperContext.Material.GetGenericColorValue(GenericMaterialProperty.EmissionColor);
materialMapperContext.VirtualMaterial.SetProperty("_EmissiveColor", value);
if (value != Color.black)
{
materialMapperContext.VirtualMaterial.GlobalIlluminationFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive;
materialMapperContext.VirtualMaterial.SetProperty("_EmissiveIntensity", materialMapperContext.Material.GetGenericPropertyValueMultiplied(GenericMaterialProperty.EmissionColor, 1f));
}
else
{
materialMapperContext.VirtualMaterial.GlobalIlluminationFlags = MaterialGlobalIlluminationFlags.EmissiveIsBlack;
}
CheckDiffuseColor(materialMapperContext);
}
private void CheckDiffuseColor(MaterialMapperContext materialMapperContext)
{
var value = materialMapperContext.Material.GetGenericColorValue(GenericMaterialProperty.DiffuseColor) * materialMapperContext.Material.GetGenericPropertyValueMultiplied(GenericMaterialProperty.DiffuseColor, 1f);
value.a *= materialMapperContext.Material.GetGenericFloatValue(GenericMaterialProperty.AlphaValue);
if (!materialMapperContext.VirtualMaterial.HasAlpha && value.a < 1f)
{
materialMapperContext.VirtualMaterial.HasAlpha = true;
}
materialMapperContext.VirtualMaterial.SetProperty("_BaseColor", value);
BuildMaterial(materialMapperContext);
BuildHDRPMask(materialMapperContext);
}
private void BuildHDRPMask(MaterialMapperContext materialMapperContext)
{
if (materialMapperContext.UnityMaterial == null)
{
return;
}
var hdrpVirtualMaterial = (HDRPVirtualMaterial)materialMapperContext.VirtualMaterial;
var maskBaseTexture = hdrpVirtualMaterial.MetallicTexture ?? hdrpVirtualMaterial.OcclusionTexture ?? hdrpVirtualMaterial.DetailMaskTexture ?? hdrpVirtualMaterial.SmoothnessTexture;
if (maskBaseTexture == null)
{
materialMapperContext.UnityMaterial.DisableKeyword("_MASKMAP");
return;
}
var material = new Material(Shader.Find("Hidden/TriLib/BuildHDRPMask"));
material.SetTexture("_MetallicTex", hdrpVirtualMaterial.MetallicTexture);
material.SetTexture("_OcclusionTex", hdrpVirtualMaterial.OcclusionTexture);
material.SetTexture("_DetailMaskTex", hdrpVirtualMaterial.DetailMaskTexture);
material.SetTexture("_SmoothnessTex", hdrpVirtualMaterial.SmoothnessTexture);
var graphicsFormat = materialMapperContext.Context.Options.Enforce16BitsTextures ? GraphicsFormat.R16G16B16A16_SFloat : GraphicsFormat.R8G8B8A8_SRGB;
var renderTexture = RenderTexture.GetTemporary(maskBaseTexture.width, maskBaseTexture.height, 0, graphicsFormat);
renderTexture.useMipMap = true;
renderTexture.autoGenerateMips = false;
Graphics.Blit(null, renderTexture, material);
var texture2D = new Texture2D(
maskBaseTexture.width,
maskBaseTexture.height,
graphicsFormat,
materialMapperContext.Context.Options.GenerateMipmaps ? TextureCreationFlags.MipChain : TextureCreationFlags.None)
{
name = "Mask"
};
Graphics.CopyTexture(renderTexture, texture2D);
materialMapperContext.UnityMaterial.EnableKeyword("_MASKMAP");
materialMapperContext.UnityMaterial.SetTexture("_MaskMap", texture2D);
materialMapperContext.Context.Allocations.Add(texture2D);
Graphics.SetRenderTarget(null);
renderTexture.Release();
if (Application.isPlaying)
{
Destroy(material);
}
else
{
DestroyImmediate(material);
}
}
}
}