您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
382 行
22 KiB
382 行
22 KiB
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Experimental.Rendering.HDPipeline;
|
|
|
|
namespace UnityEditor.Experimental.Rendering.HDPipeline
|
|
{
|
|
// A Material can be authored from the shader graph or by hand. When written by hand we need to provide an inspector.
|
|
// Such a Material will share some properties between it various variant (shader graph variant or hand authored variant).
|
|
// This is the purpose of BaseLitGUI. It contain all properties that are common to all Material based on Lit template.
|
|
// For the default hand written Lit material see LitUI.cs that contain specific properties for our default implementation.
|
|
public abstract class BaseLitGUI : BaseUnlitGUI
|
|
{
|
|
protected static class StylesBaseLit
|
|
{
|
|
public static GUIContent doubleSidedNormalModeText = new GUIContent("Normal mode", "This will modify the normal base on the selected mode. None: untouch, Mirror: Mirror the normal with vertex normal plane, Flip: Flip the normal");
|
|
public static GUIContent depthOffsetEnableText = new GUIContent("Enable Depth Offset", "EnableDepthOffset on this shader (Use with heightmap)");
|
|
|
|
// Material ID
|
|
public static GUIContent materialIDText = new GUIContent("Material type", "Subsurface Scattering: enable for translucent materials such as skin, vegetation, fruit, marble, wax and milk.");
|
|
|
|
// Per pixel displacement
|
|
public static GUIContent enablePerPixelDisplacementText = new GUIContent("Enable Per Pixel Displacement", "Per pixel displacement work best with flat surfaces. This is an expensive features and should be enable wisely. Typical use case is paved road.");
|
|
public static GUIContent ppdMinSamplesText = new GUIContent("Minimum steps", "Minimum steps (texture sample) to use with per pixel displacement mapping");
|
|
public static GUIContent ppdMaxSamplesText = new GUIContent("Maximum steps", "Maximum steps (texture sample) to use with per pixel displacement mapping");
|
|
public static GUIContent ppdLodThresholdText = new GUIContent("Fading mip level start", "Starting heightmap mipmap lod number where the parallax occlusion mapping effect start to disappear");
|
|
public static GUIContent perPixelDisplacementObjectScaleText = new GUIContent("Lock with object scale", "Per Pixel displacement will take into account the tiling scale - Only work with uniform positive scale");
|
|
|
|
// Vertex displacement
|
|
public static string vertexDisplacementText = "Vertex displacement";
|
|
|
|
public static GUIContent enableVertexDisplacementText = new GUIContent("Enable vertex displacement", "Use heightmap as a displacement map. Displacement map is use to move vertex position in local space");
|
|
public static GUIContent vertexDisplacementObjectScaleText = new GUIContent("Lock with object scale", "Vertex displacement will take into account the object scale - Only work with uniform positive scale");
|
|
public static GUIContent vertexDisplacementTilingScaleText = new GUIContent("Lock with heightmap tiling", "Vertex displacement will take into account the tiling scale - Only work with uniform positive scale");
|
|
|
|
// Tessellation
|
|
public static string tessellationModeText = "Tessellation Mode";
|
|
public static readonly string[] tessellationModeNames = Enum.GetNames(typeof(TessellationMode));
|
|
|
|
public static GUIContent tessellationText = new GUIContent("Tessellation options", "Tessellation options");
|
|
public static GUIContent tessellationFactorText = new GUIContent("Tessellation factor", "This value is the tessellation factor use for tessellation, higher mean more tessellated");
|
|
public static GUIContent tessellationFactorMinDistanceText = new GUIContent("Start fade distance", "Distance (in unity unit) at which the tessellation start to fade out. Must be inferior at Max distance");
|
|
public static GUIContent tessellationFactorMaxDistanceText = new GUIContent("End fade distance", "Maximum distance (in unity unit) to the camera where triangle are tessellated");
|
|
public static GUIContent tessellationFactorTriangleSizeText = new GUIContent("Triangle size", "Desired screen space sized of triangle (in pixel). Smaller value mean smaller triangle.");
|
|
public static GUIContent tessellationShapeFactorText = new GUIContent("Shape factor", "Strength of Phong tessellation shape (lerp factor)");
|
|
public static GUIContent tessellationBackFaceCullEpsilonText = new GUIContent("Triangle culling Epsilon", "If -1.0 back face culling is enabled for tessellation, higher number mean more aggressive culling and better performance");
|
|
|
|
// Vertex animation
|
|
public static string vertexAnimation = "Vertex animation";
|
|
|
|
// Wind
|
|
public static GUIContent windText = new GUIContent("Enable Wind");
|
|
public static GUIContent windInitialBendText = new GUIContent("Initial Bend");
|
|
public static GUIContent windStiffnessText = new GUIContent("Stiffness");
|
|
public static GUIContent windDragText = new GUIContent("Drag");
|
|
public static GUIContent windShiverDragText = new GUIContent("Shiver Drag");
|
|
public static GUIContent windShiverDirectionalityText = new GUIContent("Shiver Directionality");
|
|
}
|
|
|
|
public enum DoubleSidedNormalMode
|
|
{
|
|
None,
|
|
Mirror,
|
|
Flip
|
|
}
|
|
|
|
public enum TessellationMode
|
|
{
|
|
None,
|
|
Phong
|
|
}
|
|
|
|
protected MaterialProperty doubleSidedNormalMode = null;
|
|
protected const string kDoubleSidedNormalMode = "_DoubleSidedNormalMode";
|
|
protected MaterialProperty depthOffsetEnable = null;
|
|
protected const string kDepthOffsetEnable = "_DepthOffsetEnable";
|
|
|
|
// Properties
|
|
// Material ID
|
|
protected MaterialProperty materialID = null;
|
|
protected const string kMaterialID = "_MaterialID";
|
|
|
|
protected const string kStencilRef = "_StencilRef";
|
|
|
|
// Per pixel displacement params
|
|
protected MaterialProperty enablePerPixelDisplacement = null;
|
|
protected const string kEnablePerPixelDisplacement = "_EnablePerPixelDisplacement";
|
|
protected MaterialProperty ppdMinSamples = null;
|
|
protected const string kPpdMinSamples = "_PPDMinSamples";
|
|
protected MaterialProperty ppdMaxSamples = null;
|
|
protected const string kPpdMaxSamples = "_PPDMaxSamples";
|
|
protected MaterialProperty ppdLodThreshold = null;
|
|
protected const string kPpdLodThreshold = "_PPDLodThreshold";
|
|
protected MaterialProperty perPixelDisplacementObjectScale = null;
|
|
protected const string kPerPixelDisplacementObjectScale = "_PerPixelDisplacementObjectScale";
|
|
|
|
// Vertex displacement
|
|
protected MaterialProperty enableVertexDisplacement = null;
|
|
protected const string kEnableVertexDisplacement = "_EnableVertexDisplacement";
|
|
protected MaterialProperty vertexDisplacementObjectScale = null;
|
|
protected const string kVertexDisplacementObjectScale = "_VertexDisplacementObjectScale";
|
|
protected MaterialProperty vertexDisplacementTilingScale = null;
|
|
protected const string kVertexDisplacementTilingScale = "_VertexDisplacementTilingScale";
|
|
|
|
// Wind
|
|
protected MaterialProperty windEnable = null;
|
|
protected const string kWindEnabled = "_EnableWind";
|
|
protected MaterialProperty windInitialBend = null;
|
|
protected const string kWindInitialBend = "_InitialBend";
|
|
protected MaterialProperty windStiffness = null;
|
|
protected const string kWindStiffness = "_Stiffness";
|
|
protected MaterialProperty windDrag = null;
|
|
protected const string kWindDrag = "_Drag";
|
|
protected MaterialProperty windShiverDrag = null;
|
|
protected const string kWindShiverDrag = "_ShiverDrag";
|
|
protected MaterialProperty windShiverDirectionality = null;
|
|
protected const string kWindShiverDirectionality = "_ShiverDirectionality";
|
|
|
|
// tessellation params
|
|
protected MaterialProperty tessellationMode = null;
|
|
protected const string kTessellationMode = "_TessellationMode";
|
|
protected MaterialProperty tessellationFactor = null;
|
|
protected const string kTessellationFactor = "_TessellationFactor";
|
|
protected MaterialProperty tessellationFactorMinDistance = null;
|
|
protected const string kTessellationFactorMinDistance = "_TessellationFactorMinDistance";
|
|
protected MaterialProperty tessellationFactorMaxDistance = null;
|
|
protected const string kTessellationFactorMaxDistance = "_TessellationFactorMaxDistance";
|
|
protected MaterialProperty tessellationFactorTriangleSize = null;
|
|
protected const string kTessellationFactorTriangleSize = "_TessellationFactorTriangleSize";
|
|
protected MaterialProperty tessellationShapeFactor = null;
|
|
protected const string kTessellationShapeFactor = "_TessellationShapeFactor";
|
|
protected MaterialProperty tessellationBackFaceCullEpsilon = null;
|
|
protected const string kTessellationBackFaceCullEpsilon = "_TessellationBackFaceCullEpsilon";
|
|
|
|
protected override void FindBaseMaterialProperties(MaterialProperty[] props)
|
|
{
|
|
base.FindBaseMaterialProperties(props);
|
|
|
|
doubleSidedNormalMode = FindProperty(kDoubleSidedNormalMode, props);
|
|
depthOffsetEnable = FindProperty(kDepthOffsetEnable, props);
|
|
|
|
// MaterialID
|
|
materialID = FindProperty(kMaterialID, props, false); // LayeredLit is force to be standard for now, so materialID could not exist
|
|
|
|
// Per pixel displacement
|
|
enablePerPixelDisplacement = FindProperty(kEnablePerPixelDisplacement, props);
|
|
ppdMinSamples = FindProperty(kPpdMinSamples, props);
|
|
ppdMaxSamples = FindProperty(kPpdMaxSamples, props);
|
|
ppdLodThreshold = FindProperty(kPpdLodThreshold, props);
|
|
perPixelDisplacementObjectScale = FindProperty(kPerPixelDisplacementObjectScale, props);
|
|
|
|
// vertex displacement
|
|
enableVertexDisplacement = FindProperty(kEnableVertexDisplacement, props);
|
|
vertexDisplacementObjectScale = FindProperty(kVertexDisplacementObjectScale, props);
|
|
vertexDisplacementTilingScale = FindProperty(kVertexDisplacementTilingScale, props);
|
|
|
|
// tessellation specific, silent if not found
|
|
tessellationMode = FindProperty(kTessellationMode, props, false);
|
|
tessellationFactor = FindProperty(kTessellationFactor, props, false);
|
|
tessellationFactorMinDistance = FindProperty(kTessellationFactorMinDistance, props, false);
|
|
tessellationFactorMaxDistance = FindProperty(kTessellationFactorMaxDistance, props, false);
|
|
tessellationFactorTriangleSize = FindProperty(kTessellationFactorTriangleSize, props, false);
|
|
tessellationShapeFactor = FindProperty(kTessellationShapeFactor, props, false);
|
|
tessellationBackFaceCullEpsilon = FindProperty(kTessellationBackFaceCullEpsilon, props, false);
|
|
|
|
// Wind
|
|
windEnable = FindProperty(kWindEnabled, props);
|
|
windInitialBend = FindProperty(kWindInitialBend, props);
|
|
windStiffness = FindProperty(kWindStiffness, props);
|
|
windDrag = FindProperty(kWindDrag, props);
|
|
windShiverDrag = FindProperty(kWindShiverDrag, props);
|
|
windShiverDirectionality = FindProperty(kWindShiverDirectionality, props);
|
|
}
|
|
|
|
void TessellationModePopup()
|
|
{
|
|
EditorGUI.showMixedValue = tessellationMode.hasMixedValue;
|
|
var mode = (TessellationMode)tessellationMode.floatValue;
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
mode = (TessellationMode)EditorGUILayout.Popup(StylesBaseLit.tessellationModeText, (int)mode, StylesBaseLit.tessellationModeNames);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
m_MaterialEditor.RegisterPropertyChangeUndo("Tessellation Mode");
|
|
tessellationMode.floatValue = (float)mode;
|
|
}
|
|
|
|
EditorGUI.showMixedValue = false;
|
|
}
|
|
|
|
protected override void BaseMaterialPropertiesGUI()
|
|
{
|
|
base.BaseMaterialPropertiesGUI();
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
// This follow double sided option
|
|
if (doubleSidedEnable.floatValue > 0.0f)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
m_MaterialEditor.ShaderProperty(doubleSidedNormalMode, StylesBaseLit.doubleSidedNormalModeText);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
if (materialID != null)
|
|
m_MaterialEditor.ShaderProperty(materialID, StylesBaseLit.materialIDText);
|
|
|
|
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, StylesBaseLit.enablePerPixelDisplacementText);
|
|
if (enablePerPixelDisplacement.floatValue > 0.0f)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
m_MaterialEditor.ShaderProperty(ppdMinSamples, StylesBaseLit.ppdMinSamplesText);
|
|
m_MaterialEditor.ShaderProperty(ppdMaxSamples, StylesBaseLit.ppdMaxSamplesText);
|
|
ppdMinSamples.floatValue = Mathf.Min(ppdMinSamples.floatValue, ppdMaxSamples.floatValue);
|
|
m_MaterialEditor.ShaderProperty(ppdLodThreshold, StylesBaseLit.ppdLodThresholdText);
|
|
//m_MaterialEditor.ShaderProperty(perPixelDisplacementObjectScale, StylesBaseLit.perPixelDisplacementObjectScaleText);
|
|
m_MaterialEditor.ShaderProperty(depthOffsetEnable, StylesBaseLit.depthOffsetEnableText);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
|
|
// Vertex displacement options
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField(StylesBaseLit.vertexDisplacementText, EditorStyles.boldLabel);
|
|
EditorGUI.indentLevel++;
|
|
|
|
m_MaterialEditor.ShaderProperty(enableVertexDisplacement, StylesBaseLit.enableVertexDisplacementText);
|
|
if (enableVertexDisplacement.floatValue > 0.0f)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
m_MaterialEditor.ShaderProperty(vertexDisplacementObjectScale, StylesBaseLit.vertexDisplacementObjectScaleText);
|
|
m_MaterialEditor.ShaderProperty(vertexDisplacementTilingScale, StylesBaseLit.vertexDisplacementTilingScaleText);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
|
|
// Display tessellation option if it exist
|
|
if (tessellationMode != null)
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField(StylesBaseLit.tessellationText, EditorStyles.boldLabel);
|
|
EditorGUI.indentLevel++;
|
|
TessellationModePopup();
|
|
m_MaterialEditor.ShaderProperty(tessellationFactor, StylesBaseLit.tessellationFactorText);
|
|
m_MaterialEditor.ShaderProperty(tessellationFactorMinDistance, StylesBaseLit.tessellationFactorMinDistanceText);
|
|
m_MaterialEditor.ShaderProperty(tessellationFactorMaxDistance, StylesBaseLit.tessellationFactorMaxDistanceText);
|
|
// clamp min distance to be below max distance
|
|
tessellationFactorMinDistance.floatValue = Math.Min(tessellationFactorMaxDistance.floatValue, tessellationFactorMinDistance.floatValue);
|
|
m_MaterialEditor.ShaderProperty(tessellationFactorTriangleSize, StylesBaseLit.tessellationFactorTriangleSizeText);
|
|
if ((TessellationMode)tessellationMode.floatValue == TessellationMode.Phong)
|
|
{
|
|
m_MaterialEditor.ShaderProperty(tessellationShapeFactor, StylesBaseLit.tessellationShapeFactorText);
|
|
}
|
|
if (doubleSidedEnable.floatValue == 0.0)
|
|
{
|
|
m_MaterialEditor.ShaderProperty(tessellationBackFaceCullEpsilon, StylesBaseLit.tessellationBackFaceCullEpsilonText);
|
|
}
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
protected override void VertexAnimationPropertiesGUI()
|
|
{
|
|
EditorGUILayout.LabelField(StylesBaseLit.vertexAnimation, EditorStyles.boldLabel);
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
m_MaterialEditor.ShaderProperty(windEnable, StylesBaseLit.windText);
|
|
if (!windEnable.hasMixedValue && windEnable.floatValue > 0.0f)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
m_MaterialEditor.ShaderProperty(windInitialBend, StylesBaseLit.windInitialBendText);
|
|
m_MaterialEditor.ShaderProperty(windStiffness, StylesBaseLit.windStiffnessText);
|
|
m_MaterialEditor.ShaderProperty(windDrag, StylesBaseLit.windDragText);
|
|
m_MaterialEditor.ShaderProperty(windShiverDrag, StylesBaseLit.windShiverDragText);
|
|
m_MaterialEditor.ShaderProperty(windShiverDirectionality, StylesBaseLit.windShiverDirectionalityText);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
// All Setup Keyword functions must be static. It allow to create script to automatically update the shaders with a script if code change
|
|
static public void SetupBaseLitKeywords(Material material)
|
|
{
|
|
SetupBaseUnlitKeywords(material);
|
|
|
|
bool doubleSidedEnable = material.GetFloat(kDoubleSidedEnable) > 0.0f;
|
|
|
|
if (doubleSidedEnable)
|
|
{
|
|
DoubleSidedNormalMode doubleSidedNormalMode = (DoubleSidedNormalMode)material.GetFloat(kDoubleSidedNormalMode);
|
|
switch (doubleSidedNormalMode)
|
|
{
|
|
case DoubleSidedNormalMode.None:
|
|
material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, 1.0f, 0.0f));
|
|
break;
|
|
|
|
case DoubleSidedNormalMode.Mirror: // Mirror mode (in tangent space)
|
|
material.SetVector("_DoubleSidedConstants", new Vector4(1.0f, 1.0f, -1.0f, 0.0f));
|
|
break;
|
|
|
|
case DoubleSidedNormalMode.Flip: // Flip mode (in tangent space)
|
|
material.SetVector("_DoubleSidedConstants", new Vector4(-1.0f, -1.0f, -1.0f, 0.0f));
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Depth offset is only enabled if per pixel displacement is
|
|
bool depthOffsetEnable = (material.GetFloat(kDepthOffsetEnable) > 0.0f) && (material.GetFloat(kEnablePerPixelDisplacement) > 0.0f);
|
|
SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable);
|
|
|
|
// Set the reference value for the stencil test.
|
|
int stencilRef = (int)StencilLightingUsage.RegularLighting;
|
|
if (material.HasProperty(kMaterialID))
|
|
{
|
|
if ((int)material.GetFloat(kMaterialID) == (int)UnityEngine.Experimental.Rendering.HDPipeline.Lit.MaterialId.LitSSS)
|
|
{
|
|
stencilRef = (int)StencilLightingUsage.SplitLighting;
|
|
}
|
|
}
|
|
material.SetInt(kStencilRef, stencilRef);
|
|
|
|
bool enablePerPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) > 0.0f;
|
|
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", enablePerPixelDisplacement);
|
|
|
|
bool perPixelDisplacementObjectScale = material.GetFloat(kPerPixelDisplacementObjectScale) > 0.0;
|
|
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT_OBJECT_SCALE", perPixelDisplacementObjectScale && enablePerPixelDisplacement);
|
|
|
|
bool enableVertexDisplacement = material.GetFloat(kEnableVertexDisplacement) > 0.0f;
|
|
SetKeyword(material, "_VERTEX_DISPLACEMENT", enableVertexDisplacement);
|
|
|
|
bool vertexDisplacementObjectScaleEnable = material.GetFloat(kVertexDisplacementObjectScale) > 0.0;
|
|
SetKeyword(material, "_VERTEX_DISPLACEMENT_OBJECT_SCALE", vertexDisplacementObjectScaleEnable && enableVertexDisplacement);
|
|
|
|
bool vertexDisplacementTilingScaleEnable = material.GetFloat(kVertexDisplacementTilingScale) > 0.0;
|
|
SetKeyword(material, "_VERTEX_DISPLACEMENT_TILING_SCALE", vertexDisplacementTilingScaleEnable && enableVertexDisplacement);
|
|
|
|
bool windEnabled = material.GetFloat(kWindEnabled) > 0.0f;
|
|
SetKeyword(material, "_VERTEX_WIND", windEnabled);
|
|
|
|
if (material.HasProperty(kTessellationMode))
|
|
{
|
|
TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode);
|
|
SetKeyword(material, "_TESSELLATION_PHONG", tessMode == TessellationMode.Phong);
|
|
}
|
|
}
|
|
|
|
static public void SetupBaseLitMaterialPass(Material material)
|
|
{
|
|
bool distortionEnable = material.GetFloat(kDistortionEnable) > 0.0f;
|
|
bool distortionOnly = material.GetFloat(kDistortionOnly) > 0.0f;
|
|
|
|
if (distortionEnable && distortionOnly)
|
|
{
|
|
// Disable all passes except distortion (setup in BaseUnlitUI.cs) and debug passes (to visualize distortion)
|
|
material.SetShaderPassEnabled("GBuffer", false);
|
|
material.SetShaderPassEnabled("GBufferDisplayDebug", true);
|
|
material.SetShaderPassEnabled("Meta", false);
|
|
material.SetShaderPassEnabled("ShadowCaster", false);
|
|
material.SetShaderPassEnabled("DepthOnly", false);
|
|
material.SetShaderPassEnabled("MotionVectors", false);
|
|
material.SetShaderPassEnabled("Forward", false);
|
|
material.SetShaderPassEnabled("ForwardDisplayDebug", true);
|
|
}
|
|
else
|
|
{
|
|
// Enable all passes except distortion (setup in BaseUnlitUI.cs)
|
|
material.SetShaderPassEnabled("GBuffer", true);
|
|
material.SetShaderPassEnabled("GBufferDisplayDebug", true);
|
|
material.SetShaderPassEnabled("Meta", true);
|
|
material.SetShaderPassEnabled("ShadowCaster", true);
|
|
material.SetShaderPassEnabled("DepthOnly", true);
|
|
material.SetShaderPassEnabled("MotionVectors", true);
|
|
material.SetShaderPassEnabled("Forward", true);
|
|
material.SetShaderPassEnabled("ForwardDisplayDebug", true);
|
|
}
|
|
}
|
|
}
|
|
} // namespace UnityEditor
|