You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
8.0 KiB
199 lines
8.0 KiB
using System; |
|
using UnityEditor.ShaderGraph; |
|
using UnityEngine; |
|
using UnityEngine.Rendering; |
|
using UnityEngine.Rendering.Universal; |
|
using UnityEngine.Rendering.Universal.Internal; |
|
|
|
namespace UnityEditor.Rendering.Universal |
|
{ |
|
/// <summary> |
|
/// Scope that indicates start of <see cref="DecalProjector"/> GUI. |
|
/// </summary> |
|
internal class DecalProjectorScope : GUI.Scope |
|
{ |
|
public DecalProjectorScope() |
|
{ |
|
DecalShaderGraphGUI.isDecalProjectorGUI = true; |
|
} |
|
|
|
protected override void CloseScope() |
|
{ |
|
DecalShaderGraphGUI.isDecalProjectorGUI = false; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Represents the GUI for Decal Shader Graph materials. |
|
/// </summary> |
|
internal class DecalShaderGraphGUI : UnityEditor.ShaderGUI |
|
{ |
|
internal class Styles |
|
{ |
|
public static GUIContent inputs = new GUIContent("Inputs"); |
|
public static GUIContent advancedOptions = new GUIContent("Advanced Options"); |
|
|
|
public static GUIContent meshDecalBiasType = new GUIContent("Mesh Bias Type", "Set the type of bias that is applied to the mesh decal. Depth Bias applies a bias to the final depth value, while View bias applies a world space bias (in meters) alongside the view vector."); |
|
public static GUIContent meshDecalDepthBiasText = new GUIContent("Depth Bias", "Sets a depth bias to stop the decal's Mesh from overlapping with other Meshes."); |
|
public static GUIContent meshDecalViewBiasText = new GUIContent("View Bias", "Sets a world-space bias alongside the view vector to stop the decal's Mesh from overlapping with other Meshes. The unit is meters."); |
|
public static GUIContent drawOrderText = new GUIContent("Priority", "Controls the draw order of Decal Projectors. URP draws decals with lower values first."); |
|
} |
|
|
|
protected enum Expandable |
|
{ |
|
Inputs = 1 << 0, |
|
Advanced = 1 << 1, |
|
} |
|
|
|
public static bool isDecalProjectorGUI { get; set; } |
|
|
|
const string kDecalMeshBiasType = "_DecalMeshBiasType"; |
|
const string kDecalMeshDepthBias = "_DecalMeshDepthBias"; |
|
const string kDecalViewDepthBias = "_DecalMeshViewBias"; |
|
const string kDrawOrder = "_DrawOrder"; |
|
|
|
readonly MaterialHeaderScopeList m_MaterialScopeList = new MaterialHeaderScopeList(uint.MaxValue & ~((uint)Expandable.Advanced)); |
|
|
|
MaterialEditor m_MaterialEditor; |
|
MaterialProperty[] m_Properties; |
|
|
|
MaterialProperty decalMeshBiasType; |
|
MaterialProperty decalMeshDepthBias; |
|
MaterialProperty decalMeshViewBias; |
|
MaterialProperty drawOrder; |
|
|
|
public DecalShaderGraphGUI() |
|
{ |
|
m_MaterialScopeList.RegisterHeaderScope(Styles.inputs, Expandable.Inputs, DrawExposedProperties); |
|
m_MaterialScopeList.RegisterHeaderScope(Styles.advancedOptions, Expandable.Advanced, DrawSortingProperties); |
|
} |
|
|
|
/// <summary> |
|
/// Override this function to implement your custom GUI. To display a user interface similar to HDRP shaders, use a MaterialUIBlockList. |
|
/// </summary> |
|
/// <param name="materialEditor">The current material editor.</param> |
|
/// <param name="props">The list of properties the material has.</param> |
|
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) |
|
{ |
|
DecalMeshWarning(); |
|
|
|
m_MaterialEditor = materialEditor; |
|
FindProperties(props); |
|
|
|
Material material = materialEditor.target as Material; |
|
|
|
using (var changed = new EditorGUI.ChangeCheckScope()) |
|
{ |
|
m_MaterialScopeList.DrawHeaders(materialEditor, material); |
|
} |
|
|
|
// We should always do this call at the end |
|
materialEditor.serializedObject.ApplyModifiedProperties(); |
|
} |
|
|
|
private void FindProperties(MaterialProperty[] properties) |
|
{ |
|
decalMeshBiasType = FindProperty(kDecalMeshBiasType, properties); |
|
decalMeshViewBias = FindProperty(kDecalViewDepthBias, properties); |
|
decalMeshDepthBias = FindProperty(kDecalMeshDepthBias, properties); |
|
drawOrder = FindProperty(kDrawOrder, properties); |
|
|
|
m_Properties = properties; |
|
} |
|
|
|
private void DrawExposedProperties(Material material) |
|
{ |
|
MaterialProperty[] properties = m_Properties; |
|
MaterialEditor materialEditor = m_MaterialEditor; |
|
|
|
// TODO: scope |
|
var fieldWidth = EditorGUIUtility.fieldWidth; |
|
var labelWidth = EditorGUIUtility.labelWidth; |
|
|
|
// Copy of MaterialEditor.PropertiesDefaultGUI that excludes properties of PerRendererData |
|
materialEditor.SetDefaultGUIWidths(); |
|
for (var i = 0; i < properties.Length; i++) |
|
{ |
|
if ((properties[i].flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) != 0) |
|
continue; |
|
|
|
float h = materialEditor.GetPropertyHeight(properties[i], properties[i].displayName); |
|
Rect r = EditorGUILayout.GetControlRect(true, h, EditorStyles.layerMaskField); |
|
|
|
materialEditor.ShaderProperty(r, properties[i], properties[i].displayName); |
|
} |
|
|
|
EditorGUIUtility.fieldWidth = fieldWidth; |
|
EditorGUIUtility.labelWidth = labelWidth; |
|
} |
|
|
|
private void DrawSortingProperties(Material material) |
|
{ |
|
MaterialEditor materialEditor = m_MaterialEditor; |
|
|
|
materialEditor.EnableInstancingField(); |
|
DrawOrder(); |
|
materialEditor.ShaderProperty(decalMeshBiasType, Styles.meshDecalBiasType); |
|
|
|
DecalMeshDepthBiasType decalBias = (DecalMeshDepthBiasType)decalMeshBiasType.floatValue; |
|
EditorGUI.indentLevel++; |
|
switch (decalBias) |
|
{ |
|
case DecalMeshDepthBiasType.DepthBias: |
|
materialEditor.ShaderProperty(decalMeshDepthBias, Styles.meshDecalDepthBiasText); |
|
break; |
|
case DecalMeshDepthBiasType.ViewBias: |
|
materialEditor.ShaderProperty(decalMeshViewBias, Styles.meshDecalViewBiasText); |
|
break; |
|
} |
|
EditorGUI.indentLevel--; |
|
} |
|
|
|
private void DrawOrder() |
|
{ |
|
MaterialEditor materialEditor = m_MaterialEditor; |
|
|
|
EditorGUI.BeginChangeCheck(); |
|
EditorGUI.showMixedValue = drawOrder.hasMixedValue; |
|
var queue = EditorGUILayout.IntSlider(Styles.drawOrderText, (int)drawOrder.floatValue, -50, 50); |
|
if (EditorGUI.EndChangeCheck()) |
|
{ |
|
foreach (var target in materialEditor.targets) |
|
{ |
|
var material = target as Material; |
|
material.renderQueue = 2000 + queue; |
|
} |
|
drawOrder.floatValue = queue; |
|
} |
|
EditorGUI.showMixedValue = false; |
|
} |
|
|
|
private void DecalMeshWarning() |
|
{ |
|
if (isDecalProjectorGUI) |
|
return; |
|
|
|
var urp = UniversalRenderPipeline.asset; |
|
if (urp == null) |
|
return; |
|
|
|
bool hasDecalScreenSpace = false; |
|
var renderers = urp.m_RendererDataList; |
|
foreach (var renderer in renderers) |
|
{ |
|
if (renderer.TryGetRendererFeature(out DecalRendererFeature decalRendererFeature)) |
|
{ |
|
var technique = decalRendererFeature.GetTechnique(renderer); |
|
if (technique == DecalTechnique.ScreenSpace || technique == DecalTechnique.GBuffer) |
|
{ |
|
hasDecalScreenSpace = true; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if (hasDecalScreenSpace) |
|
EditorGUILayout.HelpBox("Decals with Screen Space technique only support rendering with DecalProjector component.", MessageType.Warning); |
|
} |
|
} |
|
}
|
|
|