2021-09-09 20:42:29 -04:00

117 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
// Include material common properties names
using static UnityEngine.Rendering.HighDefinition.HDMaterialProperties;
namespace UnityEditor.Rendering.HighDefinition
{
// A Material can be authored from the shader graph or by hand. When written by hand we need to provide an inspector.
// Such a Material will share some properties between it various variant (shader graph variant or hand authored variant).
// HDShaderGUI is here to provide a support for setup material keyword and pass function. It will allow the GUI
// to setup the material properties needed for rendering when switching shaders on a material. For the GUI part
// of the material you must use Material UI Blocks, examples of doing so can be found in the classes UnlitGUI,
// LitGUI or LayeredLitGUI.
/// <summary>
/// Use this class to build your custom Shader GUI for HDRP.
/// You can use a class that inherits from HDShaderGUI in the Shader Graph Custom EditorGUI field.
/// </summary>
public abstract class HDShaderGUI : ShaderGUI
{
internal protected bool m_FirstFrame = true;
// The following set of functions are call by the ShaderGraph
// It will allow to display our common parameters + setup keyword correctly for them
/// <summary>
/// Sets up the keywords and passes for the material you pass in as a parameter.
/// </summary>
/// <param name="material">Target material.</param>
protected abstract void SetupMaterialKeywordsAndPass(Material material);
/// <summary>
/// Unity calls this function when you assign a new shader to the material.
/// </summary>
/// <param name="material">The current material.</param>
/// <param name="oldShader">The shader the material currently uses.</param>
/// <param name="newShader">The new shader to assign to the material.</param>
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
base.AssignNewShaderToMaterial(material, oldShader, newShader);
SetupMaterialKeywordsAndPass(material);
}
/// <summary>
/// Sets up the keywords and passes for the material. You must call this function after you change a property on a material to ensure it's validity.
/// </summary>
/// <param name="changed">GUI.changed is the usual value for this parameter. If this value is false, the function just exits.</param>
/// <param name="materials">The materials to perform the setup on.</param>
protected void ApplyKeywordsAndPassesIfNeeded(bool changed, Material[] materials)
{
// !!! HACK !!!
// When a user creates a new Material from the contextual menu, the material is created from the editor code and the appropriate shader is applied to it.
// This means that we never setup keywords and passes for a newly created material. The material is then in an invalid state.
// To work around this, as the material is automatically selected when created, we force an update of the keyword at the first "frame" of the editor.
// Apply material keywords and pass:
if (changed || m_FirstFrame)
{
m_FirstFrame = false;
foreach (var material in materials)
SetupMaterialKeywordsAndPass(material);
}
}
/// <summary>
/// Unity calls this function when it displays the GUI. This method is sealed so you cannot override it. To implement your custom GUI, use OnMaterialGUI instead.
/// </summary>
/// <param name="materialEditor">Material editor instance.</param>
/// <param name="props">The list of properties in the inspected material(s).</param>
public sealed override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
if (!(RenderPipelineManager.currentPipeline is HDRenderPipeline))
{
EditorGUILayout.HelpBox("Editing HDRP materials is only supported when an HDRP asset assigned in the graphic settings", MessageType.Warning);
}
else
{
OnMaterialGUI(materialEditor, props);
}
}
/// <summary>
/// Implement your custom GUI in this function. To display a UI similar to HDRP shaders, use a MaterialUIBlockList.
/// </summary>
/// <param name="materialEditor">The current material editor.</param>
/// <param name="props">The list of properties in the inspected material(s).</param>
protected abstract void OnMaterialGUI(MaterialEditor materialEditor, MaterialProperty[] props);
readonly static string[] floatPropertiesToSynchronize =
{
kUseSplitLighting,
};
/// <summary>
/// Synchronize a set of properties that Unity requires for Shader Graph materials to work correctly. This function is for Shader Graph only.
/// </summary>
/// <param name="material">The target material.</param>
protected static void SynchronizeShaderGraphProperties(Material material)
{
var defaultProperties = new Material(material.shader);
foreach (var floatToSync in floatPropertiesToSynchronize)
if (material.HasProperty(floatToSync))
material.SetFloat(floatToSync, defaultProperties.GetFloat(floatToSync));
CoreUtils.Destroy(defaultProperties);
defaultProperties = null;
}
}
}