using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEditor.SpeedTree.Importer;
namespace UnityEditor.Rendering.HighDefinition
{
///
/// SpeedTree 9 material upgrader for HDRP.
///
class HDSpeedTree9MaterialUpgrader : SpeedTree9MaterialUpgrader
{
private static class HDProperties
{
internal static readonly int ExtraMapKwToggleID = Shader.PropertyToID("_ExtraMapKwToggle");
internal static readonly int TwoSidedID = Shader.PropertyToID("_TwoSided");
internal static readonly int DoubleSidedEnableID = Shader.PropertyToID("_DoubleSidedEnable");
internal static readonly int CullModeID = Shader.PropertyToID("_CullMode");
internal static readonly int CullModeForwardID = Shader.PropertyToID("_CullModeForward");
internal static readonly int DiffusionProfileAssetID = Shader.PropertyToID("_Diffusion_Profile_Asset");
internal static readonly int DiffusionProfileID = Shader.PropertyToID("_Diffusion_Profile");
internal static readonly string WindShared = "_WIND_SHARED";
internal static readonly string WindBranch2 = "_WIND_BRANCH2";
internal static readonly string WindBranch1 = "_WIND_BRANCH1";
internal static readonly string WindRipple = "_WIND_RIPPLE";
internal static readonly string WindShimmer = "_WIND_SHIMMER";
// Should match HDRenderPipelineEditorResources.defaultDiffusionProfileSettingsList[foliageIdx].name
internal static readonly string DefaultDiffusionProfileName = "Foliage";
}
const int kMaterialUpgraderVersion = 1;
const int kCustomGUIVersion = 1;
[MaterialSettingsCallbackAttribute(kMaterialUpgraderVersion)]
private static void OnAssetPostProcessDelegate(GameObject mainObject)
{
if (IsCurrentPipelineHDRP())
{
SpeedTree9MaterialUpgrader.PostprocessSpeedTree9Materials(mainObject, HDSpeedTree9MaterialUpgrader.HDSpeedTree9MaterialFinalizer);
}
}
private static void HDSpeedTree9MaterialFinalizer(Material mat)
{
SetupHDPropertiesOnImport(mat);
SetDefaultDiffusionProfileIfNecessary(mat);
// Need to call this again after reconfiguring keyword toggles (like motion vectors).
HDShaderUtils.ResetMaterialKeywords(mat);
}
private static void SetupHDPropertiesOnImport(Material mat)
{
// Since _DoubleSidedEnable controls _CullMode in HD,
// disable it for billboard LOD.
float doubleSided = mat.GetInt(HDProperties.ExtraMapKwToggleID) > 0 ? 0.0f : 1.0f;
mat.SetFloat(HDProperties.DoubleSidedEnableID, doubleSided);
if (mat.HasFloat(HDProperties.TwoSidedID))
{
mat.SetFloat(HDProperties.CullModeID, mat.GetFloat(HDProperties.TwoSidedID));
mat.SetFloat(HDProperties.CullModeForwardID, mat.GetFloat(HDProperties.TwoSidedID));
}
bool windShared = mat.IsKeywordEnabled(HDProperties.WindShared);
bool windBranch2 = mat.IsKeywordEnabled(HDProperties.WindBranch2);
bool windBranch1 = mat.IsKeywordEnabled(HDProperties.WindBranch1);
bool windRipple = mat.IsKeywordEnabled(HDProperties.WindRipple);
bool windShimmer = mat.IsKeywordEnabled(HDProperties.WindShimmer);
// Trees render motion vectors only when wind enabled on the model
bool enableMotionVectorPass = windShared || windBranch2 || windBranch1 || windRipple || windShimmer;
mat.SetShaderPassEnabled(HDShaderPassNames.s_MotionVectorsStr, enableMotionVectorPass);
mat.SetInt(HDShaderPassNames.s_MotionVectorsStr, (enableMotionVectorPass) ? 1 : 0);
}
private static void SetDefaultDiffusionProfileIfNecessary(Material mat)
{
bool hasDiffusionProfile = mat.HasVector(HDProperties.DiffusionProfileAssetID);
bool hasDiffusionProfileID = mat.HasFloat(HDProperties.DiffusionProfileID);
if (!hasDiffusionProfile || !hasDiffusionProfileID)
return;
Vector4 profAsset = mat.GetVector(HDProperties.DiffusionProfileAssetID);
float profHash = mat.GetFloat(HDProperties.DiffusionProfileID);
// User already set values from the inspector.
if (profAsset != null && profAsset != Vector4.zero && profHash != 0)
return;
string matDiffProfile = HDUtils.ConvertVector4ToGUID(mat.GetVector(HDProperties.DiffusionProfileAssetID));
string guid = "";
uint diffusionProfileHash = 0;
var volumeProfileSettings = GraphicsSettings.GetRenderPipelineSettings();
if (volumeProfileSettings != null)
{
var diffusionProfiles = VolumeUtils.GetOrCreateDiffusionProfileList(volumeProfileSettings.volumeProfile).ToArray();
foreach (var diffusionProfileAsset in diffusionProfiles)
{
if (diffusionProfileAsset != null)
{
bool gotGuid = AssetDatabase.TryGetGUIDAndLocalFileIdentifier(diffusionProfileAsset, out guid, out var localID);
if (gotGuid && (diffusionProfileAsset.name.Equals(HDProperties.DefaultDiffusionProfileName) || guid.Equals(matDiffProfile)))
{
diffusionProfileHash = diffusionProfileAsset.profile.hash;
break;
}
}
}
}
if (diffusionProfileHash == 0)
{
// Use the first DiffusionProfileSettings as the default profile if nothing has been set by the user previously.
HDRenderPipelineEditorAssets editorAssets = GraphicsSettings.GetRenderPipelineSettings();
if (editorAssets != null && editorAssets.defaultDiffusionProfileSettingsList != null && editorAssets.defaultDiffusionProfileSettingsList.Length > 0)
{
DiffusionProfileSettings profielSettings = editorAssets.defaultDiffusionProfileSettingsList[0];
if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(profielSettings, out guid, out long localID))
{
diffusionProfileHash = profielSettings.profile.hash;
}
}
}
if (diffusionProfileHash != 0)
{
mat.SetVector(HDProperties.DiffusionProfileAssetID, HDUtils.ConvertGUIDToVector4(guid));
mat.SetFloat(HDProperties.DiffusionProfileID, HDShadowUtils.Asfloat(diffusionProfileHash));
}
}
private static bool IsCurrentPipelineHDRP()
{
return GraphicsSettings.currentRenderPipeline is HDRenderPipelineAsset;
}
[DiffuseProfileCallbackAttribute(kCustomGUIVersion)]
private static void OnGUIDiffuseProfile(ref SerializedProperty diffusionProfileAssetValue, ref SerializedProperty diffusionProfileHashValue)
{
string guid = HDUtils.ConvertVector4ToGUID(diffusionProfileAssetValue.vector4Value);
DiffusionProfileSettings diffusionProfile = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid));
EditorGUI.BeginChangeCheck();
diffusionProfile = (DiffusionProfileSettings)EditorGUILayout.ObjectField("Diffusion Profile", diffusionProfile, typeof(DiffusionProfileSettings), false);
if (EditorGUI.EndChangeCheck())
{
Vector4 newGuid = Vector4.zero;
uint hash = 0;
if (diffusionProfile != null)
{
guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(diffusionProfile));
newGuid = HDUtils.ConvertGUIDToVector4(guid);
hash = diffusionProfile.profile.hash;
}
diffusionProfileAssetValue.vector4Value = newGuid;
diffusionProfileHashValue.uintValue = hash;
}
}
}
}