using Misaki.ShaderGUI; using System.Linq; using UnityEditor; using UnityEditor.Rendering; using UnityEngine; using static Misaki.HdrpToon.UtsShaderPropertyName.SurfaceInputs; namespace Misaki.HdrpToon.Editor { public class SurfaceInputsScope : MaterialUIScope { private static class Properties { public static MaterialProperty normalMap; public static MaterialProperty normalMapScale; public static MaterialProperty maskMap; public static MaterialProperty metallic; public static MaterialProperty metallicRemapMin; public static MaterialProperty metallicRemapMax; public static MaterialProperty aoRemapMin; public static MaterialProperty aoRemapMax; public static MaterialProperty smoothness; public static MaterialProperty smoothnessRemapMin; public static MaterialProperty smoothnessRemapMax; public static MaterialProperty anisotropyMap; public static MaterialProperty anisotropy; public static MaterialProperty kkColor; public static MaterialProperty bsdfContribution; public static MaterialProperty specularColorMap; public static MaterialProperty specularColor; public static MaterialProperty specularFeather; public static MaterialProperty specularStep; public static MaterialProperty hairBlendingMap; public static MaterialProperty emissiveColorLDR; public static MaterialProperty emissiveColorMap; public static MaterialProperty emissiveIntensity; public static MaterialProperty albedoAffectEmissive; public static MaterialProperty emissiveExposureWeight; } private static class Styles { public static readonly GUIContent normalMapText = new("Normal Map", "A texture that dictates the bumpiness of the material."); public static readonly GUIContent maskMapText = new("Mask Map", "A texture that dictates the physical properties of the material. R channel for metallic, G channel for ambient occlusion, A channel for smoothness"); public static readonly GUIContent metallicText = new("Metallic", "Specifies the metallic value of the material."); public static readonly GUIContent metallicRemap = new("Metallic Remap", "Remap the max and min value of metallic"); public static readonly GUIContent aoRemap = new("AO Remap", "Remap the max and min value of ambient occlusion"); public static readonly GUIContent smoothnessText = new("Smoothness", "Specifies the smoothness of the material."); public static readonly GUIContent smoothnessRemapText = new("Smoothness Remap", "Remap the max and min value of smoothness"); public static readonly GUIContent anisotropyMapText = new("Anisotropy Map", "Specifies the anisotropy map of the material."); public static readonly GUIContent kkColorText = new("KK specular Color", "Specifies the color of KK specular."); public static readonly GUIContent bsdfContributionText = new("BSDF Contribution", "BSDF smoothness contribution, 1 means KK Hair smoothness will fully contribute bsdf calculation"); public static readonly GUIContent specularColorMapText = new("Specular Color Map", "Specifies the specular color map of the material."); public static readonly GUIContent specRemap = new("Specular Remap", "Feather and step value of Toon Specular"); public static readonly GUIContent hairBlenderMapText = new("Hair Blending Map", "Specifies the hair blending map of the material."); public static readonly GUIContent emissiveColorText = new("Emissive Color", "The color and color map to set for emissive effect."); public static readonly GUIContent albedoAffectEmissiveText = new("Albedo Affect Emissive", "Enable to affect emissive color with base color"); public static readonly GUIContent emissiveIntensityText = new("Emissive Intensity", "Set the intensity of the emissive color,in Nits"); public static readonly GUIContent emissiveExposureWeightText = new("Exposure Weight", "Controls how the camera exposure influences the perceived intensity of the emissivity. A weight of 0 means that the emissive intensity is calculated ignoring the exposure; increasing this weight progressively increases the influence of exposure on the final emissive value."); } protected override ShaderGUIExpandable ExpandableBit => ShaderGUIExpandable.SurfaceInputs; protected override GUIContent Header => new("Surface Inputs"); public override void LoadMaterialProperties() { Properties.normalMap = FindProperty("_NormalMap"); Properties.normalMapScale = FindProperty("_NormalScale"); Properties.maskMap = FindProperty("_MaskMap"); Properties.metallic = FindProperty("_Metallic"); Properties.metallicRemapMin = FindProperty("_MetallicRemapMin"); Properties.metallicRemapMax = FindProperty("_MetallicRemapMax"); Properties.aoRemapMin = FindProperty("_AORemapMin"); Properties.aoRemapMax = FindProperty("_AORemapMax"); Properties.smoothnessRemapMin = FindProperty("_SmoothnessRemapMin"); Properties.smoothnessRemapMax = FindProperty("_SmoothnessRemapMax"); Properties.smoothness = FindProperty("_Smoothness"); Properties.anisotropyMap = FindProperty("_AnisotropyMap"); Properties.anisotropy = FindProperty("_Anisotropy"); Properties.kkColor = FindProperty("_KKColor"); Properties.bsdfContribution = FindProperty("_BSDFContribution"); Properties.specularColorMap = FindProperty("_SpecularColorMap"); Properties.specularColor = FindProperty("_SpecularColor"); Properties.specularFeather = FindProperty("_ToonSpecularFeather"); Properties.specularStep = FindProperty("_ToonSpecularStep"); Properties.hairBlendingMap = FindProperty("_HairBlendingMap"); Properties.emissiveColorLDR = FindProperty(EMISSIVE_COLOR_LDR); Properties.emissiveColorMap = FindProperty(EMISSIVE_COLOR_MAP); Properties.albedoAffectEmissive = FindProperty(ALBEDO_AFFECT_EMISSIVE); Properties.emissiveIntensity = FindProperty(EMISSIVE_INTENSITY); Properties.emissiveExposureWeight = FindProperty(EMISSIVE_EXPOSURE_WEIGHT); } protected override void DrawContent() { editor.KeywordTexturePropertySingleLine(Styles.normalMapText, Properties.normalMap, Properties.normalMapScale); if (materials.All(mat => mat.GetPBRMode() != PBRMode.Off)) { if (editor.KeywordTexturePropertySingleLine(Styles.maskMapText, Properties.maskMap)) { editor.MinMaxShaderProperty(Properties.metallicRemapMin, Properties.metallicRemapMax, 0, 1, Styles.metallicRemap); editor.MinMaxShaderProperty(Properties.aoRemapMin, Properties.aoRemapMax, 0, 1, Styles.aoRemap); editor.MinMaxShaderProperty(Properties.smoothnessRemapMin, Properties.smoothnessRemapMax, 0, 1, Styles.smoothnessRemapText); } else { if (materials.All(mat => { var pbrMode = mat.GetPBRMode(); return pbrMode != PBRMode.Hair && pbrMode != PBRMode.Toon; })) { editor.ShaderProperty(Properties.metallic, Styles.metallicText); } editor.ShaderProperty(Properties.smoothness, Styles.smoothnessText); } } if (materials.All(mat => mat.GetPBRMode() == PBRMode.Anisotropy || mat.GetPBRMode() == PBRMode.Hair)) { EditorGUILayout.Space(); editor.KeywordTexturePropertySingleLine(Styles.anisotropyMapText, Properties.anisotropyMap, Properties.anisotropy); if (materials.All(mat => mat.GetPBRMode() == PBRMode.Hair)) { editor.ShaderProperty(Properties.kkColor, Styles.kkColorText); editor.ShaderProperty(Properties.bsdfContribution, Styles.bsdfContributionText); } EditorGUILayout.Space(); EditorGUILayout.LabelField("Anisotropy Map only ST"); editor.TextureScaleOffsetProperty(Properties.anisotropyMap); } else if (materials.All(mat => mat.GetPBRMode() == PBRMode.Toon)) { EditorGUILayout.Space(); editor.KeywordTexturePropertySingleLine(Styles.specularColorMapText, Properties.specularColorMap, Properties.specularColor); editor.MinMaxShaderProperty(Properties.specularFeather, Properties.specularStep, 0, 1, Styles.specRemap); } if (materials.All(mat => mat.IsHairBlendingTarget())) { editor.TexturePropertySingleLine(Styles.hairBlenderMapText, Properties.hairBlendingMap); } EditorGUILayout.Space(); using (var EmissiveIntentLevel = new EditorGUI.IndentLevelScope(-1)) { EditorGUILayout.LabelField("Emissive", EditorStyles.boldLabel); } EditorGUI.BeginChangeCheck(); editor.KeywordTexturePropertySingleLine(Styles.emissiveColorText, Properties.emissiveColorMap, Properties.emissiveColorLDR, "_EMISSIVE_COLOR_MAP"); editor.ShaderProperty(Properties.emissiveIntensity, Styles.emissiveIntensityText); if (EditorGUI.EndChangeCheck()) { foreach (var material in materials) { if (material.HasProperty(EMISSIVE_COLOR_LDR) && material.HasProperty(EMISSIVE_INTENSITY) && material.HasProperty(EMISSIVE_COLOR)) { // Important: The color picker for kEmissiveColorLDR is LDR and in sRGB color space but Unity don't perform any color space conversion in the color // picker BUT only when sending the color data to the shader... So as we are doing our own calculation here in C#, we must do the conversion ourselves. var emissiveColorLDR = material.GetColor(EMISSIVE_COLOR_LDR); var emissiveColorLDRLinear = new Color(Mathf.GammaToLinearSpace(emissiveColorLDR.r), Mathf.GammaToLinearSpace(emissiveColorLDR.g), Mathf.GammaToLinearSpace(emissiveColorLDR.b)); material.SetColor(EMISSIVE_COLOR, emissiveColorLDRLinear * material.GetFloat(EMISSIVE_INTENSITY)); } } } EditorGUILayout.Space(); editor.ShaderProperty(Properties.albedoAffectEmissive, Styles.albedoAffectEmissiveText); editor.ShaderProperty(Properties.emissiveExposureWeight, Styles.emissiveExposureWeightText); } } }