testss
This commit is contained in:
@@ -0,0 +1,619 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
|
||||
namespace UnityEditor
|
||||
{
|
||||
public abstract class BaseShaderGUI : ShaderGUI
|
||||
{
|
||||
#region EnumsAndClasses
|
||||
|
||||
public enum SurfaceType
|
||||
{
|
||||
Opaque,
|
||||
Transparent
|
||||
}
|
||||
|
||||
public enum BlendMode
|
||||
{
|
||||
Alpha, // Old school alpha-blending mode, fresnel does not affect amount of transparency
|
||||
Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply
|
||||
Additive,
|
||||
Multiply
|
||||
}
|
||||
|
||||
public enum SmoothnessSource
|
||||
{
|
||||
BaseAlpha,
|
||||
SpecularAlpha
|
||||
}
|
||||
|
||||
public enum RenderFace
|
||||
{
|
||||
Front = 2,
|
||||
Back = 1,
|
||||
Both = 0
|
||||
}
|
||||
|
||||
protected class Styles
|
||||
{
|
||||
// Catergories
|
||||
public static readonly GUIContent SurfaceOptions =
|
||||
new GUIContent("Surface Options", "Controls how Universal RP renders the Material on a screen.");
|
||||
|
||||
public static readonly GUIContent SurfaceInputs = new GUIContent("Surface Inputs",
|
||||
"These settings describe the look and feel of the surface itself.");
|
||||
|
||||
public static readonly GUIContent AdvancedLabel = new GUIContent("Advanced",
|
||||
"These settings affect behind-the-scenes rendering and underlying calculations.");
|
||||
|
||||
public static readonly GUIContent surfaceType = new GUIContent("Surface Type",
|
||||
"Select a surface type for your texture. Choose between Opaque or Transparent.");
|
||||
|
||||
public static readonly GUIContent blendingMode = new GUIContent("Blending Mode",
|
||||
"Controls how the color of the Transparent surface blends with the Material color in the background.");
|
||||
|
||||
public static readonly GUIContent cullingText = new GUIContent("Render Face",
|
||||
"Specifies which faces to cull from your geometry. Front culls front faces. Back culls backfaces. None means that both sides are rendered.");
|
||||
|
||||
public static readonly GUIContent alphaClipText = new GUIContent("Alpha Clipping",
|
||||
"Makes your Material act like a Cutout shader. Use this to create a transparent effect with hard edges between opaque and transparent areas.");
|
||||
|
||||
public static readonly GUIContent alphaClipThresholdText = new GUIContent("Threshold",
|
||||
"Sets where the Alpha Clipping starts. The higher the value is, the brighter the effect is when clipping starts.");
|
||||
|
||||
public static readonly GUIContent receiveShadowText = new GUIContent("Receive Shadows",
|
||||
"When enabled, other GameObjects can cast shadows onto this GameObject.");
|
||||
|
||||
public static readonly GUIContent baseMap = new GUIContent("Base Map",
|
||||
"Specifies the base Material and/or Color of the surface. If you’ve selected Transparent or Alpha Clipping under Surface Options, your Material uses the Texture’s alpha channel or color.");
|
||||
|
||||
public static readonly GUIContent emissionMap = new GUIContent("Emission Map",
|
||||
"Sets a Texture map to use for emission. You can also select a color with the color picker. Colors are multiplied over the Texture.");
|
||||
|
||||
public static readonly GUIContent normalMapText =
|
||||
new GUIContent("Normal Map", "Assigns a tangent-space normal map.");
|
||||
|
||||
public static readonly GUIContent bumpScaleNotSupported =
|
||||
new GUIContent("Bump scale is not supported on mobile platforms");
|
||||
|
||||
public static readonly GUIContent fixNormalNow = new GUIContent("Fix now",
|
||||
"Converts the assigned texture to be a normal map format.");
|
||||
|
||||
public static readonly GUIContent queueSlider = new GUIContent("Priority",
|
||||
"Determines the chronological rendering order for a Material. High values are rendered first.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Variables
|
||||
|
||||
protected MaterialEditor materialEditor { get; set; }
|
||||
|
||||
protected MaterialProperty surfaceTypeProp { get; set; }
|
||||
|
||||
protected MaterialProperty blendModeProp { get; set; }
|
||||
|
||||
protected MaterialProperty cullingProp { get; set; }
|
||||
|
||||
protected MaterialProperty alphaClipProp { get; set; }
|
||||
|
||||
protected MaterialProperty alphaCutoffProp { get; set; }
|
||||
|
||||
protected MaterialProperty receiveShadowsProp { get; set; }
|
||||
|
||||
// Common Surface Input properties
|
||||
|
||||
protected MaterialProperty baseMapProp { get; set; }
|
||||
|
||||
protected MaterialProperty baseColorProp { get; set; }
|
||||
|
||||
protected MaterialProperty emissionMapProp { get; set; }
|
||||
|
||||
protected MaterialProperty emissionColorProp { get; set; }
|
||||
|
||||
protected MaterialProperty queueOffsetProp { get; set; }
|
||||
|
||||
public bool m_FirstTimeApply = true;
|
||||
|
||||
private const string k_KeyPrefix = "UniversalRP:Material:UI_State:";
|
||||
|
||||
private string m_HeaderStateKey = null;
|
||||
|
||||
protected string headerStateKey { get { return m_HeaderStateKey; } }
|
||||
|
||||
// Header foldout states
|
||||
|
||||
SavedBool m_SurfaceOptionsFoldout;
|
||||
|
||||
SavedBool m_SurfaceInputsFoldout;
|
||||
|
||||
SavedBool m_AdvancedFoldout;
|
||||
|
||||
#endregion
|
||||
|
||||
private const int queueOffsetRange = 50;
|
||||
////////////////////////////////////
|
||||
// General Functions //
|
||||
////////////////////////////////////
|
||||
#region GeneralFunctions
|
||||
|
||||
public abstract void MaterialChanged(Material material);
|
||||
|
||||
public virtual void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
surfaceTypeProp = FindProperty("_Surface", properties);
|
||||
blendModeProp = FindProperty("_Blend", properties);
|
||||
cullingProp = FindProperty("_Cull", properties);
|
||||
alphaClipProp = FindProperty("_AlphaClip", properties);
|
||||
alphaCutoffProp = FindProperty("_Cutoff", properties);
|
||||
receiveShadowsProp = FindProperty("_ReceiveShadows", properties, false);
|
||||
baseMapProp = FindProperty("_BaseMap", properties, false);
|
||||
baseColorProp = FindProperty("_BaseColor", properties, false);
|
||||
emissionMapProp = FindProperty("_EmissionMap", properties, false);
|
||||
emissionColorProp = FindProperty("_EmissionColor", properties, false);
|
||||
queueOffsetProp = FindProperty("_QueueOffset", properties, false);
|
||||
}
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties)
|
||||
{
|
||||
if (materialEditorIn == null)
|
||||
throw new ArgumentNullException("materialEditorIn");
|
||||
|
||||
FindProperties(properties); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
|
||||
materialEditor = materialEditorIn;
|
||||
Material material = materialEditor.target as Material;
|
||||
|
||||
// Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
|
||||
// material to a universal shader.
|
||||
if (m_FirstTimeApply)
|
||||
{
|
||||
OnOpenGUI(material, materialEditorIn);
|
||||
m_FirstTimeApply = false;
|
||||
}
|
||||
|
||||
ShaderPropertiesGUI(material);
|
||||
}
|
||||
|
||||
public virtual void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
// Foldout states
|
||||
m_HeaderStateKey = k_KeyPrefix + material.shader.name; // Create key string for editor prefs
|
||||
m_SurfaceOptionsFoldout = new SavedBool($"{m_HeaderStateKey}.SurfaceOptionsFoldout", true);
|
||||
m_SurfaceInputsFoldout = new SavedBool($"{m_HeaderStateKey}.SurfaceInputsFoldout", true);
|
||||
m_AdvancedFoldout = new SavedBool($"{m_HeaderStateKey}.AdvancedFoldout", false);
|
||||
|
||||
foreach (var obj in materialEditor.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
|
||||
public void ShaderPropertiesGUI(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
m_SurfaceOptionsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SurfaceOptionsFoldout.value, Styles.SurfaceOptions);
|
||||
if (m_SurfaceOptionsFoldout.value)
|
||||
{
|
||||
DrawSurfaceOptions(material);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
m_SurfaceInputsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SurfaceInputsFoldout.value, Styles.SurfaceInputs);
|
||||
if (m_SurfaceInputsFoldout.value)
|
||||
{
|
||||
DrawSurfaceInputs(material);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
DrawAdditionalFoldouts(material);
|
||||
|
||||
m_AdvancedFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_AdvancedFoldout.value, Styles.AdvancedLabel);
|
||||
if (m_AdvancedFoldout.value)
|
||||
{
|
||||
DrawAdvancedOptions(material);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in materialEditor.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Drawing Functions //
|
||||
////////////////////////////////////
|
||||
#region DrawingFunctions
|
||||
|
||||
public virtual void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
DoPopup(Styles.surfaceType, surfaceTypeProp, Enum.GetNames(typeof(SurfaceType)));
|
||||
if ((SurfaceType)material.GetFloat("_Surface") == SurfaceType.Transparent)
|
||||
DoPopup(Styles.blendingMode, blendModeProp, Enum.GetNames(typeof(BlendMode)));
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = cullingProp.hasMixedValue;
|
||||
var culling = (RenderFace)cullingProp.floatValue;
|
||||
culling = (RenderFace)EditorGUILayout.EnumPopup(Styles.cullingText, culling);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo(Styles.cullingText.text);
|
||||
cullingProp.floatValue = (float)culling;
|
||||
material.doubleSidedGI = (RenderFace)cullingProp.floatValue != RenderFace.Front;
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = alphaClipProp.hasMixedValue;
|
||||
var alphaClipEnabled = EditorGUILayout.Toggle(Styles.alphaClipText, alphaClipProp.floatValue == 1);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
alphaClipProp.floatValue = alphaClipEnabled ? 1 : 0;
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
if (alphaClipProp.floatValue == 1)
|
||||
materialEditor.ShaderProperty(alphaCutoffProp, Styles.alphaClipThresholdText, 1);
|
||||
|
||||
if (receiveShadowsProp != null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = receiveShadowsProp.hasMixedValue;
|
||||
var receiveShadows =
|
||||
EditorGUILayout.Toggle(Styles.receiveShadowText, receiveShadowsProp.floatValue == 1.0f);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
receiveShadowsProp.floatValue = receiveShadows ? 1.0f : 0.0f;
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
DrawBaseProperties(material);
|
||||
}
|
||||
|
||||
public virtual void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
materialEditor.EnableInstancingField();
|
||||
DrawQueueOffsetField();
|
||||
}
|
||||
|
||||
protected void DrawQueueOffsetField()
|
||||
{
|
||||
if (queueOffsetProp != null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = queueOffsetProp.hasMixedValue;
|
||||
var queue = EditorGUILayout.IntSlider(Styles.queueSlider, (int)queueOffsetProp.floatValue, -queueOffsetRange, queueOffsetRange);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
queueOffsetProp.floatValue = queue;
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DrawAdditionalFoldouts(Material material) {}
|
||||
|
||||
public virtual void DrawBaseProperties(Material material)
|
||||
{
|
||||
if (baseMapProp != null && baseColorProp != null) // Draw the baseMap, most shader will have at least a baseMap
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.baseMap, baseMapProp, baseColorProp);
|
||||
// TODO Temporary fix for lightmapping, to be replaced with attribute tag.
|
||||
if (material.HasProperty("_MainTex"))
|
||||
{
|
||||
material.SetTexture("_MainTex", baseMapProp.textureValue);
|
||||
var baseMapTiling = baseMapProp.textureScaleAndOffset;
|
||||
material.SetTextureScale("_MainTex", new Vector2(baseMapTiling.x, baseMapTiling.y));
|
||||
material.SetTextureOffset("_MainTex", new Vector2(baseMapTiling.z, baseMapTiling.w));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DrawEmissionProperties(Material material, bool keyword)
|
||||
{
|
||||
var emissive = true;
|
||||
var hadEmissionTexture = emissionMapProp.textureValue != null;
|
||||
|
||||
if (!keyword)
|
||||
{
|
||||
materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp, emissionColorProp,
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Emission for GI?
|
||||
emissive = materialEditor.EmissionEnabledProperty();
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!emissive);
|
||||
{
|
||||
// Texture and HDR color controls
|
||||
materialEditor.TexturePropertyWithHDRColor(Styles.emissionMap, emissionMapProp,
|
||||
emissionColorProp,
|
||||
false);
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
// If texture was assigned and color was black set color to white
|
||||
var brightness = emissionColorProp.colorValue.maxColorComponent;
|
||||
if (emissionMapProp.textureValue != null && !hadEmissionTexture && brightness <= 0f)
|
||||
emissionColorProp.colorValue = Color.white;
|
||||
|
||||
// UniversalRP does not support RealtimeEmissive. We set it to bake emissive and handle the emissive is black right.
|
||||
if (emissive)
|
||||
{
|
||||
var oldFlags = material.globalIlluminationFlags;
|
||||
var newFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
|
||||
|
||||
if (brightness <= 0f)
|
||||
newFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
|
||||
|
||||
if (newFlags != oldFlags)
|
||||
material.globalIlluminationFlags = newFlags;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawNormalArea(MaterialEditor materialEditor, MaterialProperty bumpMap, MaterialProperty bumpMapScale = null)
|
||||
{
|
||||
if (bumpMapScale != null)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap,
|
||||
bumpMap.textureValue != null ? bumpMapScale : null);
|
||||
if (bumpMapScale.floatValue != 1 &&
|
||||
UnityEditorInternal.InternalEditorUtility.IsMobilePlatform(
|
||||
EditorUserBuildSettings.activeBuildTarget))
|
||||
if (materialEditor.HelpBoxWithButton(Styles.bumpScaleNotSupported, Styles.fixNormalNow))
|
||||
bumpMapScale.floatValue = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void DrawTileOffset(MaterialEditor materialEditor, MaterialProperty textureProp)
|
||||
{
|
||||
materialEditor.TextureScaleOffsetProperty(textureProp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Material Data Functions //
|
||||
////////////////////////////////////
|
||||
#region MaterialDataFunctions
|
||||
|
||||
public static void SetMaterialKeywords(Material material, Action<Material> shadingModelFunc = null, Action<Material> shaderFunc = null)
|
||||
{
|
||||
// Clear all keywords for fresh start
|
||||
material.shaderKeywords = null;
|
||||
|
||||
// Setup blending - consistent across all Universal RP shaders
|
||||
SetupMaterialBlendMode(material);
|
||||
|
||||
// Receive Shadows
|
||||
if (material.HasProperty("_ReceiveShadows"))
|
||||
CoreUtils.SetKeyword(material, "_RECEIVE_SHADOWS_OFF", material.GetFloat("_ReceiveShadows") == 0.0f);
|
||||
|
||||
// Emission
|
||||
if (material.HasProperty("_EmissionColor"))
|
||||
MaterialEditor.FixupEmissiveFlag(material);
|
||||
bool shouldEmissionBeEnabled =
|
||||
(material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0;
|
||||
if (material.HasProperty("_EmissionEnabled") && !shouldEmissionBeEnabled)
|
||||
shouldEmissionBeEnabled = material.GetFloat("_EmissionEnabled") >= 0.5f;
|
||||
CoreUtils.SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
|
||||
|
||||
// Normal Map
|
||||
if (material.HasProperty("_BumpMap"))
|
||||
CoreUtils.SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap"));
|
||||
|
||||
// Shader specific keyword functions
|
||||
shadingModelFunc?.Invoke(material);
|
||||
shaderFunc?.Invoke(material);
|
||||
}
|
||||
|
||||
public static void SetupMaterialBlendMode(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
bool alphaClip = false;
|
||||
if (material.HasProperty("_AlphaClip"))
|
||||
alphaClip = material.GetFloat("_AlphaClip") >= 0.5;
|
||||
|
||||
if (alphaClip)
|
||||
{
|
||||
material.EnableKeyword("_ALPHATEST_ON");
|
||||
}
|
||||
else
|
||||
{
|
||||
material.DisableKeyword("_ALPHATEST_ON");
|
||||
}
|
||||
|
||||
if (material.HasProperty("_Surface"))
|
||||
{
|
||||
SurfaceType surfaceType = (SurfaceType)material.GetFloat("_Surface");
|
||||
if (surfaceType == SurfaceType.Opaque)
|
||||
{
|
||||
if (alphaClip)
|
||||
{
|
||||
material.renderQueue = (int)RenderQueue.AlphaTest;
|
||||
material.SetOverrideTag("RenderType", "TransparentCutout");
|
||||
}
|
||||
else
|
||||
{
|
||||
material.renderQueue = (int)RenderQueue.Geometry;
|
||||
material.SetOverrideTag("RenderType", "Opaque");
|
||||
}
|
||||
|
||||
material.renderQueue += material.HasProperty("_QueueOffset") ? (int)material.GetFloat("_QueueOffset") : 0;
|
||||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One);
|
||||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero);
|
||||
material.SetFloat("_ZWrite", 1.0f);
|
||||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||||
material.SetShaderPassEnabled("ShadowCaster", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlendMode blendMode = (BlendMode)material.GetFloat("_Blend");
|
||||
|
||||
// Specific Transparent Mode Settings
|
||||
switch (blendMode)
|
||||
{
|
||||
case BlendMode.Alpha:
|
||||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||||
break;
|
||||
case BlendMode.Premultiply:
|
||||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.One);
|
||||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
|
||||
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
|
||||
break;
|
||||
case BlendMode.Additive:
|
||||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
|
||||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.One);
|
||||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||||
break;
|
||||
case BlendMode.Multiply:
|
||||
material.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.DstColor);
|
||||
material.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.Zero);
|
||||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
|
||||
material.EnableKeyword("_ALPHAMODULATE_ON");
|
||||
break;
|
||||
}
|
||||
|
||||
// General Transparent Material Settings
|
||||
material.SetOverrideTag("RenderType", "Transparent");
|
||||
material.SetFloat("_ZWrite", 0.0f);
|
||||
material.renderQueue = (int)RenderQueue.Transparent;
|
||||
material.renderQueue += material.HasProperty("_QueueOffset") ? (int)material.GetFloat("_QueueOffset") : 0;
|
||||
material.SetShaderPassEnabled("ShadowCaster", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
////////////////////////////////////
|
||||
// Helper Functions //
|
||||
////////////////////////////////////
|
||||
#region HelperFunctions
|
||||
|
||||
public static void TwoFloatSingleLine(GUIContent title, MaterialProperty prop1, GUIContent prop1Label,
|
||||
MaterialProperty prop2, GUIContent prop2Label, MaterialEditor materialEditor, float labelWidth = 30f)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = prop1.hasMixedValue || prop2.hasMixedValue;
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
EditorGUI.PrefixLabel(rect, title);
|
||||
var indent = EditorGUI.indentLevel;
|
||||
var preLabelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
Rect propRect1 = new Rect(rect.x + preLabelWidth, rect.y,
|
||||
(rect.width - preLabelWidth) * 0.5f, EditorGUIUtility.singleLineHeight);
|
||||
var prop1val = EditorGUI.FloatField(propRect1, prop1Label, prop1.floatValue);
|
||||
|
||||
Rect propRect2 = new Rect(propRect1.x + propRect1.width, rect.y,
|
||||
propRect1.width, EditorGUIUtility.singleLineHeight);
|
||||
var prop2val = EditorGUI.FloatField(propRect2, prop2Label, prop2.floatValue);
|
||||
|
||||
EditorGUI.indentLevel = indent;
|
||||
EditorGUIUtility.labelWidth = preLabelWidth;
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo(title.text);
|
||||
prop1.floatValue = prop1val;
|
||||
prop2.floatValue = prop2val;
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
public void DoPopup(GUIContent label, MaterialProperty property, string[] options)
|
||||
{
|
||||
DoPopup(label, property, options, materialEditor);
|
||||
}
|
||||
|
||||
public static void DoPopup(GUIContent label, MaterialProperty property, string[] options, MaterialEditor materialEditor)
|
||||
{
|
||||
if (property == null)
|
||||
throw new ArgumentNullException("property");
|
||||
|
||||
EditorGUI.showMixedValue = property.hasMixedValue;
|
||||
|
||||
var mode = property.floatValue;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
mode = EditorGUILayout.Popup(label, (int)mode, options);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo(label.text);
|
||||
property.floatValue = mode;
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
// Helper to show texture and color properties
|
||||
public static Rect TextureColorProps(MaterialEditor materialEditor, GUIContent label, MaterialProperty textureProp, MaterialProperty colorProp, bool hdr = false)
|
||||
{
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
EditorGUI.showMixedValue = textureProp.hasMixedValue;
|
||||
materialEditor.TexturePropertyMiniThumbnail(rect, textureProp, label.text, label.tooltip);
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
if (colorProp != null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = colorProp.hasMixedValue;
|
||||
int indentLevel = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
Rect rectAfterLabel = new Rect(rect.x + EditorGUIUtility.labelWidth, rect.y,
|
||||
EditorGUIUtility.fieldWidth, EditorGUIUtility.singleLineHeight);
|
||||
var col = EditorGUI.ColorField(rectAfterLabel, GUIContent.none, colorProp.colorValue, true,
|
||||
false, hdr);
|
||||
EditorGUI.indentLevel = indentLevel;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo(colorProp.displayName);
|
||||
colorProp.colorValue = col;
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Copied from shaderGUI as it is a protected function in an abstract class, unavailable to others
|
||||
|
||||
public new static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties)
|
||||
{
|
||||
return FindProperty(propertyName, properties, true);
|
||||
}
|
||||
|
||||
// Copied from shaderGUI as it is a protected function in an abstract class, unavailable to others
|
||||
|
||||
public new static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties, bool propertyIsMandatory)
|
||||
{
|
||||
for (int index = 0; index < properties.Length; ++index)
|
||||
{
|
||||
if (properties[index] != null && properties[index].name == propertyName)
|
||||
return properties[index];
|
||||
}
|
||||
if (propertyIsMandatory)
|
||||
throw new ArgumentException("Could not find MaterialProperty: '" + propertyName + "', Num properties: " + (object)properties.Length);
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,466 @@
|
||||
using UnityEngine;
|
||||
using UnityEditorInternal;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.Scripting.APIUpdating;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
[MovedFrom("UnityEditor.Rendering.LWRP.ShaderGUI")] public static class ParticleGUI
|
||||
{
|
||||
public enum ColorMode
|
||||
{
|
||||
Multiply,
|
||||
Additive,
|
||||
Subtractive,
|
||||
Overlay,
|
||||
Color,
|
||||
Difference
|
||||
}
|
||||
|
||||
public static class Styles
|
||||
{
|
||||
public static GUIContent colorMode = new GUIContent("Color Mode",
|
||||
"Controls how the Particle color and the Material color blend together.");
|
||||
|
||||
public static GUIContent flipbookMode = new GUIContent("Flip-Book Blending",
|
||||
"Blends the frames in a flip-book together in a smooth animation.");
|
||||
|
||||
public static GUIContent softParticlesEnabled = new GUIContent("Soft Particles",
|
||||
"Makes particles fade out when they get close to intersecting with the surface of other geometry in the depth buffer.");
|
||||
|
||||
public static GUIContent softParticlesNearFadeDistanceText =
|
||||
new GUIContent("Near",
|
||||
"The distance from the other surface where the particle is completely transparent.");
|
||||
|
||||
public static GUIContent softParticlesFarFadeDistanceText =
|
||||
new GUIContent("Far",
|
||||
"The distance from the other surface where the particle is completely opaque.");
|
||||
|
||||
public static GUIContent cameraFadingEnabled = new GUIContent("Camera Fading",
|
||||
"Makes particles fade out when they get close to the camera.");
|
||||
|
||||
public static GUIContent cameraNearFadeDistanceText =
|
||||
new GUIContent("Near",
|
||||
"The distance from the camera where the particle is completely transparent.");
|
||||
|
||||
public static GUIContent cameraFarFadeDistanceText =
|
||||
new GUIContent("Far", "The distance from the camera where the particle is completely opaque.");
|
||||
|
||||
public static GUIContent distortionEnabled = new GUIContent("Distortion",
|
||||
"Creates a distortion effect by making particles perform refraction with the objects drawn before them.");
|
||||
|
||||
public static GUIContent distortionStrength = new GUIContent("Strength",
|
||||
"Controls how much the Particle distorts the background. ");
|
||||
|
||||
public static GUIContent distortionBlend = new GUIContent("Blend",
|
||||
"Controls how visible the distortion effect is. At 0, there’s no visible distortion. At 1, only the distortion effect is visible, not the background.");
|
||||
|
||||
public static GUIContent VertexStreams = new GUIContent("Vertex Streams",
|
||||
"The vertex streams needed for this Material to function properly.");
|
||||
|
||||
public static string streamPositionText = "Position (POSITION.xyz)";
|
||||
public static string streamNormalText = "Normal (NORMAL.xyz)";
|
||||
public static string streamColorText = "Color (COLOR.xyzw)";
|
||||
public static string streamColorInstancedText = "Color (INSTANCED0.xyzw)";
|
||||
public static string streamUVText = "UV (TEXCOORD0.xy)";
|
||||
public static string streamUV2Text = "UV2 (TEXCOORD0.zw)";
|
||||
public static string streamAnimBlendText = "AnimBlend (TEXCOORD1.x)";
|
||||
public static string streamAnimFrameText = "AnimFrame (INSTANCED1.x)";
|
||||
public static string streamTangentText = "Tangent (TANGENT.xyzw)";
|
||||
|
||||
public static GUIContent streamApplyToAllSystemsText = new GUIContent("Fix Now",
|
||||
"Apply the vertex stream layout to all Particle Systems using this material");
|
||||
|
||||
public static string undoApplyCustomVertexStreams = L10n.Tr("Apply custom vertex streams from material");
|
||||
|
||||
public static GUIStyle vertexStreamIcon = new GUIStyle();
|
||||
}
|
||||
|
||||
private static ReorderableList vertexStreamList;
|
||||
|
||||
public struct ParticleProperties
|
||||
{
|
||||
// Surface Option Props
|
||||
public MaterialProperty colorMode;
|
||||
|
||||
// Advanced Props
|
||||
public MaterialProperty flipbookMode;
|
||||
public MaterialProperty softParticlesEnabled;
|
||||
public MaterialProperty cameraFadingEnabled;
|
||||
public MaterialProperty distortionEnabled;
|
||||
public MaterialProperty softParticlesNearFadeDistance;
|
||||
public MaterialProperty softParticlesFarFadeDistance;
|
||||
public MaterialProperty cameraNearFadeDistance;
|
||||
public MaterialProperty cameraFarFadeDistance;
|
||||
public MaterialProperty distortionBlend;
|
||||
public MaterialProperty distortionStrength;
|
||||
|
||||
public ParticleProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Option Props
|
||||
colorMode = BaseShaderGUI.FindProperty("_ColorMode", properties, false);
|
||||
// Advanced Props
|
||||
flipbookMode = BaseShaderGUI.FindProperty("_FlipbookBlending", properties);
|
||||
softParticlesEnabled = BaseShaderGUI.FindProperty("_SoftParticlesEnabled", properties);
|
||||
cameraFadingEnabled = BaseShaderGUI.FindProperty("_CameraFadingEnabled", properties);
|
||||
distortionEnabled = BaseShaderGUI.FindProperty("_DistortionEnabled", properties, false);
|
||||
softParticlesNearFadeDistance = BaseShaderGUI.FindProperty("_SoftParticlesNearFadeDistance", properties);
|
||||
softParticlesFarFadeDistance = BaseShaderGUI.FindProperty("_SoftParticlesFarFadeDistance", properties);
|
||||
cameraNearFadeDistance = BaseShaderGUI.FindProperty("_CameraNearFadeDistance", properties);
|
||||
cameraFarFadeDistance = BaseShaderGUI.FindProperty("_CameraFarFadeDistance", properties);
|
||||
distortionBlend = BaseShaderGUI.FindProperty("_DistortionBlend", properties, false);
|
||||
distortionStrength = BaseShaderGUI.FindProperty("_DistortionStrength", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetupMaterialWithColorMode(Material material)
|
||||
{
|
||||
var colorMode = (ColorMode)material.GetFloat("_ColorMode");
|
||||
|
||||
switch (colorMode)
|
||||
{
|
||||
case ColorMode.Multiply:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.DisableKeyword("_COLORADDSUBDIFF_ON");
|
||||
break;
|
||||
case ColorMode.Overlay:
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.DisableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.EnableKeyword("_COLOROVERLAY_ON");
|
||||
break;
|
||||
case ColorMode.Color:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.EnableKeyword("_COLORCOLOR_ON");
|
||||
break;
|
||||
case ColorMode.Difference:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.EnableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.SetVector("_BaseColorAddSubDiff", new Vector4(-1.0f, 1.0f, 0.0f, 0.0f));
|
||||
break;
|
||||
case ColorMode.Additive:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.EnableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.SetVector("_BaseColorAddSubDiff", new Vector4(1.0f, 0.0f, 0.0f, 0.0f));
|
||||
break;
|
||||
case ColorMode.Subtractive:
|
||||
material.DisableKeyword("_COLOROVERLAY_ON");
|
||||
material.DisableKeyword("_COLORCOLOR_ON");
|
||||
material.EnableKeyword("_COLORADDSUBDIFF_ON");
|
||||
material.SetVector("_BaseColorAddSubDiff", new Vector4(-1.0f, 0.0f, 0.0f, 0.0f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void FadingOptions(Material material, MaterialEditor materialEditor, ParticleProperties properties)
|
||||
{
|
||||
// Z write doesn't work with fading
|
||||
bool hasZWrite = (material.GetFloat("_ZWrite") > 0.0f);
|
||||
if (!hasZWrite)
|
||||
{
|
||||
// Soft Particles
|
||||
{
|
||||
EditorGUI.showMixedValue = properties.softParticlesEnabled.hasMixedValue;
|
||||
var enabled = properties.softParticlesEnabled.floatValue;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
enabled = EditorGUILayout.Toggle(Styles.softParticlesEnabled, enabled != 0.0f) ? 1.0f : 0.0f;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo("Soft Particles Enabled");
|
||||
properties.softParticlesEnabled.floatValue = enabled;
|
||||
}
|
||||
|
||||
if (enabled >= 0.5f)
|
||||
{
|
||||
UniversalRenderPipelineAsset urpAsset = UniversalRenderPipeline.asset;
|
||||
if (urpAsset != null && !urpAsset.supportsCameraDepthTexture)
|
||||
{
|
||||
GUIStyle warnStyle = new GUIStyle(GUI.skin.label);
|
||||
warnStyle.fontStyle = FontStyle.BoldAndItalic;
|
||||
warnStyle.wordWrap = true;
|
||||
EditorGUILayout.HelpBox("Soft Particles require depth texture. Please enable \"Depth Texture\" in the Universal Render Pipeline settings.", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
BaseShaderGUI.TwoFloatSingleLine(new GUIContent("Surface Fade"),
|
||||
properties.softParticlesNearFadeDistance,
|
||||
Styles.softParticlesNearFadeDistanceText,
|
||||
properties.softParticlesFarFadeDistance,
|
||||
Styles.softParticlesFarFadeDistanceText,
|
||||
materialEditor);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
// Camera Fading
|
||||
{
|
||||
EditorGUI.showMixedValue = properties.cameraFadingEnabled.hasMixedValue;
|
||||
var enabled = properties.cameraFadingEnabled.floatValue;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
enabled = EditorGUILayout.Toggle(Styles.cameraFadingEnabled, enabled != 0.0f) ? 1.0f : 0.0f;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo("Camera Fading Enabled");
|
||||
properties.cameraFadingEnabled.floatValue = enabled;
|
||||
}
|
||||
|
||||
if (enabled >= 0.5f)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
BaseShaderGUI.TwoFloatSingleLine(new GUIContent("Distance"),
|
||||
properties.cameraNearFadeDistance,
|
||||
Styles.cameraNearFadeDistanceText,
|
||||
properties.cameraFarFadeDistance,
|
||||
Styles.cameraFarFadeDistanceText,
|
||||
materialEditor);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
// Distortion
|
||||
if (properties.distortionEnabled != null)
|
||||
{
|
||||
EditorGUI.showMixedValue = properties.distortionEnabled.hasMixedValue;
|
||||
var enabled = properties.distortionEnabled.floatValue;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
enabled = EditorGUILayout.Toggle(Styles.distortionEnabled, enabled != 0.0f) ? 1.0f : 0.0f;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo("Distortion Enabled");
|
||||
properties.distortionEnabled.floatValue = enabled;
|
||||
}
|
||||
|
||||
if (enabled >= 0.5f)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
materialEditor.ShaderProperty(properties.distortionStrength, Styles.distortionStrength);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = properties.distortionStrength.hasMixedValue;
|
||||
var blend = EditorGUILayout.Slider(Styles.distortionBlend, properties.distortionBlend.floatValue, 0f, 1f);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
properties.distortionBlend.floatValue = blend;
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoVertexStreamsArea(Material material, List<ParticleSystemRenderer> renderers, bool useLighting = false)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
// Display list of streams required to make this shader work
|
||||
bool useNormalMap = false;
|
||||
bool useFlipbookBlending = (material.GetFloat("_FlipbookBlending") > 0.0f);
|
||||
if (material.HasProperty("_BumpMap"))
|
||||
useNormalMap = material.GetTexture("_BumpMap");
|
||||
|
||||
bool useGPUInstancing = ShaderUtil.HasProceduralInstancing(material.shader);
|
||||
if (useGPUInstancing && renderers.Count > 0)
|
||||
{
|
||||
if (!renderers[0].enableGPUInstancing || renderers[0].renderMode != ParticleSystemRenderMode.Mesh)
|
||||
useGPUInstancing = false;
|
||||
}
|
||||
|
||||
// Build the list of expected vertex streams
|
||||
List<ParticleSystemVertexStream> streams = new List<ParticleSystemVertexStream>();
|
||||
List<string> streamList = new List<string>();
|
||||
|
||||
streams.Add(ParticleSystemVertexStream.Position);
|
||||
streamList.Add(Styles.streamPositionText);
|
||||
|
||||
if (useLighting || useNormalMap)
|
||||
{
|
||||
streams.Add(ParticleSystemVertexStream.Normal);
|
||||
streamList.Add(Styles.streamNormalText);
|
||||
if (useNormalMap)
|
||||
{
|
||||
streams.Add(ParticleSystemVertexStream.Tangent);
|
||||
streamList.Add(Styles.streamTangentText);
|
||||
}
|
||||
}
|
||||
|
||||
streams.Add(ParticleSystemVertexStream.Color);
|
||||
streamList.Add(useGPUInstancing ? Styles.streamColorInstancedText : Styles.streamColorText);
|
||||
streams.Add(ParticleSystemVertexStream.UV);
|
||||
streamList.Add(Styles.streamUVText);
|
||||
|
||||
List<ParticleSystemVertexStream> instancedStreams = new List<ParticleSystemVertexStream>(streams);
|
||||
|
||||
if (useGPUInstancing)
|
||||
{
|
||||
instancedStreams.Add(ParticleSystemVertexStream.AnimFrame);
|
||||
streamList.Add(Styles.streamAnimFrameText);
|
||||
}
|
||||
else if (useFlipbookBlending && !useGPUInstancing)
|
||||
{
|
||||
streams.Add(ParticleSystemVertexStream.UV2);
|
||||
streamList.Add(Styles.streamUV2Text);
|
||||
streams.Add(ParticleSystemVertexStream.AnimBlend);
|
||||
streamList.Add(Styles.streamAnimBlendText);
|
||||
}
|
||||
|
||||
vertexStreamList = new ReorderableList(streamList, typeof(string), false, true, false, false);
|
||||
|
||||
vertexStreamList.drawHeaderCallback = (Rect rect) => {
|
||||
EditorGUI.LabelField(rect, "Vertex Streams");
|
||||
};
|
||||
|
||||
vertexStreamList.DoLayoutList();
|
||||
|
||||
// Display a warning if any renderers have incorrect vertex streams
|
||||
string Warnings = "";
|
||||
List<ParticleSystemVertexStream> rendererStreams = new List<ParticleSystemVertexStream>();
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
renderer.GetActiveVertexStreams(rendererStreams);
|
||||
|
||||
bool streamsValid;
|
||||
if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing)
|
||||
streamsValid = CompareVertexStreams(rendererStreams, instancedStreams);
|
||||
else
|
||||
streamsValid = CompareVertexStreams(rendererStreams, instancedStreams);
|
||||
|
||||
if (!streamsValid)
|
||||
Warnings += "-" + renderer.name + "\n";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Warnings))
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
"The following Particle System Renderers are using this material with incorrect Vertex Streams:\n" +
|
||||
Warnings, MessageType.Error, true);
|
||||
// Set the streams on all systems using this material
|
||||
if (GUILayout.Button(Styles.streamApplyToAllSystemsText, EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
|
||||
{
|
||||
Undo.RecordObjects(renderers.Where(r => r != null).ToArray(), Styles.undoApplyCustomVertexStreams);
|
||||
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing)
|
||||
renderer.SetActiveVertexStreams(instancedStreams);
|
||||
else
|
||||
renderer.SetActiveVertexStreams(streams);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CompareVertexStreams(IEnumerable<ParticleSystemVertexStream> a, IEnumerable<ParticleSystemVertexStream> b)
|
||||
{
|
||||
var differenceA = a.Except(b);
|
||||
var differenceB = b.Except(a);
|
||||
var difference = differenceA.Union(differenceB).Distinct();
|
||||
if (!difference.Any())
|
||||
return true;
|
||||
// If normals are the only difference, ignore them, because the default particle streams include normals, to make it easy for users to switch between lit and unlit
|
||||
if (difference.Count() == 1)
|
||||
{
|
||||
if (difference.First() == ParticleSystemVertexStream.Normal)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
// Setup particle + material color blending
|
||||
SetupMaterialWithColorMode(material);
|
||||
// Is the material transparent, this is set in BaseShaderGUI
|
||||
bool isTransparent = material.GetTag("RenderType", false) == "Transparent";
|
||||
// Z write doesn't work with distortion/fading
|
||||
bool hasZWrite = (material.GetFloat("_ZWrite") > 0.0f);
|
||||
|
||||
// Flipbook blending
|
||||
if (material.HasProperty("_FlipbookBlending"))
|
||||
{
|
||||
var useFlipbookBlending = (material.GetFloat("_FlipbookBlending") > 0.0f);
|
||||
CoreUtils.SetKeyword(material, "_FLIPBOOKBLENDING_ON", useFlipbookBlending);
|
||||
}
|
||||
// Soft particles
|
||||
var useSoftParticles = false;
|
||||
if (material.HasProperty("_SoftParticlesEnabled"))
|
||||
{
|
||||
useSoftParticles = (material.GetFloat("_SoftParticlesEnabled") > 0.0f && isTransparent);
|
||||
if (useSoftParticles)
|
||||
{
|
||||
var softParticlesNearFadeDistance = material.GetFloat("_SoftParticlesNearFadeDistance");
|
||||
var softParticlesFarFadeDistance = material.GetFloat("_SoftParticlesFarFadeDistance");
|
||||
// clamp values
|
||||
if (softParticlesNearFadeDistance < 0.0f)
|
||||
{
|
||||
softParticlesNearFadeDistance = 0.0f;
|
||||
material.SetFloat("_SoftParticlesNearFadeDistance", 0.0f);
|
||||
}
|
||||
|
||||
if (softParticlesFarFadeDistance < 0.0f)
|
||||
{
|
||||
softParticlesFarFadeDistance = 0.0f;
|
||||
material.SetFloat("_SoftParticlesFarFadeDistance", 0.0f);
|
||||
}
|
||||
// set keywords
|
||||
material.SetVector("_SoftParticleFadeParams",
|
||||
new Vector4(softParticlesNearFadeDistance,
|
||||
1.0f / (softParticlesFarFadeDistance - softParticlesNearFadeDistance), 0.0f, 0.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
material.SetVector("_SoftParticleFadeParams", new Vector4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
CoreUtils.SetKeyword(material, "_SOFTPARTICLES_ON", useSoftParticles);
|
||||
}
|
||||
// Camera fading
|
||||
var useCameraFading = false;
|
||||
if (material.HasProperty("_CameraFadingEnabled") && isTransparent)
|
||||
{
|
||||
useCameraFading = (material.GetFloat("_CameraFadingEnabled") > 0.0f);
|
||||
if (useCameraFading)
|
||||
{
|
||||
var cameraNearFadeDistance = material.GetFloat("_CameraNearFadeDistance");
|
||||
var cameraFarFadeDistance = material.GetFloat("_CameraFarFadeDistance");
|
||||
// clamp values
|
||||
if (cameraNearFadeDistance < 0.0f)
|
||||
{
|
||||
cameraNearFadeDistance = 0.0f;
|
||||
material.SetFloat("_CameraNearFadeDistance", 0.0f);
|
||||
}
|
||||
|
||||
if (cameraFarFadeDistance < 0.0f)
|
||||
{
|
||||
cameraFarFadeDistance = 0.0f;
|
||||
material.SetFloat("_CameraFarFadeDistance", 0.0f);
|
||||
}
|
||||
// set keywords
|
||||
material.SetVector("_CameraFadeParams",
|
||||
new Vector4(cameraNearFadeDistance, 1.0f / (cameraFarFadeDistance - cameraNearFadeDistance),
|
||||
0.0f, 0.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
material.SetVector("_CameraFadeParams", new Vector4(0.0f, Mathf.Infinity, 0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
// Distortion
|
||||
if (material.HasProperty("_DistortionEnabled"))
|
||||
{
|
||||
var useDistortion = (material.GetFloat("_DistortionEnabled") > 0.0f) && isTransparent;
|
||||
CoreUtils.SetKeyword(material, "_DISTORTION_ON", useDistortion);
|
||||
if (useDistortion)
|
||||
material.SetFloat("_DistortionStrengthScaled", material.GetFloat("_DistortionStrength") * 0.1f);
|
||||
}
|
||||
|
||||
var useFading = (useSoftParticles || useCameraFading) && !hasZWrite;
|
||||
CoreUtils.SetKeyword(material, "_FADING_ON", useFading);
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Rendering.Universal;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class BakedLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private BakedLitGUI.BakedLitProperties shadingModelProperties;
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new BakedLitGUI.BakedLitProperties(properties);
|
||||
}
|
||||
|
||||
// material changed check
|
||||
public override void MaterialChanged(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
SetMaterialKeywords(material);
|
||||
}
|
||||
|
||||
// material main surface options
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// Use default labelWidth
|
||||
EditorGUIUtility.labelWidth = 0f;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
BakedLitGUI.Inputs(shadingModelProperties, materialEditor);
|
||||
DrawTileOffset(materialEditor, baseMapProp);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
base.DrawAdvancedOptions(material);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// _Emission property is lost after assigning Standard shader to the material
|
||||
// thus transfer it before assigning the new shader
|
||||
if (material.HasProperty("_Emission"))
|
||||
{
|
||||
material.SetColor("_EmissionColor", material.GetColor("_Emission"));
|
||||
}
|
||||
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
|
||||
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
|
||||
{
|
||||
SetupMaterialBlendMode(material);
|
||||
return;
|
||||
}
|
||||
|
||||
SurfaceType surfaceType = SurfaceType.Opaque;
|
||||
BlendMode blendMode = BlendMode.Alpha;
|
||||
if (oldShader.name.Contains("/Transparent/Cutout/"))
|
||||
{
|
||||
surfaceType = SurfaceType.Opaque;
|
||||
material.SetFloat("_AlphaClip", 1);
|
||||
}
|
||||
else if (oldShader.name.Contains("/Transparent/"))
|
||||
{
|
||||
// NOTE: legacy shaders did not provide physically based transparency
|
||||
// therefore Fade mode
|
||||
surfaceType = SurfaceType.Transparent;
|
||||
blendMode = BlendMode.Alpha;
|
||||
}
|
||||
material.SetFloat("_Surface", (float)surfaceType);
|
||||
material.SetFloat("_Blend", (float)blendMode);
|
||||
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class LitShader : BaseShaderGUI
|
||||
{
|
||||
private LitGUI.LitProperties litProperties;
|
||||
private LitDetailGUI.LitProperties litDetailProperties;
|
||||
private SavedBool m_DetailInputsFoldout;
|
||||
|
||||
public override void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
base.OnOpenGUI(material, materialEditor);
|
||||
m_DetailInputsFoldout = new SavedBool($"{headerStateKey}.DetailInputsFoldout", true);
|
||||
}
|
||||
|
||||
public override void DrawAdditionalFoldouts(Material material)
|
||||
{
|
||||
m_DetailInputsFoldout.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_DetailInputsFoldout.value, LitDetailGUI.Styles.detailInputs);
|
||||
if (m_DetailInputsFoldout.value)
|
||||
{
|
||||
LitDetailGUI.DoDetailArea(litDetailProperties, materialEditor);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
}
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
litProperties = new LitGUI.LitProperties(properties);
|
||||
litDetailProperties = new LitDetailGUI.LitProperties(properties);
|
||||
}
|
||||
|
||||
// material changed check
|
||||
public override void MaterialChanged(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
SetMaterialKeywords(material, LitGUI.SetMaterialKeywords, LitDetailGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
// material main surface options
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// Use default labelWidth
|
||||
EditorGUIUtility.labelWidth = 0f;
|
||||
|
||||
// Detect any changes to the material
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (litProperties.workflowMode != null)
|
||||
{
|
||||
DoPopup(LitGUI.Styles.workflowModeText, litProperties.workflowMode, Enum.GetNames(typeof(LitGUI.WorkflowMode)));
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
LitGUI.Inputs(litProperties, materialEditor, material);
|
||||
DrawEmissionProperties(material, true);
|
||||
DrawTileOffset(materialEditor, baseMapProp);
|
||||
}
|
||||
|
||||
// material main advanced options
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
if (litProperties.reflections != null && litProperties.highlights != null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
materialEditor.ShaderProperty(litProperties.highlights, LitGUI.Styles.highlightsText);
|
||||
materialEditor.ShaderProperty(litProperties.reflections, LitGUI.Styles.reflectionsText);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
|
||||
base.DrawAdvancedOptions(material);
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// _Emission property is lost after assigning Standard shader to the material
|
||||
// thus transfer it before assigning the new shader
|
||||
if (material.HasProperty("_Emission"))
|
||||
{
|
||||
material.SetColor("_EmissionColor", material.GetColor("_Emission"));
|
||||
}
|
||||
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
|
||||
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
|
||||
{
|
||||
SetupMaterialBlendMode(material);
|
||||
return;
|
||||
}
|
||||
|
||||
SurfaceType surfaceType = SurfaceType.Opaque;
|
||||
BlendMode blendMode = BlendMode.Alpha;
|
||||
if (oldShader.name.Contains("/Transparent/Cutout/"))
|
||||
{
|
||||
surfaceType = SurfaceType.Opaque;
|
||||
material.SetFloat("_AlphaClip", 1);
|
||||
}
|
||||
else if (oldShader.name.Contains("/Transparent/"))
|
||||
{
|
||||
// NOTE: legacy shaders did not provide physically based transparency
|
||||
// therefore Fade mode
|
||||
surfaceType = SurfaceType.Transparent;
|
||||
blendMode = BlendMode.Alpha;
|
||||
}
|
||||
material.SetFloat("_Surface", (float)surfaceType);
|
||||
material.SetFloat("_Blend", (float)blendMode);
|
||||
|
||||
if (oldShader.name.Equals("Standard (Specular setup)"))
|
||||
{
|
||||
material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Specular);
|
||||
Texture texture = material.GetTexture("_SpecGlossMap");
|
||||
if (texture != null)
|
||||
material.SetTexture("_MetallicSpecGlossMap", texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
material.SetFloat("_WorkflowMode", (float)LitGUI.WorkflowMode.Metallic);
|
||||
Texture texture = material.GetTexture("_MetallicGlossMap");
|
||||
if (texture != null)
|
||||
material.SetTexture("_MetallicSpecGlossMap", texture);
|
||||
}
|
||||
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class ParticlesLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private LitGUI.LitProperties litProperties;
|
||||
private ParticleGUI.ParticleProperties particleProps;
|
||||
|
||||
// List of renderers using this material in the scene, used for validating vertex streams
|
||||
List<ParticleSystemRenderer> m_RenderersUsingThisMaterial = new List<ParticleSystemRenderer>();
|
||||
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
litProperties = new LitGUI.LitProperties(properties);
|
||||
particleProps = new ParticleGUI.ParticleProperties(properties);
|
||||
}
|
||||
|
||||
public override void MaterialChanged(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
SetMaterialKeywords(material, LitGUI.SetMaterialKeywords, ParticleGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
// Detect any changes to the material
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
DoPopup(ParticleGUI.Styles.colorMode, particleProps.colorMode, Enum.GetNames(typeof(ParticleGUI.ColorMode)));
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
LitGUI.Inputs(litProperties, materialEditor, material);
|
||||
DrawEmissionProperties(material, true);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
materialEditor.ShaderProperty(particleProps.flipbookMode, ParticleGUI.Styles.flipbookMode);
|
||||
ParticleGUI.FadingOptions(material, materialEditor, particleProps);
|
||||
ParticleGUI.DoVertexStreamsArea(material, m_RenderersUsingThisMaterial, true);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
|
||||
DrawQueueOffsetField();
|
||||
}
|
||||
|
||||
public override void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
CacheRenderersUsingThisMaterial(material);
|
||||
base.OnOpenGUI(material, materialEditor);
|
||||
}
|
||||
|
||||
void CacheRenderersUsingThisMaterial(Material material)
|
||||
{
|
||||
m_RenderersUsingThisMaterial.Clear();
|
||||
|
||||
ParticleSystemRenderer[] renderers = UnityEngine.Object.FindObjectsOfType(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[];
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (renderer.sharedMaterial == material)
|
||||
m_RenderersUsingThisMaterial.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class ParticlesSimpleLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private SimpleLitGUI.SimpleLitProperties shadingModelProperties;
|
||||
private ParticleGUI.ParticleProperties particleProps;
|
||||
|
||||
// List of renderers using this material in the scene, used for validating vertex streams
|
||||
List<ParticleSystemRenderer> m_RenderersUsingThisMaterial = new List<ParticleSystemRenderer>();
|
||||
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new SimpleLitGUI.SimpleLitProperties(properties);
|
||||
particleProps = new ParticleGUI.ParticleProperties(properties);
|
||||
}
|
||||
|
||||
public override void MaterialChanged(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
SetMaterialKeywords(material, SimpleLitGUI.SetMaterialKeywords, ParticleGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
// Detect any changes to the material
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
DoPopup(ParticleGUI.Styles.colorMode, particleProps.colorMode, Enum.GetNames(typeof(ParticleGUI.ColorMode)));
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
SimpleLitGUI.Inputs(shadingModelProperties, materialEditor, material);
|
||||
DrawEmissionProperties(material, true);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
SimpleLitGUI.Advanced(shadingModelProperties);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
materialEditor.ShaderProperty(particleProps.flipbookMode, ParticleGUI.Styles.flipbookMode);
|
||||
ParticleGUI.FadingOptions(material, materialEditor, particleProps);
|
||||
ParticleGUI.DoVertexStreamsArea(material, m_RenderersUsingThisMaterial, true);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
|
||||
DrawQueueOffsetField();
|
||||
}
|
||||
|
||||
public override void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
CacheRenderersUsingThisMaterial(material);
|
||||
base.OnOpenGUI(material, materialEditor);
|
||||
}
|
||||
|
||||
void CacheRenderersUsingThisMaterial(Material material)
|
||||
{
|
||||
m_RenderersUsingThisMaterial.Clear();
|
||||
|
||||
ParticleSystemRenderer[] renderers = UnityEngine.Object.FindObjectsOfType(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[];
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (renderer.sharedMaterial == material)
|
||||
m_RenderersUsingThisMaterial.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class ParticlesUnlitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private BakedLitGUI.BakedLitProperties shadingModelProperties;
|
||||
private ParticleGUI.ParticleProperties particleProps;
|
||||
|
||||
// List of renderers using this material in the scene, used for validating vertex streams
|
||||
List<ParticleSystemRenderer> m_RenderersUsingThisMaterial = new List<ParticleSystemRenderer>();
|
||||
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new BakedLitGUI.BakedLitProperties(properties);
|
||||
particleProps = new ParticleGUI.ParticleProperties(properties);
|
||||
}
|
||||
|
||||
public override void MaterialChanged(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
SetMaterialKeywords(material, null, ParticleGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
// Detect any changes to the material
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
DoPopup(ParticleGUI.Styles.colorMode, particleProps.colorMode, Enum.GetNames(typeof(ParticleGUI.ColorMode)));
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
BakedLitGUI.Inputs(shadingModelProperties, materialEditor);
|
||||
DrawEmissionProperties(material, true);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
materialEditor.ShaderProperty(particleProps.flipbookMode, ParticleGUI.Styles.flipbookMode);
|
||||
ParticleGUI.FadingOptions(material, materialEditor, particleProps);
|
||||
ParticleGUI.DoVertexStreamsArea(material, m_RenderersUsingThisMaterial);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
|
||||
DrawQueueOffsetField();
|
||||
}
|
||||
|
||||
public override void OnOpenGUI(Material material, MaterialEditor materialEditor)
|
||||
{
|
||||
CacheRenderersUsingThisMaterial(material);
|
||||
base.OnOpenGUI(material, materialEditor);
|
||||
}
|
||||
|
||||
void CacheRenderersUsingThisMaterial(Material material)
|
||||
{
|
||||
m_RenderersUsingThisMaterial.Clear();
|
||||
|
||||
ParticleSystemRenderer[] renderers = UnityEngine.Object.FindObjectsOfType(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[];
|
||||
foreach (ParticleSystemRenderer renderer in renderers)
|
||||
{
|
||||
if (renderer.sharedMaterial == material)
|
||||
m_RenderersUsingThisMaterial.Add(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace UnityEditor
|
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class SimpleLitShader : BaseShaderGUI
|
||||
{
|
||||
// Properties
|
||||
private SimpleLitGUI.SimpleLitProperties shadingModelProperties;
|
||||
|
||||
// collect properties from the material properties
|
||||
public override void FindProperties(MaterialProperty[] properties)
|
||||
{
|
||||
base.FindProperties(properties);
|
||||
shadingModelProperties = new SimpleLitGUI.SimpleLitProperties(properties);
|
||||
}
|
||||
|
||||
// material changed check
|
||||
public override void MaterialChanged(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
SetMaterialKeywords(material, SimpleLitGUI.SetMaterialKeywords);
|
||||
}
|
||||
|
||||
// material main surface options
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// Use default labelWidth
|
||||
EditorGUIUtility.labelWidth = 0f;
|
||||
|
||||
// Detect any changes to the material
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
SimpleLitGUI.Inputs(shadingModelProperties, materialEditor, material);
|
||||
DrawEmissionProperties(material, true);
|
||||
DrawTileOffset(materialEditor, baseMapProp);
|
||||
}
|
||||
|
||||
public override void DrawAdvancedOptions(Material material)
|
||||
{
|
||||
SimpleLitGUI.Advanced(shadingModelProperties);
|
||||
base.DrawAdvancedOptions(material);
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// _Emission property is lost after assigning Standard shader to the material
|
||||
// thus transfer it before assigning the new shader
|
||||
if (material.HasProperty("_Emission"))
|
||||
{
|
||||
material.SetColor("_EmissionColor", material.GetColor("_Emission"));
|
||||
}
|
||||
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
|
||||
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
|
||||
{
|
||||
SetupMaterialBlendMode(material);
|
||||
return;
|
||||
}
|
||||
|
||||
SurfaceType surfaceType = SurfaceType.Opaque;
|
||||
BlendMode blendMode = BlendMode.Alpha;
|
||||
if (oldShader.name.Contains("/Transparent/Cutout/"))
|
||||
{
|
||||
surfaceType = SurfaceType.Opaque;
|
||||
material.SetFloat("_AlphaClip", 1);
|
||||
}
|
||||
else if (oldShader.name.Contains("/Transparent/"))
|
||||
{
|
||||
// NOTE: legacy shaders did not provide physically based transparency
|
||||
// therefore Fade mode
|
||||
surfaceType = SurfaceType.Transparent;
|
||||
blendMode = BlendMode.Alpha;
|
||||
}
|
||||
material.SetFloat("_Surface", (float)surfaceType);
|
||||
material.SetFloat("_Blend", (float)blendMode);
|
||||
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class UnlitShader : BaseShaderGUI
|
||||
{
|
||||
// material changed check
|
||||
public override void MaterialChanged(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
SetMaterialKeywords(material);
|
||||
}
|
||||
|
||||
// material main surface options
|
||||
public override void DrawSurfaceOptions(Material material)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// Use default labelWidth
|
||||
EditorGUIUtility.labelWidth = 0f;
|
||||
|
||||
// Detect any changes to the material
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
base.DrawSurfaceOptions(material);
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
foreach (var obj in blendModeProp.targets)
|
||||
MaterialChanged((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
// material main surface inputs
|
||||
public override void DrawSurfaceInputs(Material material)
|
||||
{
|
||||
base.DrawSurfaceInputs(material);
|
||||
DrawTileOffset(materialEditor, baseMapProp);
|
||||
}
|
||||
|
||||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
||||
{
|
||||
if (material == null)
|
||||
throw new ArgumentNullException("material");
|
||||
|
||||
// _Emission property is lost after assigning Standard shader to the material
|
||||
// thus transfer it before assigning the new shader
|
||||
if (material.HasProperty("_Emission"))
|
||||
{
|
||||
material.SetColor("_EmissionColor", material.GetColor("_Emission"));
|
||||
}
|
||||
|
||||
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
||||
|
||||
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/"))
|
||||
{
|
||||
SetupMaterialBlendMode(material);
|
||||
return;
|
||||
}
|
||||
|
||||
SurfaceType surfaceType = SurfaceType.Opaque;
|
||||
BlendMode blendMode = BlendMode.Alpha;
|
||||
if (oldShader.name.Contains("/Transparent/Cutout/"))
|
||||
{
|
||||
surfaceType = SurfaceType.Opaque;
|
||||
material.SetFloat("_AlphaClip", 1);
|
||||
}
|
||||
else if (oldShader.name.Contains("/Transparent/"))
|
||||
{
|
||||
// NOTE: legacy shaders did not provide physically based transparency
|
||||
// therefore Fade mode
|
||||
surfaceType = SurfaceType.Transparent;
|
||||
blendMode = BlendMode.Alpha;
|
||||
}
|
||||
material.SetFloat("_Surface", (float)surfaceType);
|
||||
material.SetFloat("_Blend", (float)blendMode);
|
||||
|
||||
MaterialChanged(material);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Scripting.APIUpdating;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
[MovedFrom("UnityEditor.Rendering.LWRP.ShaderGUI")] public static class BakedLitGUI
|
||||
{
|
||||
public struct BakedLitProperties
|
||||
{
|
||||
// Surface Input Props
|
||||
public MaterialProperty bumpMapProp;
|
||||
|
||||
public BakedLitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Input Props
|
||||
bumpMapProp = BaseShaderGUI.FindProperty("_BumpMap", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inputs(BakedLitProperties properties, MaterialEditor materialEditor)
|
||||
{
|
||||
BaseShaderGUI.DrawNormalArea(materialEditor, properties.bumpMapProp);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
internal class LitDetailGUI
|
||||
{
|
||||
public static class Styles
|
||||
{
|
||||
public static readonly GUIContent detailInputs = new GUIContent("Detail Inputs",
|
||||
"These settings let you add details to the surface.");
|
||||
|
||||
public static readonly GUIContent detailMaskText = new GUIContent("Mask",
|
||||
"Select a mask for the Detail maps. The mask uses the alpha channel of the selected texture. The __Tiling__ and __Offset__ settings have no effect on the mask.");
|
||||
|
||||
public static readonly GUIContent detailAlbedoMapText = new GUIContent("Base Map",
|
||||
"Select the texture containing the surface details.");
|
||||
|
||||
public static readonly GUIContent detailNormalMapText = new GUIContent("Normal Map",
|
||||
"Select the texture containing the normal vector data.");
|
||||
|
||||
public static readonly GUIContent detailAlbedoMapScaleInfo = new GUIContent("Setting the scaling factor to a value other than 1 results in a less performant shader variant.");
|
||||
}
|
||||
|
||||
public struct LitProperties
|
||||
{
|
||||
public MaterialProperty detailMask;
|
||||
public MaterialProperty detailAlbedoMapScale;
|
||||
public MaterialProperty detailAlbedoMap;
|
||||
public MaterialProperty detailNormalMapScale;
|
||||
public MaterialProperty detailNormalMap;
|
||||
|
||||
public LitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
detailMask = BaseShaderGUI.FindProperty("_DetailMask", properties, false);
|
||||
detailAlbedoMapScale = BaseShaderGUI.FindProperty("_DetailAlbedoMapScale", properties, false);
|
||||
detailAlbedoMap = BaseShaderGUI.FindProperty("_DetailAlbedoMap", properties, false);
|
||||
detailNormalMapScale = BaseShaderGUI.FindProperty("_DetailNormalMapScale", properties, false);
|
||||
detailNormalMap = BaseShaderGUI.FindProperty("_DetailNormalMap", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoDetailArea(LitProperties properties, MaterialEditor materialEditor)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.detailMaskText, properties.detailMask);
|
||||
materialEditor.TexturePropertySingleLine(Styles.detailAlbedoMapText, properties.detailAlbedoMap,
|
||||
properties.detailAlbedoMap.textureValue != null ? properties.detailAlbedoMapScale : null);
|
||||
if (properties.detailAlbedoMapScale.floatValue != 1.0f)
|
||||
{
|
||||
EditorGUILayout.HelpBox(Styles.detailAlbedoMapScaleInfo.text, MessageType.Info, true);
|
||||
}
|
||||
materialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, properties.detailNormalMap,
|
||||
properties.detailNormalMap.textureValue != null ? properties.detailNormalMapScale : null);
|
||||
materialEditor.TextureScaleOffsetProperty(properties.detailAlbedoMap);
|
||||
}
|
||||
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
if (material.HasProperty("_DetailAlbedoMap") && material.HasProperty("_DetailNormalMap") && material.HasProperty("_DetailAlbedoMapScale"))
|
||||
{
|
||||
bool isScaled = material.GetFloat("_DetailAlbedoMapScale") != 1.0f;
|
||||
bool hasDetailMap = material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap");
|
||||
CoreUtils.SetKeyword(material, "_DETAIL_MULX2", !isScaled && hasDetailMap);
|
||||
CoreUtils.SetKeyword(material, "_DETAIL_SCALED", isScaled && hasDetailMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,331 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Scripting.APIUpdating;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
[MovedFrom("UnityEditor.Rendering.LWRP.ShaderGUI")] public static class LitGUI
|
||||
{
|
||||
public enum WorkflowMode
|
||||
{
|
||||
Specular = 0,
|
||||
Metallic
|
||||
}
|
||||
|
||||
public enum SmoothnessMapChannel
|
||||
{
|
||||
SpecularMetallicAlpha,
|
||||
AlbedoAlpha,
|
||||
}
|
||||
|
||||
public static class Styles
|
||||
{
|
||||
public static GUIContent workflowModeText = new GUIContent("Workflow Mode",
|
||||
"Select a workflow that fits your textures. Choose between Metallic or Specular.");
|
||||
|
||||
public static GUIContent specularMapText =
|
||||
new GUIContent("Specular Map", "Sets and configures the map and color for the Specular workflow.");
|
||||
|
||||
public static GUIContent metallicMapText =
|
||||
new GUIContent("Metallic Map", "Sets and configures the map for the Metallic workflow.");
|
||||
|
||||
public static GUIContent smoothnessText = new GUIContent("Smoothness",
|
||||
"Controls the spread of highlights and reflections on the surface.");
|
||||
|
||||
public static GUIContent smoothnessMapChannelText =
|
||||
new GUIContent("Source",
|
||||
"Specifies where to sample a smoothness map from. By default, uses the alpha channel for your map.");
|
||||
|
||||
public static GUIContent highlightsText = new GUIContent("Specular Highlights",
|
||||
"When enabled, the Material reflects the shine from direct lighting.");
|
||||
|
||||
public static GUIContent reflectionsText =
|
||||
new GUIContent("Environment Reflections",
|
||||
"When enabled, the Material samples reflections from the nearest Reflection Probes or Lighting Probe.");
|
||||
|
||||
public static GUIContent heightMapText = new GUIContent("Height Map",
|
||||
"Specifies the Height Map (G) for this Material.");
|
||||
|
||||
public static GUIContent occlusionText = new GUIContent("Occlusion Map",
|
||||
"Sets an occlusion map to simulate shadowing from ambient lighting.");
|
||||
|
||||
public static readonly string[] metallicSmoothnessChannelNames = {"Metallic Alpha", "Albedo Alpha"};
|
||||
public static readonly string[] specularSmoothnessChannelNames = {"Specular Alpha", "Albedo Alpha"};
|
||||
|
||||
public static GUIContent clearCoatText = new GUIContent("Clear Coat",
|
||||
"A multi-layer material feature which simulates a thin layer of coating on top of the surface material." +
|
||||
"\nPerformance cost is considerable as the specular component is evaluated twice, once per layer.");
|
||||
|
||||
public static GUIContent clearCoatMaskText = new GUIContent("Mask",
|
||||
"Specifies the amount of the coat blending." +
|
||||
"\nActs as a multiplier of the clear coat map mask value or as a direct mask value if no map is specified." +
|
||||
"\nThe map specifies clear coat mask in the red channel and clear coat smoothness in the green channel.");
|
||||
|
||||
public static GUIContent clearCoatSmoothnessText = new GUIContent("Smoothness",
|
||||
"Specifies the smoothness of the coating." +
|
||||
"\nActs as a multiplier of the clear coat map smoothness value or as a direct smoothness value if no map is specified.");
|
||||
}
|
||||
|
||||
public struct LitProperties
|
||||
{
|
||||
// Surface Option Props
|
||||
public MaterialProperty workflowMode;
|
||||
|
||||
// Surface Input Props
|
||||
public MaterialProperty metallic;
|
||||
public MaterialProperty specColor;
|
||||
public MaterialProperty metallicGlossMap;
|
||||
public MaterialProperty specGlossMap;
|
||||
public MaterialProperty smoothness;
|
||||
public MaterialProperty smoothnessMapChannel;
|
||||
public MaterialProperty bumpMapProp;
|
||||
public MaterialProperty bumpScaleProp;
|
||||
public MaterialProperty parallaxMapProp;
|
||||
public MaterialProperty parallaxScaleProp;
|
||||
public MaterialProperty occlusionStrength;
|
||||
public MaterialProperty occlusionMap;
|
||||
|
||||
// Advanced Props
|
||||
public MaterialProperty highlights;
|
||||
public MaterialProperty reflections;
|
||||
|
||||
public MaterialProperty clearCoat; // Enable/Disable dummy property
|
||||
public MaterialProperty clearCoatMap;
|
||||
public MaterialProperty clearCoatMask;
|
||||
public MaterialProperty clearCoatSmoothness;
|
||||
|
||||
public LitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Option Props
|
||||
workflowMode = BaseShaderGUI.FindProperty("_WorkflowMode", properties, false);
|
||||
// Surface Input Props
|
||||
metallic = BaseShaderGUI.FindProperty("_Metallic", properties);
|
||||
specColor = BaseShaderGUI.FindProperty("_SpecColor", properties, false);
|
||||
metallicGlossMap = BaseShaderGUI.FindProperty("_MetallicGlossMap", properties);
|
||||
specGlossMap = BaseShaderGUI.FindProperty("_SpecGlossMap", properties, false);
|
||||
smoothness = BaseShaderGUI.FindProperty("_Smoothness", properties, false);
|
||||
smoothnessMapChannel = BaseShaderGUI.FindProperty("_SmoothnessTextureChannel", properties, false);
|
||||
bumpMapProp = BaseShaderGUI.FindProperty("_BumpMap", properties, false);
|
||||
bumpScaleProp = BaseShaderGUI.FindProperty("_BumpScale", properties, false);
|
||||
parallaxMapProp = BaseShaderGUI.FindProperty("_ParallaxMap", properties, false);
|
||||
parallaxScaleProp = BaseShaderGUI.FindProperty("_Parallax", properties, false);
|
||||
occlusionStrength = BaseShaderGUI.FindProperty("_OcclusionStrength", properties, false);
|
||||
occlusionMap = BaseShaderGUI.FindProperty("_OcclusionMap", properties, false);
|
||||
// Advanced Props
|
||||
highlights = BaseShaderGUI.FindProperty("_SpecularHighlights", properties, false);
|
||||
reflections = BaseShaderGUI.FindProperty("_EnvironmentReflections", properties, false);
|
||||
|
||||
clearCoat = BaseShaderGUI.FindProperty("_ClearCoat", properties, false);
|
||||
clearCoatMap = BaseShaderGUI.FindProperty("_ClearCoatMap", properties, false);
|
||||
clearCoatMask = BaseShaderGUI.FindProperty("_ClearCoatMask", properties, false);
|
||||
clearCoatSmoothness = BaseShaderGUI.FindProperty("_ClearCoatSmoothness", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inputs(LitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
DoMetallicSpecularArea(properties, materialEditor, material);
|
||||
BaseShaderGUI.DrawNormalArea(materialEditor, properties.bumpMapProp, properties.bumpScaleProp);
|
||||
|
||||
if (HeightmapAvailable(material))
|
||||
DoHeightmapArea(properties, materialEditor);
|
||||
|
||||
if (properties.occlusionMap != null)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.occlusionText, properties.occlusionMap,
|
||||
properties.occlusionMap.textureValue != null ? properties.occlusionStrength : null);
|
||||
}
|
||||
|
||||
// Check that we have all the required properties for clear coat,
|
||||
// otherwise we will get null ref exception from MaterialEditor GUI helpers.
|
||||
if (ClearCoatAvailable(material))
|
||||
DoClearCoat(properties, materialEditor, material);
|
||||
}
|
||||
|
||||
private static bool ClearCoatAvailable(Material material)
|
||||
{
|
||||
return material.HasProperty("_ClearCoat")
|
||||
&& material.HasProperty("_ClearCoatMap")
|
||||
&& material.HasProperty("_ClearCoatMask")
|
||||
&& material.HasProperty("_ClearCoatSmoothness");
|
||||
}
|
||||
|
||||
private static bool HeightmapAvailable(Material material)
|
||||
{
|
||||
return material.HasProperty("_Parallax")
|
||||
&& material.HasProperty("_ParallaxMap");
|
||||
}
|
||||
|
||||
private static void DoHeightmapArea(LitProperties properties, MaterialEditor materialEditor)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.heightMapText, properties.parallaxMapProp,
|
||||
properties.parallaxMapProp.textureValue != null ? properties.parallaxScaleProp : null);
|
||||
}
|
||||
|
||||
private static bool ClearCoatEnabled(Material material)
|
||||
{
|
||||
return material.HasProperty("_ClearCoat") && material.GetFloat("_ClearCoat") > 0.0;
|
||||
}
|
||||
|
||||
public static void DoClearCoat(LitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
var coatEnabled = ClearCoatEnabled(material);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.Toggle(EditorGUILayout.GetControlRect(), Styles.clearCoatText, coatEnabled);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (coatEnabled)
|
||||
material.SetFloat("_ClearCoat", 0); // Toggle off
|
||||
else
|
||||
material.SetFloat("_ClearCoat", 1);
|
||||
|
||||
coatEnabled = !coatEnabled;
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!coatEnabled);
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.clearCoatMaskText, properties.clearCoatMap, properties.clearCoatMask);
|
||||
|
||||
EditorGUI.indentLevel += 2;
|
||||
|
||||
// Texture and HDR color controls
|
||||
materialEditor.ShaderProperty(properties.clearCoatSmoothness , Styles.clearCoatSmoothnessText);
|
||||
|
||||
EditorGUI.indentLevel -= 2;
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
public static void DoMetallicSpecularArea(LitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
string[] smoothnessChannelNames;
|
||||
bool hasGlossMap = false;
|
||||
if (properties.workflowMode == null ||
|
||||
(WorkflowMode)properties.workflowMode.floatValue == WorkflowMode.Metallic)
|
||||
{
|
||||
hasGlossMap = properties.metallicGlossMap.textureValue != null;
|
||||
smoothnessChannelNames = Styles.metallicSmoothnessChannelNames;
|
||||
materialEditor.TexturePropertySingleLine(Styles.metallicMapText, properties.metallicGlossMap,
|
||||
hasGlossMap ? null : properties.metallic);
|
||||
}
|
||||
else
|
||||
{
|
||||
hasGlossMap = properties.specGlossMap.textureValue != null;
|
||||
smoothnessChannelNames = Styles.specularSmoothnessChannelNames;
|
||||
BaseShaderGUI.TextureColorProps(materialEditor, Styles.specularMapText, properties.specGlossMap,
|
||||
hasGlossMap ? null : properties.specColor);
|
||||
}
|
||||
EditorGUI.indentLevel++;
|
||||
DoSmoothness(properties, material, smoothnessChannelNames);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
public static void DoSmoothness(LitProperties properties, Material material, string[] smoothnessChannelNames)
|
||||
{
|
||||
var opaque = ((BaseShaderGUI.SurfaceType)material.GetFloat("_Surface") ==
|
||||
BaseShaderGUI.SurfaceType.Opaque);
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = properties.smoothness.hasMixedValue;
|
||||
var smoothness = EditorGUILayout.Slider(Styles.smoothnessText, properties.smoothness.floatValue, 0f, 1f);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
properties.smoothness.floatValue = smoothness;
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
if (properties.smoothnessMapChannel != null) // smoothness channel
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginDisabledGroup(!opaque);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = properties.smoothnessMapChannel.hasMixedValue;
|
||||
var smoothnessSource = (int)properties.smoothnessMapChannel.floatValue;
|
||||
if (opaque)
|
||||
smoothnessSource = EditorGUILayout.Popup(Styles.smoothnessMapChannelText, smoothnessSource,
|
||||
smoothnessChannelNames);
|
||||
else
|
||||
EditorGUILayout.Popup(Styles.smoothnessMapChannelText, 0, smoothnessChannelNames);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
properties.smoothnessMapChannel.floatValue = smoothnessSource;
|
||||
EditorGUI.showMixedValue = false;
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
public static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)
|
||||
{
|
||||
int ch = (int)material.GetFloat("_SmoothnessTextureChannel");
|
||||
if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)
|
||||
return SmoothnessMapChannel.AlbedoAlpha;
|
||||
|
||||
return SmoothnessMapChannel.SpecularMetallicAlpha;
|
||||
}
|
||||
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
|
||||
// (MaterialProperty value might come from renderer material property block)
|
||||
var hasGlossMap = false;
|
||||
var isSpecularWorkFlow = false;
|
||||
var opaque = ((BaseShaderGUI.SurfaceType)material.GetFloat("_Surface") ==
|
||||
BaseShaderGUI.SurfaceType.Opaque);
|
||||
if (material.HasProperty("_WorkflowMode"))
|
||||
{
|
||||
isSpecularWorkFlow = (WorkflowMode)material.GetFloat("_WorkflowMode") == WorkflowMode.Specular;
|
||||
if (isSpecularWorkFlow)
|
||||
hasGlossMap = material.GetTexture("_SpecGlossMap") != null;
|
||||
else
|
||||
hasGlossMap = material.GetTexture("_MetallicGlossMap") != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasGlossMap = material.GetTexture("_MetallicGlossMap") != null;
|
||||
}
|
||||
|
||||
CoreUtils.SetKeyword(material, "_SPECULAR_SETUP", isSpecularWorkFlow);
|
||||
|
||||
CoreUtils.SetKeyword(material, "_METALLICSPECGLOSSMAP", hasGlossMap);
|
||||
|
||||
if (material.HasProperty("_SpecularHighlights"))
|
||||
CoreUtils.SetKeyword(material, "_SPECULARHIGHLIGHTS_OFF",
|
||||
material.GetFloat("_SpecularHighlights") == 0.0f);
|
||||
if (material.HasProperty("_EnvironmentReflections"))
|
||||
CoreUtils.SetKeyword(material, "_ENVIRONMENTREFLECTIONS_OFF",
|
||||
material.GetFloat("_EnvironmentReflections") == 0.0f);
|
||||
if (material.HasProperty("_OcclusionMap"))
|
||||
CoreUtils.SetKeyword(material, "_OCCLUSIONMAP", material.GetTexture("_OcclusionMap"));
|
||||
|
||||
if (material.HasProperty("_ParallaxMap"))
|
||||
CoreUtils.SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
|
||||
|
||||
if (material.HasProperty("_SmoothnessTextureChannel"))
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A",
|
||||
GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha && opaque);
|
||||
}
|
||||
|
||||
// Clear coat keywords are independent to remove possiblity of invalid combinations.
|
||||
if (ClearCoatEnabled(material))
|
||||
{
|
||||
var hasMap = material.HasProperty("_ClearCoatMap") && material.GetTexture("_ClearCoatMap") != null;
|
||||
if (hasMap)
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOAT", false);
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOATMAP", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOAT", true);
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOATMAP", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOAT", false);
|
||||
CoreUtils.SetKeyword(material, "_CLEARCOATMAP", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Scripting.APIUpdating;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal.ShaderGUI
|
||||
{
|
||||
[MovedFrom("UnityEditor.Rendering.LWRP.ShaderGUI")] public static class SimpleLitGUI
|
||||
{
|
||||
public enum SpecularSource
|
||||
{
|
||||
SpecularTextureAndColor,
|
||||
NoSpecular
|
||||
}
|
||||
|
||||
public enum SmoothnessMapChannel
|
||||
{
|
||||
SpecularAlpha,
|
||||
AlbedoAlpha,
|
||||
}
|
||||
|
||||
public static class Styles
|
||||
{
|
||||
public static GUIContent specularMapText =
|
||||
new GUIContent("Specular Map", "Sets and configures a Specular map and color for your Material.");
|
||||
|
||||
public static GUIContent smoothnessText = new GUIContent("Smoothness",
|
||||
"Controls the spread of highlights and reflections on the surface.");
|
||||
|
||||
public static GUIContent smoothnessMapChannelText =
|
||||
new GUIContent("Source",
|
||||
"Specifies where to sample a smoothness map from. By default, uses the alpha channel for your map.");
|
||||
|
||||
public static GUIContent highlightsText = new GUIContent("Specular Highlights",
|
||||
"When enabled, the Material reflects the shine from direct lighting.");
|
||||
}
|
||||
|
||||
public struct SimpleLitProperties
|
||||
{
|
||||
// Surface Input Props
|
||||
public MaterialProperty specColor;
|
||||
public MaterialProperty specGlossMap;
|
||||
public MaterialProperty specHighlights;
|
||||
public MaterialProperty smoothnessMapChannel;
|
||||
public MaterialProperty smoothness;
|
||||
public MaterialProperty bumpMapProp;
|
||||
|
||||
public SimpleLitProperties(MaterialProperty[] properties)
|
||||
{
|
||||
// Surface Input Props
|
||||
specColor = BaseShaderGUI.FindProperty("_SpecColor", properties);
|
||||
specGlossMap = BaseShaderGUI.FindProperty("_SpecGlossMap", properties, false);
|
||||
specHighlights = BaseShaderGUI.FindProperty("_SpecularHighlights", properties, false);
|
||||
smoothnessMapChannel = BaseShaderGUI.FindProperty("_SmoothnessSource", properties, false);
|
||||
smoothness = BaseShaderGUI.FindProperty("_Smoothness", properties, false);
|
||||
bumpMapProp = BaseShaderGUI.FindProperty("_BumpMap", properties, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inputs(SimpleLitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
DoSpecularArea(properties, materialEditor, material);
|
||||
BaseShaderGUI.DrawNormalArea(materialEditor, properties.bumpMapProp);
|
||||
}
|
||||
|
||||
public static void Advanced(SimpleLitProperties properties)
|
||||
{
|
||||
SpecularSource specularSource = (SpecularSource)properties.specHighlights.floatValue;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = properties.specHighlights.hasMixedValue;
|
||||
bool enabled = EditorGUILayout.Toggle(Styles.highlightsText, specularSource == SpecularSource.SpecularTextureAndColor);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
properties.specHighlights.floatValue = enabled ? (float)SpecularSource.SpecularTextureAndColor : (float)SpecularSource.NoSpecular;
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
public static void DoSpecularArea(SimpleLitProperties properties, MaterialEditor materialEditor, Material material)
|
||||
{
|
||||
SpecularSource specSource = (SpecularSource)properties.specHighlights.floatValue;
|
||||
EditorGUI.BeginDisabledGroup(specSource == SpecularSource.NoSpecular);
|
||||
BaseShaderGUI.TextureColorProps(materialEditor, Styles.specularMapText, properties.specGlossMap, properties.specColor, true);
|
||||
DoSmoothness(properties, material);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
public static void DoSmoothness(SimpleLitProperties properties, Material material)
|
||||
{
|
||||
var opaque = ((BaseShaderGUI.SurfaceType)material.GetFloat("_Surface") ==
|
||||
BaseShaderGUI.SurfaceType.Opaque);
|
||||
EditorGUI.indentLevel += 2;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = properties.smoothness.hasMixedValue;
|
||||
var smoothnessSource = (int)properties.smoothnessMapChannel.floatValue;
|
||||
var smoothness = properties.smoothness.floatValue;
|
||||
smoothness = EditorGUILayout.Slider(Styles.smoothnessText, smoothness, 0f, 1f);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
properties.smoothness.floatValue = smoothness;
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginDisabledGroup(!opaque);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = properties.smoothnessMapChannel.hasMixedValue;
|
||||
if (opaque)
|
||||
smoothnessSource = EditorGUILayout.Popup(Styles.smoothnessMapChannelText, smoothnessSource, Enum.GetNames(typeof(SmoothnessMapChannel)));
|
||||
else
|
||||
EditorGUILayout.Popup(Styles.smoothnessMapChannelText, 0, Enum.GetNames(typeof(SmoothnessMapChannel)));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
properties.smoothnessMapChannel.floatValue = smoothnessSource;
|
||||
EditorGUI.showMixedValue = false;
|
||||
EditorGUI.indentLevel -= 3;
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
public static void SetMaterialKeywords(Material material)
|
||||
{
|
||||
UpdateMaterialSpecularSource(material);
|
||||
}
|
||||
|
||||
private static void UpdateMaterialSpecularSource(Material material)
|
||||
{
|
||||
var opaque = ((BaseShaderGUI.SurfaceType)material.GetFloat("_Surface") ==
|
||||
BaseShaderGUI.SurfaceType.Opaque);
|
||||
SpecularSource specSource = (SpecularSource)material.GetFloat("_SpecularHighlights");
|
||||
if (specSource == SpecularSource.NoSpecular)
|
||||
{
|
||||
CoreUtils.SetKeyword(material, "_SPECGLOSSMAP", false);
|
||||
CoreUtils.SetKeyword(material, "_SPECULAR_COLOR", false);
|
||||
CoreUtils.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var smoothnessSource = (SmoothnessMapChannel)material.GetFloat("_SmoothnessSource");
|
||||
bool hasMap = material.GetTexture("_SpecGlossMap");
|
||||
CoreUtils.SetKeyword(material, "_SPECGLOSSMAP", hasMap);
|
||||
CoreUtils.SetKeyword(material, "_SPECULAR_COLOR", !hasMap);
|
||||
if (opaque)
|
||||
CoreUtils.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", smoothnessSource == SmoothnessMapChannel.AlbedoAlpha);
|
||||
else
|
||||
CoreUtils.SetKeyword(material, "_GLOSSINESS_FROM_BASE_ALPHA", false);
|
||||
|
||||
string color;
|
||||
if (smoothnessSource != SmoothnessMapChannel.AlbedoAlpha || !opaque)
|
||||
color = "_SpecColor";
|
||||
else
|
||||
color = "_BaseColor";
|
||||
|
||||
var col = material.GetColor(color);
|
||||
col.a = material.GetFloat("_Smoothness");
|
||||
material.SetColor(color, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,324 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEditor;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
|
||||
namespace UnityEditor.Rendering.Universal
|
||||
{
|
||||
internal class TerrainLitShaderGUI : UnityEditor.ShaderGUI, ITerrainLayerCustomUI
|
||||
{
|
||||
private class StylesLayer
|
||||
{
|
||||
public readonly GUIContent warningHeightBasedBlending = new GUIContent("Height-based blending is disabled if you have more than four TerrainLayer materials!");
|
||||
|
||||
public readonly GUIContent enableHeightBlend = new GUIContent("Enable Height-based Blend", "Blend terrain layers based on height values.");
|
||||
public readonly GUIContent heightTransition = new GUIContent("Height Transition", "Size in world units of the smooth transition between layers.");
|
||||
public readonly GUIContent enableInstancedPerPixelNormal = new GUIContent("Enable Per-pixel Normal", "Enable per-pixel normal when the terrain uses instanced rendering.");
|
||||
|
||||
public readonly GUIContent diffuseTexture = new GUIContent("Diffuse");
|
||||
public readonly GUIContent colorTint = new GUIContent("Color Tint");
|
||||
public readonly GUIContent opacityAsDensity = new GUIContent("Opacity as Density", "Enable Density Blend (if unchecked, opacity is used as Smoothness)");
|
||||
public readonly GUIContent normalMapTexture = new GUIContent("Normal Map");
|
||||
public readonly GUIContent normalScale = new GUIContent("Normal Scale");
|
||||
public readonly GUIContent maskMapTexture = new GUIContent("Mask", "R: Metallic\nG: AO\nB: Height\nA: Smoothness");
|
||||
public readonly GUIContent maskMapTextureWithoutHeight = new GUIContent("Mask Map", "R: Metallic\nG: AO\nA: Smoothness");
|
||||
public readonly GUIContent channelRemapping = new GUIContent("Channel Remapping");
|
||||
public readonly GUIContent defaultValues = new GUIContent("Channel Default Values");
|
||||
public readonly GUIContent metallic = new GUIContent("R: Metallic");
|
||||
public readonly GUIContent ao = new GUIContent("G: AO");
|
||||
public readonly GUIContent height = new GUIContent("B: Height");
|
||||
public readonly GUIContent heightParametrization = new GUIContent("Parametrization");
|
||||
public readonly GUIContent heightAmplitude = new GUIContent("Amplitude (cm)");
|
||||
public readonly GUIContent heightBase = new GUIContent("Base (cm)");
|
||||
public readonly GUIContent heightMin = new GUIContent("Min (cm)");
|
||||
public readonly GUIContent heightMax = new GUIContent("Max (cm)");
|
||||
public readonly GUIContent heightCm = new GUIContent("B: Height (cm)");
|
||||
public readonly GUIContent smoothness = new GUIContent("A: Smoothness");
|
||||
}
|
||||
|
||||
static StylesLayer s_Styles = null;
|
||||
private static StylesLayer styles { get { if (s_Styles == null) s_Styles = new StylesLayer(); return s_Styles; } }
|
||||
|
||||
public TerrainLitShaderGUI()
|
||||
{
|
||||
}
|
||||
|
||||
// Height blend params
|
||||
MaterialProperty enableHeightBlend = null;
|
||||
const string kEnableHeightBlend = "_EnableHeightBlend";
|
||||
|
||||
MaterialProperty heightTransition = null;
|
||||
const string kHeightTransition = "_HeightTransition";
|
||||
|
||||
// Per-pixel Normal (while instancing)
|
||||
MaterialProperty enableInstancedPerPixelNormal = null;
|
||||
const string kEnableInstancedPerPixelNormal = "_EnableInstancedPerPixelNormal";
|
||||
|
||||
private bool m_ShowChannelRemapping = false;
|
||||
enum HeightParametrization
|
||||
{
|
||||
Amplitude,
|
||||
MinMax
|
||||
};
|
||||
private HeightParametrization m_HeightParametrization = HeightParametrization.Amplitude;
|
||||
|
||||
private static bool DoesTerrainUseMaskMaps(TerrainLayer[] terrainLayers)
|
||||
{
|
||||
for (int i = 0; i < terrainLayers.Length; ++i)
|
||||
{
|
||||
if (terrainLayers[i].maskMapTexture != null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void FindMaterialProperties(MaterialProperty[] props)
|
||||
{
|
||||
enableHeightBlend = FindProperty(kEnableHeightBlend, props, false);
|
||||
heightTransition = FindProperty(kHeightTransition, props, false);
|
||||
enableInstancedPerPixelNormal = FindProperty(kEnableInstancedPerPixelNormal, props, false);
|
||||
}
|
||||
|
||||
static public void SetupMaterialKeywords(Material material)
|
||||
{
|
||||
bool enableHeightBlend = (material.HasProperty(kEnableHeightBlend) && material.GetFloat(kEnableHeightBlend) > 0);
|
||||
CoreUtils.SetKeyword(material, "_TERRAIN_BLEND_HEIGHT", enableHeightBlend);
|
||||
|
||||
bool enableInstancedPerPixelNormal = material.GetFloat(kEnableInstancedPerPixelNormal) > 0.0f;
|
||||
CoreUtils.SetKeyword(material, "_TERRAIN_INSTANCED_PERPIXEL_NORMAL", enableInstancedPerPixelNormal);
|
||||
}
|
||||
|
||||
static public bool TextureHasAlpha(Texture2D inTex)
|
||||
{
|
||||
if (inTex != null)
|
||||
{
|
||||
return GraphicsFormatUtility.HasAlphaChannel(GraphicsFormatUtility.GetGraphicsFormat(inTex.format, true));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditorIn, MaterialProperty[] properties)
|
||||
{
|
||||
if (materialEditorIn == null)
|
||||
throw new ArgumentNullException("materialEditorIn");
|
||||
|
||||
FindMaterialProperties(properties);
|
||||
|
||||
bool optionsChanged = false;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
{
|
||||
if (enableHeightBlend != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
materialEditorIn.ShaderProperty(enableHeightBlend, styles.enableHeightBlend);
|
||||
if (enableHeightBlend.floatValue > 0)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.HelpBox(styles.warningHeightBasedBlending.text, MessageType.Info);
|
||||
materialEditorIn.ShaderProperty(heightTransition, styles.heightTransition);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
optionsChanged = true;
|
||||
}
|
||||
|
||||
bool enablePerPixelNormalChanged = false;
|
||||
|
||||
// Since Instanced Per-pixel normal is actually dependent on instancing enabled or not, it is not
|
||||
// important to check it in the GUI. The shader will make sure it is enabled/disabled properly.s
|
||||
if (enableInstancedPerPixelNormal != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
materialEditorIn.ShaderProperty(enableInstancedPerPixelNormal, styles.enableInstancedPerPixelNormal);
|
||||
enablePerPixelNormalChanged = EditorGUI.EndChangeCheck();
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
if (optionsChanged || enablePerPixelNormalChanged)
|
||||
{
|
||||
foreach (var obj in materialEditorIn.targets)
|
||||
{
|
||||
SetupMaterialKeywords((Material)obj);
|
||||
}
|
||||
}
|
||||
|
||||
// We should always do this call at the end
|
||||
materialEditorIn.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
bool ITerrainLayerCustomUI.OnTerrainLayerGUI(TerrainLayer terrainLayer, Terrain terrain)
|
||||
{
|
||||
var terrainLayers = terrain.terrainData.terrainLayers;
|
||||
|
||||
// Don't use the member field enableHeightBlend as ShaderGUI.OnGUI might not be called if the material UI is folded.
|
||||
// heightblend shouldn't be available if we are in multi-pass mode, because it is guaranteed to be broken.
|
||||
bool heightBlendAvailable = (terrainLayers.Length <= 4);
|
||||
bool heightBlend = heightBlendAvailable && terrain.materialTemplate.HasProperty(kEnableHeightBlend) && (terrain.materialTemplate.GetFloat(kEnableHeightBlend) > 0);
|
||||
|
||||
terrainLayer.diffuseTexture = EditorGUILayout.ObjectField(styles.diffuseTexture, terrainLayer.diffuseTexture, typeof(Texture2D), false) as Texture2D;
|
||||
TerrainLayerUtility.ValidateDiffuseTextureUI(terrainLayer.diffuseTexture);
|
||||
|
||||
var diffuseRemapMin = terrainLayer.diffuseRemapMin;
|
||||
var diffuseRemapMax = terrainLayer.diffuseRemapMax;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
bool enableDensity = false;
|
||||
if (terrainLayer.diffuseTexture != null)
|
||||
{
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
rect.y += 16 + 4;
|
||||
rect.width = EditorGUIUtility.labelWidth + 64;
|
||||
rect.height = 16;
|
||||
|
||||
++EditorGUI.indentLevel;
|
||||
|
||||
var diffuseTint = new Color(diffuseRemapMax.x, diffuseRemapMax.y, diffuseRemapMax.z);
|
||||
diffuseTint = EditorGUI.ColorField(rect, styles.colorTint, diffuseTint, true, false, false);
|
||||
diffuseRemapMax.x = diffuseTint.r;
|
||||
diffuseRemapMax.y = diffuseTint.g;
|
||||
diffuseRemapMax.z = diffuseTint.b;
|
||||
diffuseRemapMin.x = diffuseRemapMin.y = diffuseRemapMin.z = 0;
|
||||
|
||||
if (!heightBlend)
|
||||
{
|
||||
rect.y = rect.yMax + 2;
|
||||
enableDensity = EditorGUI.Toggle(rect, styles.opacityAsDensity, diffuseRemapMin.w > 0);
|
||||
}
|
||||
|
||||
--EditorGUI.indentLevel;
|
||||
}
|
||||
diffuseRemapMax.w = 1;
|
||||
diffuseRemapMin.w = enableDensity ? 1 : 0;
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
terrainLayer.diffuseRemapMin = diffuseRemapMin;
|
||||
terrainLayer.diffuseRemapMax = diffuseRemapMax;
|
||||
}
|
||||
|
||||
// Display normal map UI
|
||||
terrainLayer.normalMapTexture = EditorGUILayout.ObjectField(styles.normalMapTexture, terrainLayer.normalMapTexture, typeof(Texture2D), false) as Texture2D;
|
||||
TerrainLayerUtility.ValidateNormalMapTextureUI(terrainLayer.normalMapTexture, TerrainLayerUtility.CheckNormalMapTextureType(terrainLayer.normalMapTexture));
|
||||
|
||||
if (terrainLayer.normalMapTexture != null)
|
||||
{
|
||||
var rect = GUILayoutUtility.GetLastRect();
|
||||
rect.y += 16 + 4;
|
||||
rect.width = EditorGUIUtility.labelWidth + 64;
|
||||
rect.height = 16;
|
||||
|
||||
++EditorGUI.indentLevel;
|
||||
terrainLayer.normalScale = EditorGUI.FloatField(rect, styles.normalScale, terrainLayer.normalScale);
|
||||
--EditorGUI.indentLevel;
|
||||
}
|
||||
|
||||
// Display the mask map UI and the remap controls
|
||||
terrainLayer.maskMapTexture = EditorGUILayout.ObjectField(heightBlend ? styles.maskMapTexture : styles.maskMapTextureWithoutHeight, terrainLayer.maskMapTexture, typeof(Texture2D), false) as Texture2D;
|
||||
TerrainLayerUtility.ValidateMaskMapTextureUI(terrainLayer.maskMapTexture);
|
||||
|
||||
var maskMapRemapMin = terrainLayer.maskMapRemapMin;
|
||||
var maskMapRemapMax = terrainLayer.maskMapRemapMax;
|
||||
var smoothness = terrainLayer.smoothness;
|
||||
var metallic = terrainLayer.metallic;
|
||||
|
||||
++EditorGUI.indentLevel;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
m_ShowChannelRemapping = EditorGUILayout.Foldout(m_ShowChannelRemapping, terrainLayer.maskMapTexture != null ? s_Styles.channelRemapping : s_Styles.defaultValues);
|
||||
|
||||
if (m_ShowChannelRemapping)
|
||||
{
|
||||
if (terrainLayer.maskMapTexture != null)
|
||||
{
|
||||
float min, max;
|
||||
min = maskMapRemapMin.x; max = maskMapRemapMax.x;
|
||||
EditorGUILayout.MinMaxSlider(s_Styles.metallic, ref min, ref max, 0, 1);
|
||||
maskMapRemapMin.x = min; maskMapRemapMax.x = max;
|
||||
|
||||
min = maskMapRemapMin.y; max = maskMapRemapMax.y;
|
||||
EditorGUILayout.MinMaxSlider(s_Styles.ao, ref min, ref max, 0, 1);
|
||||
maskMapRemapMin.y = min; maskMapRemapMax.y = max;
|
||||
|
||||
if (heightBlend)
|
||||
{
|
||||
EditorGUILayout.LabelField(styles.height);
|
||||
++EditorGUI.indentLevel;
|
||||
m_HeightParametrization = (HeightParametrization)EditorGUILayout.EnumPopup(styles.heightParametrization, m_HeightParametrization);
|
||||
if (m_HeightParametrization == HeightParametrization.Amplitude)
|
||||
{
|
||||
// (height - heightBase) * amplitude
|
||||
float amplitude = Mathf.Max(maskMapRemapMax.z - maskMapRemapMin.z, Mathf.Epsilon); // to avoid divide by zero
|
||||
float heightBase = maskMapRemapMin.z / amplitude;
|
||||
amplitude = EditorGUILayout.FloatField(styles.heightAmplitude, amplitude * 100) / 100;
|
||||
heightBase = EditorGUILayout.FloatField(styles.heightBase, heightBase * 100) / 100;
|
||||
maskMapRemapMin.z = heightBase * amplitude;
|
||||
maskMapRemapMax.z = (1.0f - heightBase) * amplitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
maskMapRemapMin.z = EditorGUILayout.FloatField(styles.heightMin, maskMapRemapMin.z * 100) / 100;
|
||||
maskMapRemapMax.z = EditorGUILayout.FloatField(styles.heightMax, maskMapRemapMax.z * 100) / 100;
|
||||
}
|
||||
--EditorGUI.indentLevel;
|
||||
}
|
||||
|
||||
min = maskMapRemapMin.w; max = maskMapRemapMax.w;
|
||||
EditorGUILayout.MinMaxSlider(s_Styles.smoothness, ref min, ref max, 0, 1);
|
||||
maskMapRemapMin.w = min; maskMapRemapMax.w = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
metallic = EditorGUILayout.Slider(s_Styles.metallic, metallic, 0, 1);
|
||||
// AO and Height are still exclusively controlled via the maskRemap controls
|
||||
// metallic and smoothness have their own values as fields within the LayerData.
|
||||
maskMapRemapMax.y = EditorGUILayout.Slider(s_Styles.ao, maskMapRemapMax.y, 0, 1);
|
||||
if (heightBlend)
|
||||
{
|
||||
maskMapRemapMax.z = EditorGUILayout.FloatField(s_Styles.heightCm, maskMapRemapMax.z * 100) / 100;
|
||||
}
|
||||
|
||||
// There's a possibility that someone could slide max below the existing min value
|
||||
// so we'll just protect against that by locking the min value down a little bit.
|
||||
// In the case of height (Z), we are trying to set min to no lower than zero value unless
|
||||
// max goes negative. Zero is a good sensible value for the minimum. For AO (Y), we
|
||||
// don't need this extra protection step because the UI blocks us from going negative
|
||||
// anyway. In both cases, pushing the slider below the min value will lock them together,
|
||||
// but min will be "left behind" if you go back up.
|
||||
maskMapRemapMin.y = Mathf.Min(maskMapRemapMin.y, maskMapRemapMax.y);
|
||||
maskMapRemapMin.z = Mathf.Min(Mathf.Max(0, maskMapRemapMin.z), maskMapRemapMax.z);
|
||||
|
||||
if (TextureHasAlpha(terrainLayer.diffuseTexture))
|
||||
{
|
||||
GUIStyle warnStyle = new GUIStyle(GUI.skin.label);
|
||||
warnStyle.wordWrap = true;
|
||||
GUILayout.Label("Smoothness is controlled by diffuse alpha channel", warnStyle);
|
||||
}
|
||||
else
|
||||
smoothness = EditorGUILayout.Slider(s_Styles.smoothness, smoothness, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
terrainLayer.maskMapRemapMin = maskMapRemapMin;
|
||||
terrainLayer.maskMapRemapMax = maskMapRemapMax;
|
||||
terrainLayer.smoothness = smoothness;
|
||||
terrainLayer.metallic = metallic;
|
||||
}
|
||||
--EditorGUI.indentLevel;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
TerrainLayerUtility.TilingSettingsUI(terrainLayer);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user