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

276 行
14 KiB

using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public class DecalUI : ShaderGUI
{
protected static class Styles
{
public static string InputsText = "Inputs";
public static GUIContent baseColorText = new GUIContent("BaseColor (RGB) and Opacity (A)", "BaseColor (RGB) and Opacity (A)");
public static GUIContent baseColorText2 = new GUIContent("Opacity(A)", "Opacity (A)");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC7/BC5/DXT5(nm))");
public static GUIContent decalBlendText = new GUIContent("Global Opacity", "Whole decal Opacity");
public static GUIContent AlbedoModeText = new GUIContent("Affect BaseColor", "Base color + Opacity, Opacity only");
public static GUIContent MeshDecalDepthBiasText = new GUIContent("Mesh decal depth bias", "prevents z-fighting");
public static GUIContent DrawOrderText = new GUIContent("Draw order", "Controls draw order of decal projectors");
public static GUIContent[] maskMapText =
{
new GUIContent("Error", "Mask map"), // Not possible
new GUIContent("Mask Map - M(R), Opacity(B)", "Mask map - Metal(R), Opacity(B)"), // Decal.MaskBlendFlags.Metal:
new GUIContent("Mask Map - AO(G), Opacity(B)", "Mask map - Ambient Occlusion(G), Opacity(B)"), // Decal.MaskBlendFlags.AO:
new GUIContent("Mask Map - M(R), AO(G), Opacity(B)", "Mask map - Metal(R), Ambient Occlusion(G), Opacity(B)"), // Decal.MaskBlendFlags.Metal | Decal.MaskBlendFlags.AO:
new GUIContent("Mask Map - Opacity(B), S(A)", "Mask map - Opacity(B), Smoothness(A)"), // Decal.MaskBlendFlags.Smoothness:
new GUIContent("Mask Map - M(R), Opacity(B), S(A)", "Mask map - Metal(R), Opacity(B), Smoothness(A)"), // Decal.MaskBlendFlags.Metal | Decal.MaskBlendFlags.Smoothness:
new GUIContent("Mask Map - AO(G), Opacity(B), S(A)", "Mask map - Ambient Occlusion(G), Opacity(B), Smoothness(A)"), // Decal.MaskBlendFlags.AO | Decal.MaskBlendFlags.Smoothness:
new GUIContent("Mask Map - M(R), AO(G), Opacity(B), S(A)", "Mask map - Metal(R), Ambient Occlusion(G), Opacity(B), Smoothness(A)") // Decal.MaskBlendFlags.Metal | Decal.MaskBlendFlags.AO | Decal.MaskBlendFlags.Smoothness:
};
}
enum BlendSource
{
BaseColorMapAlpha,
MaskMapBlue
}
protected string[] blendSourceNames = Enum.GetNames(typeof(BlendSource));
protected string[] blendModeNames = Enum.GetNames(typeof(BlendMode));
protected MaterialProperty baseColorMap = new MaterialProperty();
protected const string kBaseColorMap = "_BaseColorMap";
protected MaterialProperty baseColor = new MaterialProperty();
protected const string kBaseColor = "_BaseColor";
protected MaterialProperty normalMap = new MaterialProperty();
protected const string kNormalMap = "_NormalMap";
protected MaterialProperty maskMap = new MaterialProperty();
protected const string kMaskMap = "_MaskMap";
protected MaterialProperty decalBlend = new MaterialProperty();
protected const string kDecalBlend = "_DecalBlend";
protected MaterialProperty albedoMode = new MaterialProperty();
protected const string kAlbedoMode = "_AlbedoMode";
protected MaterialProperty normalBlendSrc = new MaterialProperty();
protected const string kNormalBlendSrc = "_NormalBlendSrc";
protected MaterialProperty maskBlendSrc = new MaterialProperty();
protected const string kMaskBlendSrc = "_MaskBlendSrc";
protected MaterialProperty maskBlendMode = new MaterialProperty();
protected const string kMaskBlendMode = "_MaskBlendMode";
protected MaterialProperty maskmapMetal = new MaterialProperty();
protected const string kMaskmapMetal = "_MaskmapMetal";
protected MaterialProperty maskmapAO = new MaterialProperty();
protected const string kMaskmapAO = "_MaskmapAO";
protected MaterialProperty maskmapSmoothness = new MaterialProperty();
protected const string kMaskmapSmoothness = "_MaskmapSmoothness";
protected MaterialProperty decalMeshDepthBias = new MaterialProperty();
protected const string kDecalMeshDepthBias = "_DecalMeshDepthBias";
protected MaterialProperty drawOrder = new MaterialProperty();
protected const string kDrawOrder = "_DrawOrder";
protected const string kDecalStencilWriteMask = "_DecalStencilWriteMask";
protected const string kDecalStencilRef = "_DecalStencilRef";
protected MaterialEditor m_MaterialEditor;
// This is call by the inspector
void FindMaterialProperties(MaterialProperty[] props)
{
baseColor = FindProperty(kBaseColor, props);
baseColorMap = FindProperty(kBaseColorMap, props);
normalMap = FindProperty(kNormalMap, props);
maskMap = FindProperty(kMaskMap, props);
decalBlend = FindProperty(kDecalBlend, props);
albedoMode = FindProperty(kAlbedoMode, props);
normalBlendSrc = FindProperty(kNormalBlendSrc, props);
maskBlendSrc = FindProperty(kMaskBlendSrc, props);
maskBlendMode = FindProperty(kMaskBlendMode, props);
maskmapMetal = FindProperty(kMaskmapMetal, props);
maskmapAO = FindProperty(kMaskmapAO, props);
maskmapSmoothness = FindProperty(kMaskmapSmoothness, props);
decalMeshDepthBias = FindProperty(kDecalMeshDepthBias, props);
drawOrder = FindProperty(kDrawOrder, props);
// always instanced
SerializedProperty instancing = m_MaterialEditor.serializedObject.FindProperty("m_EnableInstancingVariants");
instancing.boolValue = true;
}
// 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 SetupMaterialKeywordsAndPass(Material material)
{
Decal.MaskBlendFlags blendMode = (Decal.MaskBlendFlags)material.GetFloat(kMaskBlendMode);
CoreUtils.SetKeyword(material, "_ALBEDOCONTRIBUTION", material.GetFloat(kAlbedoMode) == 1.0f);
CoreUtils.SetKeyword(material, "_COLORMAP", material.GetTexture(kBaseColorMap));
CoreUtils.SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap));
CoreUtils.SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap));
material.SetInt(kDecalStencilWriteMask, (int)HDRenderPipeline.StencilBitMask.Decals);
material.SetInt(kDecalStencilRef, (int)HDRenderPipeline.StencilBitMask.Decals);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMStr, false);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsAOStr, false);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMAOStr, false);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsSStr, false);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMSStr, false);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsAOSStr, false);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMAOSStr, false);
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecals3RTStr, true);
switch (blendMode)
{
case Decal.MaskBlendFlags.Metal:
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMStr, true);
break;
case Decal.MaskBlendFlags.AO:
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsAOStr, true);
break;
case Decal.MaskBlendFlags.Metal | Decal.MaskBlendFlags.AO:
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMAOStr, true);
break;
case Decal.MaskBlendFlags.Smoothness:
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsSStr, true);
break;
case Decal.MaskBlendFlags.Metal | Decal.MaskBlendFlags.Smoothness:
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMSStr, true);
break;
case Decal.MaskBlendFlags.AO | Decal.MaskBlendFlags.Smoothness:
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsAOSStr, true);
break;
case Decal.MaskBlendFlags.Metal | Decal.MaskBlendFlags.AO | Decal.MaskBlendFlags.Smoothness:
material.SetShaderPassEnabled(HDShaderPassNames.s_MeshDecalsMAOSStr, true);
break;
}
}
protected void SetupMaterialKeywordsAndPassInternal(Material material)
{
SetupMaterialKeywordsAndPass(material);
}
public void ShaderPropertiesGUI(Material material)
{
// Use default labelWidth
EditorGUIUtility.labelWidth = 0f;
float normalBlendSrcValue = normalBlendSrc.floatValue;
float maskBlendSrcValue = maskBlendSrc.floatValue;
Decal.MaskBlendFlags maskBlendFlags = (Decal.MaskBlendFlags)maskBlendMode.floatValue;
HDRenderPipelineAsset hdrp = GraphicsSettings.renderPipelineAsset as HDRenderPipelineAsset;
bool perChannelMask = hdrp.renderPipelineSettings.decalSettings.perChannelMask;
// Detect any changes to the material
EditorGUI.BeginChangeCheck();
{
EditorGUILayout.LabelField(Styles.InputsText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine((material.GetFloat(kAlbedoMode) == 1.0f) ? Styles.baseColorText : Styles.baseColorText2, baseColorMap, baseColor);
// Currently always display Albedo contribution as we have an albedo tint that apply
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(albedoMode, Styles.AlbedoModeText);
EditorGUI.indentLevel--;
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, normalMap);
if (material.GetTexture(kNormalMap))
{
EditorGUI.indentLevel++;
normalBlendSrcValue = EditorGUILayout.Popup("Normal Opacity channel", (int)normalBlendSrcValue, blendSourceNames);
EditorGUI.indentLevel--;
}
m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapText[(int)maskBlendFlags], maskMap);
if (material.GetTexture(kMaskMap))
{
EditorGUI.indentLevel++;
maskBlendSrcValue = EditorGUILayout.Popup("Mask Opacity channel", (int) maskBlendSrcValue, blendSourceNames);
if (perChannelMask)
{
// Following condition force users to always have at least one attribute enabled
m_MaterialEditor.ShaderProperty(maskmapMetal, "Affect Metal");
if ((maskmapMetal.floatValue == 0.0f) && (maskmapAO.floatValue == 0.0f) && (maskmapSmoothness.floatValue == 0.0f))
maskmapMetal.floatValue = 1.0f;
m_MaterialEditor.ShaderProperty(maskmapAO, "Affect AO");
if ((maskmapMetal.floatValue == 0.0f) && (maskmapAO.floatValue == 0.0f) && (maskmapSmoothness.floatValue == 0.0f))
maskmapAO.floatValue = 1.0f;
m_MaterialEditor.ShaderProperty(maskmapSmoothness, "Affect Smoothness");
if ((maskmapMetal.floatValue == 0.0f) && (maskmapAO.floatValue == 0.0f) && (maskmapSmoothness.floatValue == 0.0f))
maskmapSmoothness.floatValue = 1.0f;
maskBlendFlags = 0; // Re-init the mask
if (maskmapMetal.floatValue == 1.0f)
maskBlendFlags |= Decal.MaskBlendFlags.Metal;
if (maskmapAO.floatValue == 1.0f)
maskBlendFlags |= Decal.MaskBlendFlags.AO;
if (maskmapSmoothness.floatValue == 1.0f)
maskBlendFlags |= Decal.MaskBlendFlags.Smoothness;
}
else // if perChannelMask is not enabled, force to have smoothness
{
maskBlendFlags = Decal.MaskBlendFlags.Smoothness;
}
EditorGUI.indentLevel--;
}
m_MaterialEditor.ShaderProperty(drawOrder, Styles.DrawOrderText);
m_MaterialEditor.ShaderProperty(decalMeshDepthBias, Styles.MeshDecalDepthBiasText);
m_MaterialEditor.ShaderProperty(decalBlend, Styles.decalBlendText);
EditorGUI.indentLevel--;
EditorGUILayout.HelpBox(
"Control of AO and Metal is based on option 'Enable Metal and AO properties' in HDRP Asset.\nThere is a performance cost of enabling this option.",
MessageType.Info);
}
if (EditorGUI.EndChangeCheck())
{
normalBlendSrc.floatValue = normalBlendSrcValue;
maskBlendSrc.floatValue = maskBlendSrcValue;
maskBlendMode.floatValue = (float) maskBlendFlags;
foreach (var obj in m_MaterialEditor.targets)
SetupMaterialKeywordsAndPassInternal((Material)obj);
}
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
m_MaterialEditor = materialEditor;
// We should always do this call at the beginning
m_MaterialEditor.serializedObject.Update();
FindMaterialProperties(props);
Material material = materialEditor.target as Material;
ShaderPropertiesGUI(material);
// We should always do this call at the end
m_MaterialEditor.serializedObject.ApplyModifiedProperties();
}
}
}