299 lines
14 KiB
C#
299 lines
14 KiB
C#
// NiloToon Character Fur Shader - Custom ShaderGUI
|
|
// Clean, organized material inspector with foldable sections
|
|
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using System;
|
|
|
|
namespace NiloToonURP.ShaderGUI
|
|
{
|
|
public class NiloToonCharacterFurShaderGUI : UnityEditor.ShaderGUI
|
|
{
|
|
// Foldout states
|
|
private static bool showBaseColor = true;
|
|
private static bool showNormalMap = false;
|
|
private static bool showFurShape = true;
|
|
private static bool showFurRim = false;
|
|
private static bool showCelShading = true;
|
|
private static bool showShadowColor = false;
|
|
private static bool showMatCap = false;
|
|
private static bool showRimLight = false;
|
|
private static bool showEmission = false;
|
|
private static bool showOcclusion = false;
|
|
private static bool showOutline = false;
|
|
private static bool showRendering = false;
|
|
|
|
// Styles
|
|
private static GUIStyle headerStyle;
|
|
private static GUIStyle foldoutStyle;
|
|
private static bool stylesInitialized = false;
|
|
|
|
private static void InitStyles()
|
|
{
|
|
if (stylesInitialized) return;
|
|
|
|
headerStyle = new GUIStyle(EditorStyles.boldLabel)
|
|
{
|
|
fontSize = 12,
|
|
margin = new RectOffset(0, 0, 10, 5)
|
|
};
|
|
|
|
foldoutStyle = new GUIStyle(EditorStyles.foldout)
|
|
{
|
|
fontStyle = FontStyle.Bold,
|
|
fontSize = 11
|
|
};
|
|
|
|
stylesInitialized = true;
|
|
}
|
|
|
|
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
|
|
{
|
|
InitStyles();
|
|
|
|
Material material = materialEditor.target as Material;
|
|
|
|
EditorGUILayout.Space(5);
|
|
|
|
// Header
|
|
EditorGUILayout.LabelField("NiloToon Character Fur Shader", EditorStyles.boldLabel);
|
|
EditorGUILayout.HelpBox(
|
|
"Single-material fur shader with Base + Fur Shell rendering.\n\n" +
|
|
"Setup:\n" +
|
|
"1. Add 'NiloToonFurRendererFeature' to your URP Renderer Asset\n" +
|
|
"2. Apply this shader to your mesh material (single material slot)\n\n" +
|
|
"The shader will render base mesh first, then fur shells on top.",
|
|
MessageType.Info);
|
|
DrawSeparator();
|
|
|
|
// Base Color Section
|
|
showBaseColor = DrawSection("Base Color", showBaseColor, () =>
|
|
{
|
|
DrawProperty(materialEditor, properties, "_BaseMap", "Base Map");
|
|
DrawProperty(materialEditor, properties, "_BaseColor", "Base Color");
|
|
DrawProperty(materialEditor, properties, "_Cutoff", "Alpha Cutoff");
|
|
});
|
|
|
|
// Normal Map Section
|
|
showNormalMap = DrawSection("Normal Map", showNormalMap, () =>
|
|
{
|
|
DrawToggleProperty(materialEditor, properties, "_UseNormalMap", "Enable Normal Map", "_NORMALMAP", material);
|
|
if (material.IsKeywordEnabled("_NORMALMAP"))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
DrawProperty(materialEditor, properties, "_BumpMap", "Normal Map");
|
|
DrawProperty(materialEditor, properties, "_BumpScale", "Normal Scale");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
});
|
|
|
|
// Fur Shape Section
|
|
showFurShape = DrawSection("Fur Shape", showFurShape, () =>
|
|
{
|
|
DrawProperty(materialEditor, properties, "_FurNoiseMask", "Fur Noise Mask");
|
|
DrawProperty(materialEditor, properties, "_FurMask", "Fur Mask");
|
|
DrawProperty(materialEditor, properties, "_FurLengthMask", "Fur Length Mask");
|
|
EditorGUILayout.Space(5);
|
|
DrawProperty(materialEditor, properties, "_FurVector", "Fur Direction (XYZ) + Length (W)");
|
|
DrawProperty(materialEditor, properties, "_FurVectorTex", "Fur Direction Map");
|
|
DrawProperty(materialEditor, properties, "_FurVectorScale", "Fur Direction Scale");
|
|
EditorGUILayout.Space(5);
|
|
DrawProperty(materialEditor, properties, "_FurGravity", "Fur Gravity");
|
|
DrawProperty(materialEditor, properties, "_FurRandomize", "Fur Randomize");
|
|
DrawProperty(materialEditor, properties, "_FurAO", "Fur Ambient Occlusion");
|
|
EditorGUILayout.Space(5);
|
|
DrawProperty(materialEditor, properties, "_FurLayerNum", "Fur Layer Count");
|
|
DrawProperty(materialEditor, properties, "_FurRootOffset", "Fur Root Offset");
|
|
});
|
|
|
|
// Fur Rim Section
|
|
showFurRim = DrawSection("Fur Rim Light", showFurRim, () =>
|
|
{
|
|
DrawProperty(materialEditor, properties, "_FurRimColor", "Fur Rim Color");
|
|
DrawProperty(materialEditor, properties, "_FurRimFresnelPower", "Fur Rim Fresnel Power");
|
|
DrawProperty(materialEditor, properties, "_FurRimAntiLight", "Fur Rim Anti-Light");
|
|
});
|
|
|
|
// Cel Shading Section
|
|
showCelShading = DrawSection("Cel Shading", showCelShading, () =>
|
|
{
|
|
DrawProperty(materialEditor, properties, "_CelShadeMidPoint", "Cel Shade Mid Point");
|
|
DrawProperty(materialEditor, properties, "_CelShadeSoftness", "Cel Shade Softness");
|
|
});
|
|
|
|
// Shadow Color Section
|
|
showShadowColor = DrawSection("Shadow Color", showShadowColor, () =>
|
|
{
|
|
DrawToggleProperty(materialEditor, properties, "_EnableShadowColor", "Enable Shadow Color", "_SHADOW_COLOR", material);
|
|
if (material.IsKeywordEnabled("_SHADOW_COLOR"))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
DrawProperty(materialEditor, properties, "_ShadowColor", "Shadow Tint Color");
|
|
DrawProperty(materialEditor, properties, "_ShadowBrightness", "Shadow Brightness");
|
|
EditorGUILayout.Space(5);
|
|
EditorGUILayout.LabelField("HSV Adjustment", EditorStyles.miniLabel);
|
|
DrawProperty(materialEditor, properties, "_ShadowHueShift", "Hue Shift");
|
|
DrawProperty(materialEditor, properties, "_ShadowSaturationBoost", "Saturation Boost");
|
|
DrawProperty(materialEditor, properties, "_ShadowValueMultiplier", "Value Multiplier");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
});
|
|
|
|
// MatCap Section
|
|
showMatCap = DrawSection("MatCap", showMatCap, () =>
|
|
{
|
|
EditorGUILayout.LabelField("MatCap Additive", EditorStyles.miniLabel);
|
|
DrawToggleProperty(materialEditor, properties, "_UseMatCapAdd", "Enable MatCap (Add)", "_MATCAP_ADD", material);
|
|
if (material.IsKeywordEnabled("_MATCAP_ADD"))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
DrawProperty(materialEditor, properties, "_MatCapAddMap", "MatCap Add Map");
|
|
DrawProperty(materialEditor, properties, "_MatCapAddColor", "MatCap Add Color");
|
|
DrawProperty(materialEditor, properties, "_MatCapAddIntensity", "MatCap Add Intensity");
|
|
DrawProperty(materialEditor, properties, "_MatCapAddMask", "MatCap Add Mask");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
EditorGUILayout.Space(5);
|
|
EditorGUILayout.LabelField("MatCap Multiply", EditorStyles.miniLabel);
|
|
DrawToggleProperty(materialEditor, properties, "_UseMatCapMul", "Enable MatCap (Multiply)", "_MATCAP_MUL", material);
|
|
if (material.IsKeywordEnabled("_MATCAP_MUL"))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
DrawProperty(materialEditor, properties, "_MatCapMulMap", "MatCap Multiply Map");
|
|
DrawProperty(materialEditor, properties, "_MatCapMulIntensity", "MatCap Multiply Intensity");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
});
|
|
|
|
// Rim Light Section
|
|
showRimLight = DrawSection("Rim Light (General)", showRimLight, () =>
|
|
{
|
|
DrawToggleProperty(materialEditor, properties, "_UseRimLight", "Enable Rim Light", "_RIMLIGHT", material);
|
|
if (material.IsKeywordEnabled("_RIMLIGHT"))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
DrawProperty(materialEditor, properties, "_RimLightColor", "Rim Light Color");
|
|
DrawProperty(materialEditor, properties, "_RimLightPower", "Rim Light Power");
|
|
DrawProperty(materialEditor, properties, "_RimLightIntensity", "Rim Light Intensity");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
});
|
|
|
|
// Emission Section
|
|
showEmission = DrawSection("Emission", showEmission, () =>
|
|
{
|
|
DrawToggleProperty(materialEditor, properties, "_UseEmission", "Enable Emission", "_EMISSION", material);
|
|
if (material.IsKeywordEnabled("_EMISSION"))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
DrawProperty(materialEditor, properties, "_EmissionMap", "Emission Map");
|
|
DrawProperty(materialEditor, properties, "_EmissionColor", "Emission Color");
|
|
DrawProperty(materialEditor, properties, "_EmissionIntensity", "Emission Intensity");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
});
|
|
|
|
// Occlusion Section
|
|
showOcclusion = DrawSection("Occlusion", showOcclusion, () =>
|
|
{
|
|
DrawToggleProperty(materialEditor, properties, "_UseOcclusion", "Enable Occlusion Map", "_OCCLUSIONMAP", material);
|
|
if (material.IsKeywordEnabled("_OCCLUSIONMAP"))
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
DrawProperty(materialEditor, properties, "_OcclusionMap", "Occlusion Map");
|
|
DrawProperty(materialEditor, properties, "_OcclusionStrength", "Occlusion Strength");
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
});
|
|
|
|
// Outline Section
|
|
showOutline = DrawSection("Outline", showOutline, () =>
|
|
{
|
|
DrawProperty(materialEditor, properties, "_OutlineWidth", "Outline Width");
|
|
DrawProperty(materialEditor, properties, "_OutlineColor", "Outline Color");
|
|
DrawProperty(materialEditor, properties, "_OutlineWidthMask", "Outline Width Mask");
|
|
});
|
|
|
|
// Rendering Options Section
|
|
showRendering = DrawSection("Rendering Options", showRendering, () =>
|
|
{
|
|
DrawProperty(materialEditor, properties, "_Cull", "Cull Mode");
|
|
DrawProperty(materialEditor, properties, "_FurCull", "Fur Cull Mode");
|
|
DrawProperty(materialEditor, properties, "_ZWrite", "ZWrite");
|
|
DrawProperty(materialEditor, properties, "_FurZWrite", "Fur ZWrite");
|
|
DrawProperty(materialEditor, properties, "_ZTest", "ZTest");
|
|
});
|
|
|
|
EditorGUILayout.Space(10);
|
|
|
|
// Render Queue
|
|
materialEditor.RenderQueueField();
|
|
materialEditor.EnableInstancingField();
|
|
materialEditor.DoubleSidedGIField();
|
|
}
|
|
|
|
private bool DrawSection(string title, bool foldout, Action drawContent)
|
|
{
|
|
EditorGUILayout.Space(2);
|
|
|
|
// Section header with foldout
|
|
Rect headerRect = EditorGUILayout.GetControlRect(false, 20);
|
|
headerRect.x -= 2;
|
|
headerRect.width += 4;
|
|
|
|
// Background
|
|
EditorGUI.DrawRect(headerRect, new Color(0.22f, 0.22f, 0.22f, 1f));
|
|
|
|
// Foldout
|
|
headerRect.x += 4;
|
|
foldout = EditorGUI.Foldout(headerRect, foldout, title, true, foldoutStyle);
|
|
|
|
if (foldout)
|
|
{
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
EditorGUI.indentLevel++;
|
|
drawContent?.Invoke();
|
|
EditorGUI.indentLevel--;
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
return foldout;
|
|
}
|
|
|
|
private void DrawProperty(MaterialEditor editor, MaterialProperty[] properties, string propertyName, string label)
|
|
{
|
|
MaterialProperty prop = FindProperty(propertyName, properties, false);
|
|
if (prop != null)
|
|
{
|
|
editor.ShaderProperty(prop, label);
|
|
}
|
|
}
|
|
|
|
private void DrawToggleProperty(MaterialEditor editor, MaterialProperty[] properties, string propertyName, string label, string keyword, Material material)
|
|
{
|
|
MaterialProperty prop = FindProperty(propertyName, properties, false);
|
|
if (prop != null)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
editor.ShaderProperty(prop, label);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
if (prop.floatValue > 0.5f)
|
|
material.EnableKeyword(keyword);
|
|
else
|
|
material.DisableKeyword(keyword);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawSeparator()
|
|
{
|
|
EditorGUILayout.Space(5);
|
|
Rect rect = EditorGUILayout.GetControlRect(false, 1);
|
|
EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 0.5f));
|
|
EditorGUILayout.Space(5);
|
|
}
|
|
}
|
|
}
|