summaryrefslogtreecommitdiff
path: root/VRCSDK3Worlds/Assets/Bakery/shader/Editor/BakeryShaderGUI.cs
diff options
context:
space:
mode:
Diffstat (limited to 'VRCSDK3Worlds/Assets/Bakery/shader/Editor/BakeryShaderGUI.cs')
-rw-r--r--VRCSDK3Worlds/Assets/Bakery/shader/Editor/BakeryShaderGUI.cs598
1 files changed, 598 insertions, 0 deletions
diff --git a/VRCSDK3Worlds/Assets/Bakery/shader/Editor/BakeryShaderGUI.cs b/VRCSDK3Worlds/Assets/Bakery/shader/Editor/BakeryShaderGUI.cs
new file mode 100644
index 00000000..b8efd093
--- /dev/null
+++ b/VRCSDK3Worlds/Assets/Bakery/shader/Editor/BakeryShaderGUI.cs
@@ -0,0 +1,598 @@
+#if UNITY_EDITOR
+
+// Disable 'obsolete' warnings
+#pragma warning disable 0618
+#pragma warning disable 0612
+
+using System;
+using UnityEngine;
+
+namespace UnityEditor
+{
+ public class BakeryShaderGUI : ShaderGUI
+ {
+ private enum WorkflowMode
+ {
+ Specular,
+ Metallic,
+ Dielectric
+ }
+
+ public enum BlendMode
+ {
+ Opaque,
+ Cutout,
+ Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency
+ Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply
+ }
+
+ public enum SmoothnessMapChannel
+ {
+ SpecularMetallicAlpha,
+ AlbedoAlpha,
+ }
+
+ private static class Styles
+ {
+ public static GUIStyle optionsButton = "PaneOptions";
+ public static GUIContent uvSetLabel = new GUIContent("UV Set");
+ public static GUIContent[] uvSetOptions = new GUIContent[] { new GUIContent("UV channel 0"), new GUIContent("UV channel 1") };
+
+ public static string emptyTootip = "";
+ public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)");
+ public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");
+ public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)");
+ public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)");
+ public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness value");
+ public static GUIContent smoothnessScaleText = new GUIContent("Smoothness", "Smoothness scale factor");
+ public static GUIContent smoothnessMapChannelText = new GUIContent("Source", "Smoothness texture and channel");
+ public static GUIContent highlightsText = new GUIContent("Specular Highlights", "Specular Highlights");
+ public static GUIContent reflectionsText = new GUIContent("Reflections", "Glossy Reflections");
+ public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map");
+ public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)");
+ public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)");
+ public static GUIContent emissionText = new GUIContent("Emission", "Emission (RGB)");
+ public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)");
+ public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2");
+ public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map");
+
+ public static string whiteSpaceString = " ";
+ public static string primaryMapsText = "Main Maps";
+ public static string secondaryMapsText = "Secondary Maps";
+ public static string forwardText = "Forward Rendering Options";
+ public static string renderingMode = "Rendering Mode";
+ public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
+ public static GUIContent emissiveColorWarning = new GUIContent("Ensure emissive color is non-black for emission to have effect.");
+ public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode));
+
+ public static string bakeryText = "Bakery Options";
+ public static GUIContent doubleSidedLabel = new GUIContent("Double-sided", "Render both sides of triangles.");
+ public static GUIContent vertexLMLabel = new GUIContent("Allow Vertex Lightmaps", "Allows this material to use vertex lightmaps, if present.");
+ public static GUIContent vertexLMdirLabel = new GUIContent("Enable VertexLM directional", "Enables directional vertex lightmaps.");
+ public static GUIContent vertexLMSHLabel = new GUIContent("Enable VertexLM SH", "Enables SH vertex lightmaps.");
+ public static GUIContent vertexLMMaskLabel = new GUIContent("Enable VertexLM Shadowmask", "Enables per-vertex shadowmasks.");
+ public static GUIContent rnmLabel = new GUIContent("Allow RNM Lightmaps", "Allows this material to use RNM lightmaps, if present.");
+ public static GUIContent shLabel = new GUIContent("Allow SH Lightmaps", "Allows this material to use SH lightmaps, if present.");
+ public static GUIContent shnLabel = new GUIContent("Non-linear SH", "This option can enhance contrast (closer to ground truth), but it makes the shader a bit slower.");
+ public static GUIContent specLabel = new GUIContent("Enable Lightmap Specular", "Enables baked specular for all directional modes.");
+ public static GUIContent bicubicLabel = new GUIContent("Force Bicubic Filter", "Enables bicubic filtering for all lightmaps (color/shadowmask/direction/etc) used in the material.");
+ public static GUIContent pshnLabel = new GUIContent("Non-linear Light Probe SH", "Prevents negative values in light probes. This is recommended when baking probes in L1 mode. Can slow down the shader a bit.");
+ public static GUIContent volLabel = new GUIContent("Enable Volumes", "Enable usages of BakeryVolumes");
+ public static GUIContent volLabelRot = new GUIContent("Support Volume Rotation", "Normally volumes can only be repositioned or rescaled at runtime. With this checkbox volume's rotation matrix will also be used. Volumes must have a similar checkbox enabled.");
+ public static GUIContent volLabel0 = new GUIContent("Volume 0");
+ public static GUIContent volLabel1 = new GUIContent("Volume 1");
+ public static GUIContent volLabel2 = new GUIContent("Volume 2");
+ public static GUIContent volLabelMask = new GUIContent("Volume mask");
+ }
+
+ MaterialProperty blendMode = null;
+ MaterialProperty albedoMap = null;
+ MaterialProperty albedoColor = null;
+ MaterialProperty alphaCutoff = null;
+ MaterialProperty specularMap = null;
+ MaterialProperty specularColor = null;
+ MaterialProperty metallicMap = null;
+ MaterialProperty metallic = null;
+ MaterialProperty smoothness = null;
+ MaterialProperty smoothnessScale = null;
+ MaterialProperty smoothnessMapChannel = null;
+ MaterialProperty highlights = null;
+ MaterialProperty reflections = null;
+ MaterialProperty bumpScale = null;
+ MaterialProperty bumpMap = null;
+ MaterialProperty occlusionStrength = null;
+ MaterialProperty occlusionMap = null;
+ MaterialProperty heigtMapScale = null;
+ MaterialProperty heightMap = null;
+ MaterialProperty emissionColorForRendering = null;
+ MaterialProperty emissionMap = null;
+ MaterialProperty detailMask = null;
+ MaterialProperty detailAlbedoMap = null;
+ MaterialProperty detailNormalMapScale = null;
+ MaterialProperty detailNormalMap = null;
+ MaterialProperty uvSetSecondary = null;
+ MaterialProperty enableDoubleSided = null;
+ MaterialProperty enableDoubleSidedOn = null;
+ MaterialProperty enableVertexLM = null;
+ MaterialProperty enableVertexLMdir = null;
+ MaterialProperty enableVertexLMSH = null;
+ MaterialProperty enableVertexLMmask = null;
+ MaterialProperty enableSH = null;
+ MaterialProperty enableSHN = null;
+ MaterialProperty enableRNM = null;
+ MaterialProperty enableSpec = null;
+ MaterialProperty enableBicubic = null;
+ MaterialProperty enablePSHN = null;
+ MaterialProperty enableVolumes = null;
+ MaterialProperty enableVolumeRot = null;
+ MaterialProperty volume0 = null;
+ MaterialProperty volume1 = null;
+ MaterialProperty volume2 = null;
+ MaterialProperty volumeMask = null;
+ MaterialProperty volumeMin = null;
+ MaterialProperty volumeInvSize = null;
+
+ BakeryVolume assignedVolume = null;
+
+ MaterialEditor m_MaterialEditor;
+ WorkflowMode m_WorkflowMode = WorkflowMode.Specular;
+ ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, 99f, 1 / 99f, 3f);
+
+ bool m_FirstTimeApply = true;
+
+ public void FindProperties(MaterialProperty[] props)
+ {
+ blendMode = FindProperty("_Mode", props);
+ albedoMap = FindProperty("_MainTex", props);
+ albedoColor = FindProperty("_Color", props);
+ alphaCutoff = FindProperty("_Cutoff", props);
+ specularMap = FindProperty("_SpecGlossMap", props, false);
+ specularColor = FindProperty("_SpecColor", props, false);
+ metallicMap = FindProperty("_MetallicGlossMap", props, false);
+ metallic = FindProperty("_Metallic", props, false);
+ if (specularMap != null && specularColor != null)
+ m_WorkflowMode = WorkflowMode.Specular;
+ else if (metallicMap != null && metallic != null)
+ m_WorkflowMode = WorkflowMode.Metallic;
+ else
+ m_WorkflowMode = WorkflowMode.Dielectric;
+ smoothness = FindProperty("_Glossiness", props);
+ smoothnessScale = FindProperty("_GlossMapScale", props, false);
+ smoothnessMapChannel = FindProperty("_SmoothnessTextureChannel", props, false);
+ highlights = FindProperty("_SpecularHighlights", props, false);
+ reflections = FindProperty("_GlossyReflections", props, false);
+ bumpScale = FindProperty("_BumpScale", props);
+ bumpMap = FindProperty("_BumpMap", props);
+ heigtMapScale = FindProperty("_Parallax", props);
+ heightMap = FindProperty("_ParallaxMap", props);
+ occlusionStrength = FindProperty("_OcclusionStrength", props);
+ occlusionMap = FindProperty("_OcclusionMap", props);
+ emissionColorForRendering = FindProperty("_EmissionColor", props);
+ emissionMap = FindProperty("_EmissionMap", props);
+ detailMask = FindProperty("_DetailMask", props);
+ detailAlbedoMap = FindProperty("_DetailAlbedoMap", props);
+ detailNormalMapScale = FindProperty("_DetailNormalMapScale", props);
+ detailNormalMap = FindProperty("_DetailNormalMap", props);
+ uvSetSecondary = FindProperty("_UVSec", props);
+ enableDoubleSided = FindProperty("_BAKERY_2SIDED", props);
+ enableDoubleSidedOn = FindProperty("_BAKERY_2SIDEDON", props);
+ enableVertexLM = FindProperty("_BAKERY_VERTEXLM", props);
+ enableVertexLMdir = FindProperty("_BAKERY_VERTEXLMDIR", props);
+ enableVertexLMSH = FindProperty("_BAKERY_VERTEXLMSH", props);
+ enableVertexLMmask = FindProperty("_BAKERY_VERTEXLMMASK", props);
+ enableSH = FindProperty("_BAKERY_SH", props);
+ enableSHN = FindProperty("_BAKERY_SHNONLINEAR", props);
+ enableRNM = FindProperty("_BAKERY_RNM", props);
+ enableSpec = FindProperty("_BAKERY_LMSPEC", props);
+ enableBicubic = FindProperty("_BAKERY_BICUBIC", props);
+ enablePSHN = FindProperty("_BAKERY_PROBESHNONLINEAR", props);
+ try
+ {
+ enableVolumes = FindProperty("_BAKERY_VOLUME", props);
+ enableVolumeRot = FindProperty("_BAKERY_VOLROTATION", props);
+ volume0 = FindProperty("_Volume0", props);
+ volume1 = FindProperty("_Volume1", props);
+ volume2 = FindProperty("_Volume2", props);
+ volumeMask = FindProperty("_VolumeMask", props);
+ volumeMin = FindProperty("_VolumeMin", props);
+ volumeInvSize = FindProperty("_VolumeInvSize", props);
+ }
+ catch
+ {
+
+ }
+ }
+
+ public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
+ {
+ FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
+ m_MaterialEditor = materialEditor;
+ Material material = materialEditor.target as Material;
+
+ // Make sure that needed keywords are set up if we're switching some existing
+ // material to a standard shader.
+ if (m_FirstTimeApply)
+ {
+ SetMaterialKeywords(material, m_WorkflowMode);
+ m_FirstTimeApply = false;
+ }
+
+ ShaderPropertiesGUI(material);
+ }
+
+ public void ShaderPropertiesGUI(Material material)
+ {
+ // Use default labelWidth
+ EditorGUIUtility.labelWidth = 0f;
+
+ // Detect any changes to the material
+ EditorGUI.BeginChangeCheck();
+ {
+ BlendModePopup();
+
+ // Primary properties
+ GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel);
+ DoAlbedoArea(material);
+ DoSpecularMetallicArea();
+ m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null);
+ DoEmissionArea(material);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
+ EditorGUI.BeginChangeCheck();
+ m_MaterialEditor.TextureScaleOffsetProperty(albedoMap);
+ if (EditorGUI.EndChangeCheck())
+ {
+ emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
+ }
+
+ EditorGUILayout.Space();
+
+ // Secondary properties
+ GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale);
+ m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap);
+ m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text);
+
+ // Third properties
+ GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel);
+ if (highlights != null)
+ m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText);
+ if (reflections != null)
+ m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText);
+
+ GUILayout.Label(Styles.bakeryText, EditorStyles.boldLabel);
+
+ m_MaterialEditor.ShaderProperty(enableDoubleSidedOn, Styles.doubleSidedLabel);
+ enableDoubleSided.floatValue = enableDoubleSidedOn.floatValue > 0 ? 0 : 2;
+
+ m_MaterialEditor.ShaderProperty(enableVertexLM, Styles.vertexLMLabel);
+ if (enableVertexLM.floatValue > 0)
+ {
+ m_MaterialEditor.ShaderProperty(enableVertexLMdir, Styles.vertexLMdirLabel);
+ //if (enableVertexLMdir.floatValue > 0) enableVertexLMSH.floatValue = 0;
+ }
+ if (enableVertexLM.floatValue > 0)
+ {
+ m_MaterialEditor.ShaderProperty(enableVertexLMSH, Styles.vertexLMSHLabel);
+ //if (enableVertexLMSH.floatValue > 0) enableVertexLMdir.floatValue = 0;
+ }
+ if (enableVertexLM.floatValue > 0)
+ {
+ m_MaterialEditor.ShaderProperty(enableVertexLMmask, Styles.vertexLMMaskLabel);
+ }
+ m_MaterialEditor.ShaderProperty(enableRNM, Styles.rnmLabel);
+ m_MaterialEditor.ShaderProperty(enableSH, Styles.shLabel);
+ if (enableSH.floatValue > 0 || enableVertexLMSH.floatValue > 0)
+ m_MaterialEditor.ShaderProperty(enableSHN, Styles.shnLabel);
+ m_MaterialEditor.ShaderProperty(enableSpec, Styles.specLabel);
+ m_MaterialEditor.ShaderProperty(enableBicubic, Styles.bicubicLabel);
+ m_MaterialEditor.ShaderProperty(enablePSHN, Styles.pshnLabel);
+
+ try
+ {
+ m_MaterialEditor.ShaderProperty(enableVolumes, Styles.volLabel);
+ if (enableVolumes.floatValue > 0)
+ {
+ var prevAssignedVolume = assignedVolume;
+ assignedVolume = EditorGUILayout.ObjectField(volume0.textureValue == null ? "Assign volume" : "Assign different volume", assignedVolume, typeof(BakeryVolume), true) as BakeryVolume;
+ if (prevAssignedVolume != assignedVolume)
+ {
+ volume0.textureValue = assignedVolume.bakedTexture0;
+ volume1.textureValue = assignedVolume.bakedTexture1;
+ volume2.textureValue = assignedVolume.bakedTexture2;
+ volumeMask.textureValue = assignedVolume.bakedMask;
+ var b = assignedVolume.bounds;
+ volumeMin.vectorValue = b.min;
+ volumeInvSize.vectorValue = new Vector3(1.0f/b.size.x, 1.0f/b.size.y, 1.0f/b.size.z);
+ assignedVolume = null;
+ }
+ if (volume0.textureValue != null)
+ {
+ if (GUILayout.Button("Unset volume"))
+ {
+ volume0.textureValue = null;
+ volume1.textureValue = null;
+ volume2.textureValue = null;
+ volumeMask.textureValue = null;
+ volumeMin.vectorValue = Vector3.zero;
+ volumeInvSize.vectorValue = Vector3.one * 1000001;
+ }
+ }
+ EditorGUILayout.LabelField("Current Volume: " + (volume0.textureValue == null ? "<none or global>" : volume0.textureValue.name.Substring(0, volume0.textureValue.name.Length-1)));
+ EditorGUI.BeginDisabledGroup(true);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.volLabel0, volume0);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.volLabel1, volume1);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.volLabel2, volume2);
+ m_MaterialEditor.TexturePropertySingleLine(Styles.volLabelMask, volumeMask);
+ var bmin4 = volumeMin.vectorValue;
+ var bmin = new Vector3(bmin4.x, bmin4.y, bmin4.z);
+ var invSize = volumeInvSize.vectorValue;
+ var bmax = new Vector3(1.0f/invSize.x + bmin.x, 1.0f/invSize.y + bmin.y, 1.0f/invSize.z + bmin.z);
+ EditorGUILayout.LabelField("Min: " + bmin);
+ EditorGUILayout.LabelField("Max: " + bmax);
+ EditorGUI.EndDisabledGroup();
+ m_MaterialEditor.ShaderProperty(enableVolumeRot, Styles.volLabelRot);
+ }
+ }
+ catch
+ {
+
+ }
+
+ EditorGUILayout.Space();
+ }
+ if (EditorGUI.EndChangeCheck())
+ {
+ foreach (var obj in blendMode.targets)
+ MaterialChanged((Material)obj, m_WorkflowMode);
+ }
+ }
+
+ internal void DetermineWorkflow(MaterialProperty[] props)
+ {
+ if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null)
+ m_WorkflowMode = WorkflowMode.Specular;
+ else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null)
+ m_WorkflowMode = WorkflowMode.Metallic;
+ else
+ m_WorkflowMode = WorkflowMode.Dielectric;
+ }
+
+ public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
+ {
+ // _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/"))
+ {
+ SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
+ return;
+ }
+
+ BlendMode blendMode = BlendMode.Opaque;
+ if (oldShader.name.Contains("/Transparent/Cutout/"))
+ {
+ blendMode = BlendMode.Cutout;
+ }
+ else if (oldShader.name.Contains("/Transparent/"))
+ {
+ // NOTE: legacy shaders did not provide physically based transparency
+ // therefore Fade mode
+ blendMode = BlendMode.Fade;
+ }
+ material.SetFloat("_Mode", (float)blendMode);
+
+ DetermineWorkflow(MaterialEditor.GetMaterialProperties(new Material[] { material }));
+ MaterialChanged(material, m_WorkflowMode);
+ }
+
+ void BlendModePopup()
+ {
+ EditorGUI.showMixedValue = blendMode.hasMixedValue;
+ var mode = (BlendMode)blendMode.floatValue;
+
+ EditorGUI.BeginChangeCheck();
+ mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames);
+ if (EditorGUI.EndChangeCheck())
+ {
+ m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode");
+ blendMode.floatValue = (float)mode;
+ }
+
+ EditorGUI.showMixedValue = false;
+ }
+
+ void DoAlbedoArea(Material material)
+ {
+ m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor);
+ if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout))
+ {
+ m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
+ }
+ }
+
+ void DoEmissionArea(Material material)
+ {
+ bool showHelpBox = !HasValidEmissiveKeyword(material);
+
+ bool hadEmissionTexture = emissionMap.textureValue != null;
+
+ // Texture and HDR color controls
+ m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false);
+
+ // If texture was assigned and color was black set color to white
+ float brightness = emissionColorForRendering.colorValue.maxColorComponent;
+ if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f)
+ emissionColorForRendering.colorValue = Color.white;
+
+ // Emission for GI?
+ m_MaterialEditor.LightmapEmissionProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
+
+ if (showHelpBox)
+ {
+ EditorGUILayout.HelpBox(Styles.emissiveWarning.text, MessageType.Warning);
+ }
+ }
+
+ void DoSpecularMetallicArea()
+ {
+ bool hasGlossMap = false;
+ if (m_WorkflowMode == WorkflowMode.Specular)
+ {
+ hasGlossMap = specularMap.textureValue != null;
+ m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor);
+ }
+ else if (m_WorkflowMode == WorkflowMode.Metallic)
+ {
+ hasGlossMap = metallicMap.textureValue != null;
+ m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic);
+ }
+
+ bool showSmoothnessScale = hasGlossMap;
+ if (smoothnessMapChannel != null)
+ {
+ int smoothnessChannel = (int)smoothnessMapChannel.floatValue;
+ if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha)
+ showSmoothnessScale = true;
+ }
+
+ int indentation = 2; // align with labels of texture properties
+ m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation);
+
+ ++indentation;
+ if (smoothnessMapChannel != null)
+ m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation);
+ }
+
+ public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode)
+ {
+ switch (blendMode)
+ {
+ case BlendMode.Opaque:
+ material.SetOverrideTag("RenderType", "Opaque");
+ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+ material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
+ material.SetInt("_ZWrite", 1);
+ material.DisableKeyword("_ALPHATEST_ON");
+ material.DisableKeyword("_ALPHABLEND_ON");
+ material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+ material.renderQueue = -1;
+ break;
+ case BlendMode.Cutout:
+ material.SetOverrideTag("RenderType", "TransparentCutout");
+ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+ material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
+ material.SetInt("_ZWrite", 1);
+ material.EnableKeyword("_ALPHATEST_ON");
+ material.DisableKeyword("_ALPHABLEND_ON");
+ material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+ material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
+ break;
+ case BlendMode.Fade:
+ material.SetOverrideTag("RenderType", "Transparent");
+ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
+ material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
+ material.SetInt("_ZWrite", 0);
+ material.DisableKeyword("_ALPHATEST_ON");
+ material.EnableKeyword("_ALPHABLEND_ON");
+ material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+ material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
+ break;
+ case BlendMode.Transparent:
+ material.SetOverrideTag("RenderType", "Transparent");
+ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
+ material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
+ material.SetInt("_ZWrite", 0);
+ material.DisableKeyword("_ALPHATEST_ON");
+ material.DisableKeyword("_ALPHABLEND_ON");
+ material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
+ material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
+ break;
+ }
+ }
+
+ static SmoothnessMapChannel GetSmoothnessMapChannel(Material material)
+ {
+ int ch = (int)material.GetFloat("_SmoothnessTextureChannel");
+ if (ch == (int)SmoothnessMapChannel.AlbedoAlpha)
+ return SmoothnessMapChannel.AlbedoAlpha;
+ else
+ return SmoothnessMapChannel.SpecularMetallicAlpha;
+ }
+
+ static bool ShouldEmissionBeEnabled(Material mat, Color color)
+ {
+ var realtimeEmission = (mat.globalIlluminationFlags & MaterialGlobalIlluminationFlags.RealtimeEmissive) > 0;
+ return color.maxColorComponent > 0.1f / 255.0f || realtimeEmission;
+ }
+
+ static void SetMaterialKeywords(Material material, WorkflowMode workflowMode)
+ {
+ // 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)
+ SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap"));
+ if (workflowMode == WorkflowMode.Specular)
+ SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap"));
+ else if (workflowMode == WorkflowMode.Metallic)
+ SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap"));
+ SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap"));
+ SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap"));
+
+ bool shouldEmissionBeEnabled = ShouldEmissionBeEnabled(material, material.GetColor("_EmissionColor"));
+ SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled);
+
+ if (material.HasProperty("_SmoothnessTextureChannel"))
+ {
+ SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha);
+ }
+
+ // Setup lightmap emissive flags
+ MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
+ if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
+ {
+ flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
+ if (!shouldEmissionBeEnabled)
+ flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
+
+ material.globalIlluminationFlags = flags;
+ }
+ }
+
+ bool HasValidEmissiveKeyword(Material material)
+ {
+ // Material animation might be out of sync with the material keyword.
+ // So if the emission support is disabled on the material, but the property blocks have a value that requires it, then we need to show a warning.
+ // (note: (Renderer MaterialPropertyBlock applies its values to emissionColorForRendering))
+ bool hasEmissionKeyword = material.IsKeywordEnabled("_EMISSION");
+ if (!hasEmissionKeyword && ShouldEmissionBeEnabled(material, emissionColorForRendering.colorValue))
+ return false;
+ else
+ return true;
+ }
+
+ static void MaterialChanged(Material material, WorkflowMode workflowMode)
+ {
+ SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode"));
+
+ SetMaterialKeywords(material, workflowMode);
+ }
+
+ static void SetKeyword(Material m, string keyword, bool state)
+ {
+ if (state)
+ m.EnableKeyword(keyword);
+ else
+ m.DisableKeyword(keyword);
+ }
+ }
+}
+
+#endif