您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

693 行
39 KiB

using System;
using UnityEngine;
using UnityEngine.Experimental.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 BaseUnlitGUI : ShaderGUI
{
protected static class StylesBaseUnlit
{
public static string TransparencyInputsText = "Transparency Inputs";
public static string optionText = "Surface options";
public static string surfaceTypeText = "Surface Type";
public static string blendModeText = "Blend Mode";
public static readonly string[] surfaceTypeNames = Enum.GetNames(typeof(SurfaceType));
public static readonly string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
public static readonly int[] blendModeValues = Enum.GetValues(typeof(BlendMode)) as int[];
public static GUIContent alphaCutoffEnableText = new GUIContent("Alpha Cutoff Enable", "Threshold for alpha cutoff");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
public static GUIContent alphaCutoffShadowText = new GUIContent("Alpha Cutoff Shadow", "Threshold for alpha cutoff in case of shadow pass");
public static GUIContent alphaCutoffPrepassText = new GUIContent("Alpha Cutoff Prepass", "Threshold for alpha cutoff in case of depth prepass");
public static GUIContent alphaCutoffPostpassText = new GUIContent("Alpha Cutoff Postpass", "Threshold for alpha cutoff in case of depth postpass");
public static GUIContent transparentDepthPrepassEnableText = new GUIContent("Enable transparent depth prepass", "It allow to to fill depth buffer to improve sorting");
public static GUIContent transparentDepthPostpassEnableText = new GUIContent("Enable transparent depth postpass", "It allow to fill depth buffer for postprocess effect like DOF");
public static GUIContent transparentBackfaceEnableText = new GUIContent("Enable back then front rendering", "It allow to better sort transparent mesh by first rendering back faces then front faces in two separate drawcall");
public static GUIContent transparentSortPriorityText = new GUIContent("Transparent Sort Priority", "Allow to define priority (from -100 to +100) to solve sorting issue with transparent");
public static GUIContent enableTransparentFogText = new GUIContent("Enable fog", "Enable fog on transparent material");
public static GUIContent enableBlendModePreserveSpecularLightingText = new GUIContent("Blend preserve specular lighting", "Blend mode will only affect diffuse lighting, allowing correct specular lighting (reflection) on transparent object");
public static GUIContent doubleSidedEnableText = new GUIContent("Double Sided", "This will render the two face of the objects (disable backface culling) and flip/mirror normal");
public static GUIContent distortionEnableText = new GUIContent("Distortion", "Enable distortion on this shader");
public static GUIContent distortionOnlyText = new GUIContent("Distortion Only", "This shader will only be use to render distortion");
public static GUIContent distortionDepthTestText = new GUIContent("Distortion Depth Test", "Enable the depth test for distortion");
public static GUIContent distortionVectorMapText = new GUIContent("Distortion Vector Map - Dist(RG) Blur(B)", "Vector Map for the distorsion - Dist(RG) Blur(B)");
public static GUIContent distortionBlendModeText = new GUIContent("Distortion Blend Mode", "Distortion Blend Mode");
public static GUIContent distortionScaleText = new GUIContent("Distortion Scale", "Distortion Scale");
public static GUIContent distortionBlurScaleText = new GUIContent("Distortion Blur Scale", "Distortion Blur Scale");
public static GUIContent distortionBlurRemappingText = new GUIContent("Distortion Blur Remapping", "Distortion Blur Remapping");
public static GUIContent transparentPrepassText = new GUIContent("Pre Refraction Pass", "Render objects before the refraction pass");
public static GUIContent enableMotionVectorForVertexAnimationText = new GUIContent("Enable MotionVector For Vertex Animation", "This will enable an object motion vector pass for this material. Useful if wind animation is enabled or if displacement map is animated");
public static string advancedText = "Advanced Options";
}
public enum SurfaceType
{
Opaque,
Transparent
}
// Enum values are hardcoded for retro-compatibility. Don't change them.
public enum BlendMode
{
Alpha = 0,
Additive = 1,
PremultipliedAlpha = 4
}
protected MaterialEditor m_MaterialEditor;
// Properties
protected MaterialProperty surfaceType = null;
protected const string kSurfaceType = "_SurfaceType";
protected MaterialProperty alphaCutoffEnable = null;
protected const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
protected MaterialProperty alphaCutoff = null;
protected const string kAlphaCutoff = "_AlphaCutoff";
protected MaterialProperty alphaCutoffShadow = null;
protected const string kAlphaCutoffShadow = "_AlphaCutoffShadow";
protected MaterialProperty alphaCutoffPrepass = null;
protected const string kAlphaCutoffPrepass = "_AlphaCutoffPrepass";
protected MaterialProperty alphaCutoffPostpass = null;
protected const string kAlphaCutoffPostpass = "_AlphaCutoffPostpass";
protected MaterialProperty transparentDepthPrepassEnable = null;
protected const string kTransparentDepthPrepassEnable = "_TransparentDepthPrepassEnable";
protected MaterialProperty transparentDepthPostpassEnable = null;
protected const string kTransparentDepthPostpassEnable = "_TransparentDepthPostpassEnable";
protected MaterialProperty transparentBackfaceEnable = null;
protected const string kTransparentBackfaceEnable = "_TransparentBackfaceEnable";
protected MaterialProperty transparentSortPriority = null;
protected const string kTransparentSortPriority = "_TransparentSortPriority";
protected MaterialProperty doubleSidedEnable = null;
protected const string kDoubleSidedEnable = "_DoubleSidedEnable";
protected MaterialProperty blendMode = null;
protected const string kBlendMode = "_BlendMode";
protected MaterialProperty distortionEnable = null;
protected const string kDistortionEnable = "_DistortionEnable";
protected MaterialProperty distortionOnly = null;
protected const string kDistortionOnly = "_DistortionOnly";
protected MaterialProperty distortionDepthTest = null;
protected const string kDistortionDepthTest = "_DistortionDepthTest";
protected MaterialProperty distortionVectorMap = null;
protected const string kDistortionVectorMap = "_DistortionVectorMap";
protected MaterialProperty distortionBlendMode = null;
protected const string kDistortionBlendMode = "_DistortionBlendMode";
protected MaterialProperty distortionScale = null;
protected const string kDistortionScale = "_DistortionScale";
protected MaterialProperty distortionVectorScale = null;
protected const string kDistortionVectorScale = "_DistortionVectorScale";
protected MaterialProperty distortionVectorBias = null;
protected const string kDistortionVectorBias = "_DistortionVectorBias";
protected MaterialProperty distortionBlurScale = null;
protected const string kDistortionBlurScale = "_DistortionBlurScale";
protected MaterialProperty distortionBlurRemapMin = null;
protected const string kDistortionBlurRemapMin = "_DistortionBlurRemapMin";
protected MaterialProperty distortionBlurRemapMax = null;
protected const string kDistortionBlurRemapMax = "_DistortionBlurRemapMax";
protected MaterialProperty preRefractionPass = null;
protected const string kPreRefractionPass = "_PreRefractionPass";
protected MaterialProperty enableFogOnTransparent = null;
protected const string kEnableFogOnTransparent = "_EnableFogOnTransparent";
protected MaterialProperty enableBlendModePreserveSpecularLighting = null;
protected const string kEnableBlendModePreserveSpecularLighting = "_EnableBlendModePreserveSpecularLighting";
protected MaterialProperty enableMotionVectorForVertexAnimation = null;
protected const string kEnableMotionVectorForVertexAnimation = "_EnableMotionVectorForVertexAnimation";
protected const string kZTestDepthEqualForOpaque = "_ZTestDepthEqualForOpaque";
protected const string kZTestGBuffer = "_ZTestGBuffer";
protected const string kZTestModeDistortion = "_ZTestModeDistortion";
// See comment in LitProperties.hlsl
const string kEmissionColor = "_EmissionColor";
protected virtual SurfaceType defaultSurfaceType { get { return SurfaceType.Opaque; } }
protected virtual bool showBlendModePopup { get { return true; } }
// The following set of functions are call by the ShaderGraph
// It will allow to display our common parameters + setup keyword correctly for them
protected abstract void FindMaterialProperties(MaterialProperty[] props);
protected abstract void SetupMaterialKeywordsAndPassInternal(Material material);
protected abstract void MaterialPropertiesGUI(Material material);
protected virtual void MaterialPropertiesAdvanceGUI(Material material) {}
protected abstract void VertexAnimationPropertiesGUI();
// This function will say if emissive is used or not regarding enlighten/PVR
protected virtual bool ShouldEmissionBeEnabled(Material material) { return false; }
protected virtual void FindBaseMaterialProperties(MaterialProperty[] props)
{
// Everything is optional (except surface type) so users that derive from this class can decide what they expose or not
surfaceType = FindProperty(kSurfaceType, props, false);
alphaCutoffEnable = FindProperty(kAlphaCutoffEnabled, props, false);
alphaCutoff = FindProperty(kAlphaCutoff, props, false);
alphaCutoffShadow = FindProperty(kAlphaCutoffShadow, props, false);
alphaCutoffPrepass = FindProperty(kAlphaCutoffPrepass, props, false);
alphaCutoffPostpass = FindProperty(kAlphaCutoffPostpass, props, false);
transparentDepthPrepassEnable = FindProperty(kTransparentDepthPrepassEnable, props, false);
transparentDepthPostpassEnable = FindProperty(kTransparentDepthPostpassEnable, props, false);
transparentBackfaceEnable = FindProperty(kTransparentBackfaceEnable, props, false);
transparentSortPriority = FindProperty(kTransparentSortPriority, props, false);
doubleSidedEnable = FindProperty(kDoubleSidedEnable, props, false);
blendMode = FindProperty(kBlendMode, props, false);
// Distortion is optional
distortionEnable = FindProperty(kDistortionEnable, props, false);
distortionOnly = FindProperty(kDistortionOnly, props, false);
distortionDepthTest = FindProperty(kDistortionDepthTest, props, false);
distortionVectorMap = FindProperty(kDistortionVectorMap, props, false);
distortionBlendMode = FindProperty(kDistortionBlendMode, props, false);
distortionScale = FindProperty(kDistortionScale, props, false);
distortionVectorScale = FindProperty(kDistortionVectorScale, props, false);
distortionVectorBias = FindProperty(kDistortionVectorBias, props, false);
distortionBlurScale = FindProperty(kDistortionBlurScale, props, false);
distortionBlurRemapMin = FindProperty(kDistortionBlurRemapMin, props, false);
distortionBlurRemapMax = FindProperty(kDistortionBlurRemapMax, props, false);
preRefractionPass = FindProperty(kPreRefractionPass, props, false);
enableFogOnTransparent = FindProperty(kEnableFogOnTransparent, props, false);
enableBlendModePreserveSpecularLighting = FindProperty(kEnableBlendModePreserveSpecularLighting, props, false);
enableMotionVectorForVertexAnimation = FindProperty(kEnableMotionVectorForVertexAnimation, props, false);
}
protected SurfaceType surfaceTypeValue
{
get { return surfaceType != null ? (SurfaceType)surfaceType.floatValue : defaultSurfaceType; }
}
void SurfaceTypePopup()
{
if (surfaceType == null)
return;
EditorGUI.showMixedValue = surfaceType.hasMixedValue;
var mode = (SurfaceType)surfaceType.floatValue;
EditorGUI.BeginChangeCheck();
mode = (SurfaceType)EditorGUILayout.Popup(StylesBaseUnlit.surfaceTypeText, (int)mode, StylesBaseUnlit.surfaceTypeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Surface Type");
surfaceType.floatValue = (float)mode;
}
EditorGUI.showMixedValue = false;
}
private void BlendModePopup()
{
EditorGUI.showMixedValue = blendMode.hasMixedValue;
var mode = (BlendMode)blendMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.IntPopup(StylesBaseUnlit.blendModeText, (int)mode, StylesBaseUnlit.blendModeNames, StylesBaseUnlit.blendModeValues);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Blend Mode");
blendMode.floatValue = (float)mode;
}
EditorGUI.showMixedValue = false;
}
protected virtual void BaseMaterialPropertiesGUI()
{
EditorGUILayout.LabelField(StylesBaseUnlit.optionText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
SurfaceTypePopup();
if (surfaceTypeValue == SurfaceType.Transparent)
{
if (blendMode != null && showBlendModePopup)
BlendModePopup();
EditorGUI.indentLevel++;
if (enableBlendModePreserveSpecularLighting != null && blendMode != null && showBlendModePopup)
m_MaterialEditor.ShaderProperty(enableBlendModePreserveSpecularLighting, StylesBaseUnlit.enableBlendModePreserveSpecularLightingText);
if (enableFogOnTransparent != null)
m_MaterialEditor.ShaderProperty(enableFogOnTransparent, StylesBaseUnlit.enableTransparentFogText);
if (preRefractionPass != null)
m_MaterialEditor.ShaderProperty(preRefractionPass, StylesBaseUnlit.transparentPrepassText);
EditorGUI.indentLevel--;
}
if (alphaCutoffEnable != null)
m_MaterialEditor.ShaderProperty(alphaCutoffEnable, StylesBaseUnlit.alphaCutoffEnableText);
if (alphaCutoffEnable != null && alphaCutoffEnable.floatValue == 1.0f)
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(alphaCutoff, StylesBaseUnlit.alphaCutoffText);
// With transparent object and few specific materials like Hair, we need more control on the cutoff to apply
// This allow to get a better sorting (with prepass), better shadow (better silhouettes fidelity) etc...
if (surfaceTypeValue == SurfaceType.Transparent)
{
if (alphaCutoffShadow != null)
{
m_MaterialEditor.ShaderProperty(alphaCutoffShadow, StylesBaseUnlit.alphaCutoffShadowText);
}
if (transparentDepthPrepassEnable != null)
{
m_MaterialEditor.ShaderProperty(transparentDepthPrepassEnable, StylesBaseUnlit.transparentDepthPrepassEnableText);
if (transparentDepthPrepassEnable.floatValue == 1.0f)
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(alphaCutoffPrepass, StylesBaseUnlit.alphaCutoffPrepassText);
EditorGUI.indentLevel--;
}
}
if (transparentDepthPostpassEnable != null)
{
m_MaterialEditor.ShaderProperty(transparentDepthPostpassEnable, StylesBaseUnlit.transparentDepthPostpassEnableText);
if (transparentDepthPostpassEnable.floatValue == 1.0f)
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(alphaCutoffPostpass, StylesBaseUnlit.alphaCutoffPostpassText);
EditorGUI.indentLevel--;
}
}
}
EditorGUI.indentLevel--;
}
if (transparentBackfaceEnable != null && surfaceTypeValue == SurfaceType.Transparent)
m_MaterialEditor.ShaderProperty(transparentBackfaceEnable, StylesBaseUnlit.transparentBackfaceEnableText);
if (transparentSortPriority != null && surfaceTypeValue == SurfaceType.Transparent)
{
EditorGUI.BeginChangeCheck();
m_MaterialEditor.ShaderProperty(transparentSortPriority, StylesBaseUnlit.transparentSortPriorityText);
if (EditorGUI.EndChangeCheck())
{
transparentSortPriority.floatValue = Mathf.Clamp((int)transparentSortPriority.floatValue, -(int)HDRenderQueue.k_TransparentPriorityQueueRange, (int)HDRenderQueue.k_TransparentPriorityQueueRange);
}
}
// This function must finish with double sided option (see LitUI.cs)
if (doubleSidedEnable != null)
{
m_MaterialEditor.ShaderProperty(doubleSidedEnable, StylesBaseUnlit.doubleSidedEnableText);
}
EditorGUI.indentLevel--;
}
protected void DoDistortionInputsGUI()
{
if (distortionEnable != null)
{
m_MaterialEditor.ShaderProperty(distortionEnable, StylesBaseUnlit.distortionEnableText);
if (distortionEnable.floatValue == 1.0f)
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(distortionBlendMode, StylesBaseUnlit.distortionBlendModeText);
if (distortionOnly != null)
m_MaterialEditor.ShaderProperty(distortionOnly, StylesBaseUnlit.distortionOnlyText);
m_MaterialEditor.ShaderProperty(distortionDepthTest, StylesBaseUnlit.distortionDepthTestText);
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine(StylesBaseUnlit.distortionVectorMapText, distortionVectorMap, distortionVectorScale, distortionVectorBias);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(distortionScale, StylesBaseUnlit.distortionScaleText);
m_MaterialEditor.ShaderProperty(distortionBlurScale, StylesBaseUnlit.distortionBlurScaleText);
float remapMin = distortionBlurRemapMin.floatValue;
float remapMax = distortionBlurRemapMax.floatValue;
EditorGUI.BeginChangeCheck();
EditorGUILayout.MinMaxSlider(StylesBaseUnlit.distortionBlurRemappingText, ref remapMin, ref remapMax, 0.0f, 1.0f);
if (EditorGUI.EndChangeCheck())
{
distortionBlurRemapMin.floatValue = remapMin;
distortionBlurRemapMax.floatValue = remapMax;
}
EditorGUI.indentLevel--;
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 ocde change
static public void SetupBaseUnlitKeywords(Material material)
{
bool alphaTestEnable = material.HasProperty(kAlphaCutoffEnabled) && material.GetFloat(kAlphaCutoffEnabled) > 0.0f;
CoreUtils.SetKeyword(material, "_ALPHATEST_ON", alphaTestEnable);
SurfaceType surfaceType = material.HasProperty(kSurfaceType) ? (SurfaceType)material.GetFloat(kSurfaceType) : SurfaceType.Opaque;
CoreUtils.SetKeyword(material, "_SURFACE_TYPE_TRANSPARENT", surfaceType == SurfaceType.Transparent);
bool enableBlendModePreserveSpecularLighting = (surfaceType == SurfaceType.Transparent) && material.HasProperty(kEnableBlendModePreserveSpecularLighting) && material.GetFloat(kEnableBlendModePreserveSpecularLighting) > 0.0f;
CoreUtils.SetKeyword(material, "_BLENDMODE_PRESERVE_SPECULAR_LIGHTING", enableBlendModePreserveSpecularLighting);
// These need to always been set either with opaque or transparent! So a users can switch to opaque and remove the keyword correctly
CoreUtils.SetKeyword(material, "_BLENDMODE_ALPHA", false);
CoreUtils.SetKeyword(material, "_BLENDMODE_ADD", false);
CoreUtils.SetKeyword(material, "_BLENDMODE_PRE_MULTIPLY", false);
// Alpha tested materials always have a prepass where we perform the clip.
// Then during Gbuffer pass we don't perform the clip test, so we need to use depth equal in this case.
if (alphaTestEnable)
{
material.SetInt(kZTestGBuffer, (int)UnityEngine.Rendering.CompareFunction.Equal);
}
else
{
material.SetInt(kZTestGBuffer, (int)UnityEngine.Rendering.CompareFunction.LessEqual);
}
// If the material use the kZTestDepthEqualForOpaque it mean it require depth equal test for opaque but transparent are not affected
if (material.HasProperty(kZTestDepthEqualForOpaque))
{
if (surfaceType == SurfaceType.Opaque)
material.SetInt(kZTestDepthEqualForOpaque, (int)UnityEngine.Rendering.CompareFunction.Equal);
else
material.SetInt(kZTestDepthEqualForOpaque, (int)UnityEngine.Rendering.CompareFunction.LessEqual);
}
if (surfaceType == SurfaceType.Opaque)
{
material.SetOverrideTag("RenderType", alphaTestEnable ? "TransparentCutout" : "");
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.renderQueue = alphaTestEnable ? (int)HDRenderQueue.Priority.OpaqueAlphaTest : (int)HDRenderQueue.Priority.Opaque;
}
else
{
material.SetOverrideTag("RenderType", "Transparent");
material.SetInt("_ZWrite", 0);
var isPrepass = material.HasProperty(kPreRefractionPass) && material.GetFloat(kPreRefractionPass) > 0.0f;
material.renderQueue = (int)(isPrepass ? HDRenderQueue.Priority.PreRefraction : HDRenderQueue.Priority.Transparent) + (int)material.GetFloat(kTransparentSortPriority);
if (material.HasProperty(kBlendMode))
{
BlendMode blendMode = (BlendMode)material.GetFloat(kBlendMode);
CoreUtils.SetKeyword(material, "_BLENDMODE_ALPHA", BlendMode.Alpha == blendMode);
CoreUtils.SetKeyword(material, "_BLENDMODE_ADD", BlendMode.Additive == blendMode);
CoreUtils.SetKeyword(material, "_BLENDMODE_PRE_MULTIPLY", BlendMode.PremultipliedAlpha == blendMode);
switch (blendMode)
{
// Alpha
// color: src * src_a + dst * (1 - src_a)
// src * src_a is done in the shader as it allow to reduce precision issue when using _BLENDMODE_PRESERVE_SPECULAR_LIGHTING (See Material.hlsl)
case BlendMode.Alpha:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
break;
// Additive
// color: src * src_a + dst
// src * src_a is done in the shader
case BlendMode.Additive:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
break;
// PremultipliedAlpha
// color: src * src_a + dst * (1 - src_a)
// src is supposed to have been multiplied by alpha in the texture on artists side.
case BlendMode.PremultipliedAlpha:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
break;
}
}
}
bool fogEnabled = material.HasProperty(kEnableFogOnTransparent) && material.GetFloat(kEnableFogOnTransparent) > 0.0f && surfaceType == SurfaceType.Transparent;
CoreUtils.SetKeyword(material, "_ENABLE_FOG_ON_TRANSPARENT", fogEnabled);
if (material.HasProperty(kDistortionEnable))
{
bool distortionDepthTest = material.GetFloat(kDistortionDepthTest) > 0.0f;
if (material.HasProperty(kZTestModeDistortion))
{
if (distortionDepthTest)
{
material.SetInt(kZTestModeDistortion, (int)UnityEngine.Rendering.CompareFunction.LessEqual);
}
else
{
material.SetInt(kZTestModeDistortion, (int)UnityEngine.Rendering.CompareFunction.Always);
}
}
var distortionBlendMode = material.GetInt(kDistortionBlendMode);
switch (distortionBlendMode)
{
default:
case 0: // Add
material.SetInt("_DistortionSrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DistortionDstBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DistortionBlurSrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DistortionBlurDstBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DistortionBlurBlendOp", (int)UnityEngine.Rendering.BlendOp.Max);
break;
case 1: // Multiply
material.SetInt("_DistortionSrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor);
material.SetInt("_DistortionDstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_DistortionBlurSrcBlend", (int)UnityEngine.Rendering.BlendMode.DstAlpha);
material.SetInt("_DistortionBlurDstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_DistortionBlurBlendOp", (int)UnityEngine.Rendering.BlendOp.Add);
break;
}
}
bool isBackFaceEnable = material.HasProperty(kTransparentBackfaceEnable) && material.GetFloat(kTransparentBackfaceEnable) > 0.0f && surfaceType == SurfaceType.Transparent;
bool doubleSidedEnable = material.HasProperty(kDoubleSidedEnable) && material.GetFloat(kDoubleSidedEnable) > 0.0f;
// Disable culling if double sided
material.SetInt("_CullMode", doubleSidedEnable ? (int)UnityEngine.Rendering.CullMode.Off : (int)UnityEngine.Rendering.CullMode.Back);
// We have a separate cullmode (_CullModeForward) for Forward in case we use backface then frontface rendering, need to configure it
if (isBackFaceEnable)
{
material.SetInt("_CullModeForward", (int)UnityEngine.Rendering.CullMode.Back);
}
else
{
material.SetInt("_CullModeForward", doubleSidedEnable ? (int)UnityEngine.Rendering.CullMode.Off : (int)UnityEngine.Rendering.CullMode.Back);
}
CoreUtils.SetKeyword(material, "_DOUBLESIDED_ON", doubleSidedEnable);
// A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect
// or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.
// The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.
if (material.HasProperty(kEmissionColor))
material.SetColor(kEmissionColor, Color.white); // kEmissionColor must always be white to allow our own material to control the GI (this allow to fallback from builtin unity to our system).
// as it happen with old material that it isn't the case, we force it.
MaterialEditor.FixupEmissiveFlag(material);
// Commented out for now because unfortunately we used the hard coded property names used by the GI system for our own parameters
// So we need a way to work around that before we activate this.
SetupMainTexForAlphaTestGI("_EmissiveColorMap", "_EmissiveColor", material);
// DoubleSidedGI has to be synced with our double sided toggle
var serializedObject = new SerializedObject(material);
var doubleSidedGIppt = serializedObject.FindProperty("m_DoubleSidedGI");
doubleSidedGIppt.boolValue = doubleSidedEnable;
serializedObject.ApplyModifiedProperties();
}
// This is a hack for GI. PVR looks in the shader for a texture named "_MainTex" to extract the opacity of the material for baking. In the same manner, "_Cutoff" and "_Color" are also necessary.
// Since we don't have those parameters in our shaders we need to provide a "fake" useless version of them with the right values for the GI to work.
protected static void SetupMainTexForAlphaTestGI(string colorMapPropertyName, string colorPropertyName, Material material)
{
if (material.HasProperty(colorMapPropertyName))
{
var mainTex = material.GetTexture(colorMapPropertyName);
material.SetTexture("_MainTex", mainTex);
}
if (material.HasProperty(colorPropertyName))
{
var color = material.GetColor(colorPropertyName);
material.SetColor("_Color", color);
}
if (material.HasProperty("_AlphaCutoff")) // Same for all our materials
{
var cutoff = material.GetFloat("_AlphaCutoff");
material.SetFloat("_Cutoff", cutoff);
}
}
static public void SetupBaseUnlitMaterialPass(Material material)
{
if (material.HasProperty(kDistortionEnable))
{
bool distortionEnable = material.GetFloat(kDistortionEnable) > 0.0f && ((SurfaceType)material.GetFloat(kSurfaceType) == SurfaceType.Transparent);
bool distortionOnly = false;
if (material.HasProperty(kDistortionOnly))
{
distortionOnly = material.GetFloat(kDistortionOnly) > 0.0f;
}
// If distortion only is enabled, disable all passes (except distortion and debug)
bool enablePass = !(distortionEnable && distortionOnly);
// Disable all passes except distortion
// Distortion is setup in code above
material.SetShaderPassEnabled(HDShaderPassNames.s_ForwardStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_DepthOnlyStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_DepthForwardOnlyStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_ForwardOnlyStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_GBufferStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_GBufferWithPrepassStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_MotionVectorsStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_DistortionVectorsStr, distortionEnable); // note: use distortionEnable
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentDepthPrepassStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentBackfaceStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentDepthPostpassStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_MetaStr, enablePass);
material.SetShaderPassEnabled(HDShaderPassNames.s_ShadowCasterStr, enablePass);
}
if (material.HasProperty(kTransparentDepthPrepassEnable))
{
bool depthWriteEnable = (material.GetFloat(kTransparentDepthPrepassEnable) > 0.0f) && ((SurfaceType)material.GetFloat(kSurfaceType) == SurfaceType.Transparent);
if (depthWriteEnable)
{
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentDepthPrepassStr, true);
}
else
{
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentDepthPrepassStr, false);
}
}
if (material.HasProperty(kTransparentDepthPostpassEnable))
{
bool depthWriteEnable = (material.GetFloat(kTransparentDepthPostpassEnable) > 0.0f) && ((SurfaceType)material.GetFloat(kSurfaceType) == SurfaceType.Transparent);
if (depthWriteEnable)
{
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentDepthPostpassStr, true);
}
else
{
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentDepthPostpassStr, false);
}
}
if (material.HasProperty(kTransparentBackfaceEnable))
{
bool backFaceEnable = (material.GetFloat(kTransparentBackfaceEnable) > 0.0f) && ((SurfaceType)material.GetFloat(kSurfaceType) == SurfaceType.Transparent);
if (backFaceEnable)
{
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentBackfaceStr, true);
}
else
{
material.SetShaderPassEnabled(HDShaderPassNames.s_TransparentBackfaceStr, false);
}
}
if (material.HasProperty(kEnableMotionVectorForVertexAnimation))
{
material.SetShaderPassEnabled(HDShaderPassNames.s_MotionVectorsStr, material.GetFloat(kEnableMotionVectorForVertexAnimation) > 0.0f);
}
}
// Dedicated to emissive - for emissive Enlighten/PVR
protected void DoEmissionArea(Material material)
{
// Emission for GI?
if (ShouldEmissionBeEnabled(material))
{
if (m_MaterialEditor.EmissionEnabledProperty())
{
// change the GI flag and fix it up with emissive as black if necessary
m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true);
}
}
}
public void ShaderPropertiesGUI(Material material)
{
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
//EditorGUI.indentLevel++;
BaseMaterialPropertiesGUI();
EditorGUILayout.Space();
VertexAnimationPropertiesGUI();
EditorGUILayout.Space();
MaterialPropertiesGUI(material);
DoEmissionArea(material);
EditorGUILayout.Space();
EditorGUILayout.LabelField(StylesBaseUnlit.advancedText, EditorStyles.boldLabel);
// NB RenderQueue editor is not shown on purpose: we want to override it based on blend mode
EditorGUI.indentLevel++;
m_MaterialEditor.EnableInstancingField();
MaterialPropertiesAdvanceGUI(material);
EditorGUI.indentLevel--;
}
if (EditorGUI.EndChangeCheck())
{
foreach (var obj in m_MaterialEditor.targets)
SetupMaterialKeywordsAndPassInternal((Material)obj);
}
}
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
base.AssignNewShaderToMaterial(material, oldShader, newShader);
SetupMaterialKeywordsAndPassInternal(material);
}
// This is call by the inspector
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
m_MaterialEditor = materialEditor;
// We should always do this call at the beginning
m_MaterialEditor.serializedObject.Update();
// MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
FindBaseMaterialProperties(props);
FindMaterialProperties(props);
Material material = materialEditor.target as Material;
ShaderPropertiesGUI(material);
// We should always do this call at the end
m_MaterialEditor.serializedObject.ApplyModifiedProperties();
}
}
}