diff --git a/Assets/NiloToonURP/CHANGELOG.md b/Assets/NiloToonURP/CHANGELOG.md index 4114633aa..af40d1658 100644 --- a/Assets/NiloToonURP/CHANGELOG.md +++ b/Assets/NiloToonURP/CHANGELOG.md @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06ce758ad5ee1dad39025366f23e078545ed7bbfda6c26a0ef5e9d62e4584fe9 -size 254127 +oid sha256:10722f2a7bb3849d5760d2cb3b54f8f5f7bbb97d6be909bfb32dcd187a10ceb1 +size 255631 diff --git a/Assets/NiloToonURP/Editor/AutoGeneratePrefabVariantAndMaterialClone/NiloToonEditor_AutoGeneratePrefabVariantAndAssets.cs b/Assets/NiloToonURP/Editor/AutoGeneratePrefabVariantAndMaterialClone/NiloToonEditor_AutoGeneratePrefabVariantAndAssets.cs index 03248f7b5..eb74b0fac 100644 --- a/Assets/NiloToonURP/Editor/AutoGeneratePrefabVariantAndMaterialClone/NiloToonEditor_AutoGeneratePrefabVariantAndAssets.cs +++ b/Assets/NiloToonURP/Editor/AutoGeneratePrefabVariantAndMaterialClone/NiloToonEditor_AutoGeneratePrefabVariantAndAssets.cs @@ -101,6 +101,7 @@ namespace NiloToon.NiloToonURP // Mapping from original materials to cloned materials Dictionary materialMap = new Dictionary(); + List createdMaterialAssetPaths = new List(); foreach (Material mat in materialsSet) { @@ -118,6 +119,7 @@ namespace NiloToon.NiloToonURP AssetDatabase.CreateAsset(matClone, newMatPath); Debug.Log("Created Material Asset: " + newMatPath); materialMap[mat] = matClone; + createdMaterialAssetPaths.Add(newMatPath); } catch (System.Exception e) { @@ -131,6 +133,18 @@ namespace NiloToon.NiloToonURP // Instantiate the selected prefab GameObject instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab); + if (instance == null) + { + Debug.LogError($"Failed to instantiate prefab before generating NiloToon variant: {assetPath}"); + CleanupGeneratedMaterialAssets(createdMaterialAssetPaths); + return; + } + + int removedMissingScriptCount = RemoveMissingMonoBehavioursRecursive(instance); + if (removedMissingScriptCount > 0) + { + Debug.LogWarning($"Removed {removedMissingScriptCount} missing MonoBehaviour references from temporary prefab instance before generating NiloToon variant."); + } Debug.Log($"Attempting to save prefab variant at path: {variantPath}"); @@ -144,6 +158,7 @@ namespace NiloToon.NiloToonURP Debug.LogError($"Failed to save prefab variant at path: {variantPath}"); Debug.LogException(e); GameObject.DestroyImmediate(instance); + CleanupGeneratedMaterialAssets(createdMaterialAssetPaths); return; } @@ -177,7 +192,10 @@ namespace NiloToon.NiloToonURP } // Run auto setup for the prefab variant - NiloToonEditorPerCharacterRenderControllerCustomEditor.AutoSetupCharacterGameObject(prefabVariantContents); + NiloToonEditorPerCharacterRenderControllerCustomEditor.AutoSetupCharacterGameObject( + prefabVariantContents, + shouldPromptMaterialEditConfirmation: false, + shouldEditMaterialWhenConfirmationSkipped: true); // Save and unload prefab variant PrefabUtility.SaveAsPrefabAsset(prefabVariantContents, variantPath); @@ -187,6 +205,17 @@ namespace NiloToon.NiloToonURP EditorUtility.DisplayDialog("Success", "Prefab variant created with cloned materials.", "OK"); } + static void CleanupGeneratedMaterialAssets(List createdMaterialAssetPaths) + { + foreach (string materialAssetPath in createdMaterialAssetPaths) + { + AssetDatabase.DeleteAsset(materialAssetPath); + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + [MenuItem("Window/NiloToonURP/[Prefab] Create NiloToon Prefab Variant and Materials", priority = 0, validate = true)] [MenuItem("Assets/NiloToon/[Prefab] Create NiloToon Prefab Variant and Materials", priority = 1100 + 0, validate = true)] public static bool ValidateCreatePrefabVariantAndCloneMaterials() @@ -270,5 +299,17 @@ namespace NiloToon.NiloToonURP AssetDatabase.Refresh(); } + + static int RemoveMissingMonoBehavioursRecursive(GameObject root) + { + int removedCount = 0; + + foreach (Transform transform in root.GetComponentsInChildren(true)) + { + removedCount += GameObjectUtility.RemoveMonoBehavioursWithMissingScript(transform.gameObject); + } + + return removedCount; + } } -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Editor/MaterialConvertor/NiloToonMaterialConvertor.cs b/Assets/NiloToonURP/Editor/MaterialConvertor/NiloToonMaterialConvertor.cs index 0982ec9a7..7c4034f70 100644 --- a/Assets/NiloToonURP/Editor/MaterialConvertor/NiloToonMaterialConvertor.cs +++ b/Assets/NiloToonURP/Editor/MaterialConvertor/NiloToonMaterialConvertor.cs @@ -18,6 +18,8 @@ namespace NiloToon.NiloToonURP private static readonly int RenderOutline = Shader.PropertyToID("_RenderOutline"); private static readonly int IsSkin = Shader.PropertyToID("_IsSkin"); private static readonly int IsFace = Shader.PropertyToID("_IsFace"); + private static readonly int DepthTexRimLight3DRimMaskEnable = + Shader.PropertyToID("_DepthTexRimLight3DRimMaskEnable"); private static readonly int PerMaterialEnableDepthTextureRimLightAndShadow = Shader.PropertyToID("_PerMaterialEnableDepthTextureRimLightAndShadow"); @@ -48,6 +50,38 @@ namespace NiloToon.NiloToonURP Transparent } + private sealed class MaterialCloneList : IDisposable + { + private readonly List materials; + + public MaterialCloneList(IReadOnlyList sourceMaterials) + { + materials = new List(sourceMaterials.Count); + for (int i = 0; i < sourceMaterials.Count; i++) + { + Material material = sourceMaterials[i]; + materials.Add(material != null ? Object.Instantiate(material) : null); + } + } + + public int Count => materials.Count; + + public Material this[int index] => materials[index]; + + public void Dispose() + { + foreach (Material material in materials) + { + if (material) + { + Object.DestroyImmediate(material); + } + } + + materials.Clear(); + } + } + public static void AutoConvertMaterialsToNiloToon(List allTargetMaterials) { Shader niloToonCharShader = Shader.Find("Universal Render Pipeline/NiloToon/NiloToon_Character"); @@ -63,13 +97,11 @@ namespace NiloToon.NiloToonURP Shader.Find( "VRM10/Universal Render Pipeline/MToon10"); // share the exact same shader properties with BRP version Shader builtinRPStandardShader = Shader.Find("Standard"); + var renderQueueRepackItems = new List(); + var renderQueueRepackMaterials = new HashSet(); // clone all original materials to a new List with the same order, for later reference, since we will edit the real material later - List allOriginalMaterialsClone = new List(allTargetMaterials); - for (int i = 0; i < allTargetMaterials.Count; i++) - { - allOriginalMaterialsClone[i] = Object.Instantiate(allTargetMaterials[i]); - } + using MaterialCloneList allOriginalMaterialsClone = new MaterialCloneList(allTargetMaterials); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Find the correct NiloToonSurfaceTypePreset index of each original material @@ -87,6 +119,10 @@ namespace NiloToon.NiloToonURP for (int i = 0; i < allOriginalMaterialsClone.Count; i++) { Material matOriginal = allOriginalMaterialsClone[i]; + if (!HasUsableShader(matOriginal)) + { + continue; + } if (matOriginal.shader == UniGLTFUnlitShader) { @@ -268,7 +304,11 @@ namespace NiloToon.NiloToonURP (NiloToonSurfaceTypePreset)(int)matOriginal.GetFloat("_SurfaceTypePreset"); } - if (matOriginal.shader.name.Contains("lilToon")) + if (IsLilToonMultiFamilyShader(matOriginal.shader)) + { + niloToonSurfaceTypePresetIDArray[i] = ResolveLilToonMultiSurfaceTypePreset(matOriginal); + } + else if (matOriginal.shader.name.Contains("lilToon")) { /* // [Rendering Mode] @@ -344,41 +384,13 @@ namespace NiloToon.NiloToonURP else if ( isCutout && isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 32 } - // since there are many model's texture that alpha is not used for transparency(e.g. store special data that is not alpha), - // we will not use texture's alpha to decide if Cutout should be enabled or not anymore - /* - // [feature removed] - // If the NiloToonSurfaceTypePreset is the default one that ignores alpha, use _BaseMap's alpha to determine if cutout is needed - // this step is useful when there is no information about what NiloToonSurfaceTypePreset should be, - // the only information we have is the _BaseMap's alpha, the alpha will hint us what NiloToonSurfaceTypePreset is suitable - if (matOriginal.shader == URPLitShader && niloToonSurfaceTypePresetIDArray[i] == NiloToonSurfaceTypePreset.Opaque_Outline) + if (IsLilToonFurMaterial(matOriginal)) { - Texture2D baseMapTexture; - - // try to get _MainTex first from any BRP material - baseMapTexture = matOriginal.mainTexture as Texture2D; - - // if we can't get one, try to get _BaseMap from any URP material - if (!baseMapTexture) - { - if(matOriginal.HasProperty("_BaseMap")) - { - baseMapTexture = matOriginal.GetTexture("_BaseMap") as Texture2D; - } - } - - // if the material has a _MainTex or _BaseMap - if (baseMapTexture != null) - { - // and if texture has alpha value - if(TextureHasAlpha(baseMapTexture)) - { - // convert Opaque_Outline -> CutoutOpaque_Outline - niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline; - } - } + // NiloToonFurPass renders the opaque queue only. Keep converted fur renderable even when the lilToon source used a transparent fur mode. + niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque; } - */ + + // Do not use texture alpha to infer cutout: many models store non-transparency data in alpha. } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -388,6 +400,11 @@ namespace NiloToon.NiloToonURP //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// foreach (var mat in allTargetMaterials) { + if (mat == null) + { + continue; + } + // skip for vrm mtoon, since we will not rely on URP's material upgrader, and handle everything by ourself if (mat.shader == VRMBRPMToon00Shader || mat.shader == VRMBRPMToon10Shader || @@ -396,7 +413,14 @@ namespace NiloToon.NiloToonURP // Ensure not a variant BreakMaterialVariant(mat); - + + if (!HasUsableShader(mat)) + { + mat.shader = builtinRPStandardShader; + EditorUtility.SetDirty(mat); + continue; + } + // support these special shaders from URP's package: // - PhysicalMaterial3DsMax // - ArnoldStandardSurface @@ -432,18 +456,17 @@ namespace NiloToon.NiloToonURP HashSet shaderNamesToIgnore = new HashSet(); GetShaderNamesToIgnore(ref shaderNamesToIgnore); - // set selection to materials that we want to upgrade - UnityEngine.Object[] targets = new UnityEngine.Object[allTargetMaterials.Count]; - targets = allTargetMaterials.ToArray(); - var originalSelectionObjects = Selection.objects; - Selection.objects = targets; + for (int i = 0; i < allTargetMaterials.Count; i++) + { + Material material = allTargetMaterials[i]; + if (!ShouldUpgradeMaterialNonInteractively(material, shaderNamesToIgnore)) + { + continue; + } - // call SRP's UpgradeSelection() - MaterialUpgrader.UpgradeSelection(upgraders, shaderNamesToIgnore, "Upgrade to UniversalRP Materials", - MaterialUpgrader.UpgradeFlags.LogMessageWhenNoUpgraderFound); - - // restore Selection - Selection.objects = originalSelectionObjects; + MaterialUpgrader.Upgrade(material, upgraders, + MaterialUpgrader.UpgradeFlags.LogMessageWhenNoUpgraderFound); + } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // switch material to "NiloToon_Character" shader, @@ -457,7 +480,16 @@ namespace NiloToon.NiloToonURP // Ensure not a variant BreakMaterialVariant(mat); - + if (!HasUsableShader(mat)) + { + continue; + } + + bool hasUsableOriginalShader = HasUsableShader(originalMatClone); + string currentShaderName = mat.shader.name; + string originalShaderName = hasUsableOriginalShader ? originalMatClone.shader.name : string.Empty; + int sourceRenderQueue = hasUsableOriginalShader ? originalMatClone.renderQueue : mat.renderQueue; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // if material is URP package's material (e.g. Lit.mat), // skip editing the material, @@ -474,8 +506,8 @@ namespace NiloToon.NiloToonURP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // if material is Particle or Sprite shader, skip editing it ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (mat.shader.name.Contains("Particle") || - mat.shader.name.Contains("Sprite")) + if (currentShaderName.Contains("Particle") || + currentShaderName.Contains("Sprite")) { continue; } @@ -484,7 +516,7 @@ namespace NiloToon.NiloToonURP // if the current shader is not any NiloToon shader // switch this shader to NiloToon_Character shader ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (!mat.shader.name.Contains("NiloToon")) + if (!currentShaderName.Contains("NiloToon")) { int originalRenderQueue = mat.renderQueue; @@ -563,13 +595,13 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------- List IsNoOutlineFinalTargetNames = IsFaceFinalTargetNames.Where(x => x != "face" && x != "head").ToList(); - IsNoOutlineFinalTargetNames.Concat(IsNoOutlineTargetNames); + IsNoOutlineFinalTargetNames = IsNoOutlineFinalTargetNames.Concat(IsNoOutlineTargetNames).ToList(); List IsNoOutlineExactTargetNames = new List(); - IsNoOutlineExactTargetNames.Concat(IsFaceExactTargetNames); + IsNoOutlineExactTargetNames = IsNoOutlineExactTargetNames.Concat(IsFaceExactTargetNames).ToList(); List IsNoOutlineFinalBanNames = IsFaceFinalBanNames.ToList(); - IsNoOutlineFinalBanNames.Concat(IsNoOutlineBanNames); + IsNoOutlineFinalBanNames = IsNoOutlineFinalBanNames.Concat(IsNoOutlineBanNames).ToList(); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // auto disable classic outline if material name contain face/outline related keywords that should not render classic outline @@ -622,15 +654,18 @@ namespace NiloToon.NiloToonURP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // auto set SurfaceType preset - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SetMaterialNiloToonSurfaceTypeAndProperties(mat, nilotoonSurfaceTypePresetID); + // Group by the converted NiloToon preset. Source queues only preserve order inside the chosen opaque/transparent group. + bool targetUsesOpaqueQueue = mat.renderQueue <= (int)RenderQueue.GeometryLast; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // port common vrm00 mtoon00 & vrm10 mtoon10 to nilotoon ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (originalMatClone.shader == VRMBRPMToon00Shader || + if (hasUsableOriginalShader && + (originalMatClone.shader == VRMBRPMToon00Shader || originalMatClone.shader == VRMBRPMToon10Shader || - originalMatClone.shader == VRMURPMToon10Shader) + originalMatClone.shader == VRMURPMToon10Shader)) { // port base map mat.SetTexture("_BaseMap", originalMatClone.GetTexture("_MainTex")); @@ -652,7 +687,7 @@ namespace NiloToon.NiloToonURP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // auto set outline extra mul for VRM00 mtoon00 material ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (originalMatClone.shader == VRMBRPMToon00Shader) + if (hasUsableOriginalShader && originalMatClone.shader == VRMBRPMToon00Shader) { const float niloToonWidthRelativeToMToon00 = 12; //12~18 is good mat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeToMToon00); @@ -667,8 +702,9 @@ namespace NiloToon.NiloToonURP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // auto set outline extra mul for VRM10 mtoon10 material ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (originalMatClone.shader == VRMBRPMToon10Shader || - originalMatClone.shader == VRMURPMToon10Shader) + if (hasUsableOriginalShader && + (originalMatClone.shader == VRMBRPMToon10Shader || + originalMatClone.shader == VRMURPMToon10Shader)) { const float niloToonWidthRelativeToMToon10 = 512; mat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeToMToon10); @@ -683,7 +719,7 @@ namespace NiloToon.NiloToonURP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // port vrm00 mtoon00 properties to nilotoon ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (originalMatClone.shader == VRMBRPMToon00Shader) + if (hasUsableOriginalShader && originalMatClone.shader == VRMBRPMToon00Shader) { float MToonScrollX = originalMatClone.GetFloat("_UvAnimScrollX"); float MToonScrollY = originalMatClone.GetFloat("_UvAnimScrollY"); @@ -754,8 +790,9 @@ namespace NiloToon.NiloToonURP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // port vrm10 mtoon10 properties to nilotoon ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (originalMatClone.shader == VRMBRPMToon10Shader || - originalMatClone.shader == VRMURPMToon10Shader) + if (hasUsableOriginalShader && + (originalMatClone.shader == VRMBRPMToon10Shader || + originalMatClone.shader == VRMURPMToon10Shader)) { float MToonScrollX = originalMatClone.GetFloat("_UvAnimScrollXSpeed"); float MToonScrollY = originalMatClone.GetFloat("_UvAnimScrollYSpeed"); @@ -793,6 +830,8 @@ namespace NiloToon.NiloToonURP break; } + // Batch repack normally overwrites this value and uses originalMatClone.renderQueue as the ordering signal. + // Validated UniVRM MToon10 already includes this offset there; this legacy add only matters if repack falls back. mat.renderQueue += (int)originalMatClone.GetFloat("_RenderQueueOffset"); Texture2D _ShadeTex = originalMatClone.GetTexture("_ShadeTex") as Texture2D; @@ -815,7 +854,7 @@ namespace NiloToon.NiloToonURP ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // port liltoon properties to nilotoon ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (originalMatClone.shader.name.Contains("lilToon")) + if (originalShaderName.Contains("lilToon")) { Port_lilToon_properties_To_NiloToon(originalMatClone, mat); } @@ -827,8 +866,9 @@ namespace NiloToon.NiloToonURP // - any lilToon shader // since we handled them already, if we do it again here, we may enable texture features that should be keep disabled) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if ((originalMatClone.shader != niloToonCharShader) && - !(originalMatClone.name.Contains("lilToon"))) + if (!hasUsableOriginalShader || + ((originalMatClone.shader != niloToonCharShader) && + !originalShaderName.Contains("lilToon"))) { if (mat.GetTexture("_OutlineWidthTex")) { @@ -856,7 +896,7 @@ namespace NiloToon.NiloToonURP // Reset _Parallax from 0.02 -> 0.005(default value) if _ParallaxMap doesn't exist // so _Parallax is not a modified property which confuses user ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (originalMatClone.HasProperty("_ParallaxMap")) + if (hasUsableOriginalShader && originalMatClone.HasProperty("_ParallaxMap")) { if (!originalMatClone.GetTexture("_ParallaxMap")) { @@ -912,15 +952,13 @@ namespace NiloToon.NiloToonURP SetMaterialAsIsSkin(mat); } - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // auto disable depth tex shadow if - // - it is eye (e.g. eye white material) - // - it doesn't draw depth texture (e.g., render queue >= 2500) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (NiloToonUtils.NameHasKeyword(mat.name, "eye") || - mat.renderQueue >= 2500) + if (renderQueueRepackMaterials.Add(mat)) { - mat.SetFloat(PerMaterialEnableDepthTextureRimLightAndShadow, 0); + renderQueueRepackItems.Add(new RenderQueueRepackItem( + mat, + sourceRenderQueue, + i, + targetUsesOpaqueQueue)); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -958,6 +996,790 @@ namespace NiloToon.NiloToonURP EditorUtility.SetDirty(mat); } } + + RepackRenderQueuesPreservingRelativeOrder(renderQueueRepackItems); + foreach (RenderQueueRepackItem item in renderQueueRepackItems) + { + AutoDisableDepthTextureRimLightAndShadowIfNeeded(item.Material); + EditorUtility.SetDirty(item.Material); + } + } + + private readonly struct RenderQueueRepackItem + { + public RenderQueueRepackItem( + Material material, + int sourceRenderQueue, + int originalIndex, + bool targetUsesOpaqueQueue) + { + Material = material; + SourceRenderQueue = sourceRenderQueue; + OriginalIndex = originalIndex; + TargetUsesOpaqueQueue = targetUsesOpaqueQueue; + } + + public Material Material { get; } + public int SourceRenderQueue { get; } + public int OriginalIndex { get; } + public bool TargetUsesOpaqueQueue { get; } + } + + private sealed class RenderQueueBucket + { + public int SourceRenderQueue; + public int AssignedRenderQueue; + public readonly List Items = new List(); + } + + private static void RepackRenderQueuesPreservingRelativeOrder(List items) + { + RepackRenderQueueGroup(items, true, 0, (int)RenderQueue.GeometryLast); + RepackRenderQueueGroup(items, false, (int)RenderQueue.GeometryLast + 1, (int)RenderQueue.Overlay - 1); + } + + private static void RepackRenderQueueGroup( + List allItems, + bool targetUsesOpaqueQueue, + int minQueue, + int maxQueue) + { + List groupItems = allItems + .Where(item => item.TargetUsesOpaqueQueue == targetUsesOpaqueQueue) + .OrderBy(item => item.SourceRenderQueue) + .ThenBy(item => item.OriginalIndex) + .ToList(); + + if (groupItems.Count == 0) + { + return; + } + + List buckets = CreateRenderQueueBuckets(groupItems); + if (buckets.Count > maxQueue - minQueue + 1) + { + Debug.LogWarning( + $"[NiloToon] Too many distinct render queues ({buckets.Count}) to preserve relative order inside {minQueue}..{maxQueue}."); + return; + } + + for (int i = 0; i < buckets.Count; i++) + { + buckets[i].AssignedRenderQueue = Mathf.Clamp(buckets[i].SourceRenderQueue, minQueue, maxQueue); + if (i > 0 && buckets[i].AssignedRenderQueue <= buckets[i - 1].AssignedRenderQueue) + { + buckets[i].AssignedRenderQueue = buckets[i - 1].AssignedRenderQueue + 1; + } + } + + if (buckets[buckets.Count - 1].AssignedRenderQueue > maxQueue) + { + buckets[buckets.Count - 1].AssignedRenderQueue = maxQueue; + for (int i = buckets.Count - 2; i >= 0; i--) + { + if (buckets[i].AssignedRenderQueue >= buckets[i + 1].AssignedRenderQueue) + { + buckets[i].AssignedRenderQueue = buckets[i + 1].AssignedRenderQueue - 1; + } + } + } + + foreach (RenderQueueBucket bucket in buckets) + { + foreach (RenderQueueRepackItem item in bucket.Items) + { + item.Material.renderQueue = bucket.AssignedRenderQueue; + } + } + } + + private static List CreateRenderQueueBuckets(List sortedItems) + { + var buckets = new List(); + foreach (RenderQueueRepackItem item in sortedItems) + { + RenderQueueBucket bucket = buckets.Count > 0 && buckets[buckets.Count - 1].SourceRenderQueue == item.SourceRenderQueue + ? buckets[buckets.Count - 1] + : null; + if (bucket == null) + { + bucket = new RenderQueueBucket { SourceRenderQueue = item.SourceRenderQueue }; + buckets.Add(bucket); + } + + bucket.Items.Add(item); + } + + return buckets; + } + + private static void AutoDisableDepthTextureRimLightAndShadowIfNeeded(Material mat) + { + if (NiloToonUtils.NameHasKeyword(mat.name, "eye") || + mat.renderQueue > (int)RenderQueue.GeometryLast) + { + mat.SetFloat(PerMaterialEnableDepthTextureRimLightAndShadow, 0); + } + } + + private static bool IsLilToonMultiFamilyShader(Shader shader) + { + return shader != null && + shader.name.Contains("lilToonMulti", StringComparison.Ordinal); + } + + private static bool IsLilToonFurMaterial(Material material) + { + if (!HasUsableShader(material)) + { + return false; + } + + string shaderName = material.shader.name; + bool isLilToonFamily = shaderName.Contains("lilToon", StringComparison.Ordinal); + if (!isLilToonFamily) + { + return false; + } + + if (shaderName.Contains("Fur", StringComparison.Ordinal)) + { + return true; + } + + if (IsLilToonMultiFamilyShader(material.shader) && material.HasProperty("_TransparentMode")) + { + int transparentMode = Mathf.RoundToInt(material.GetFloat("_TransparentMode")); + return transparentMode == 4 || transparentMode == 5; + } + + return material.HasProperty("_FurNoiseMask") || + material.HasProperty("_FurMask") || + material.HasProperty("_FurLengthMask") || + material.HasProperty("_FurVector") || + material.HasProperty("_FurLayerNum"); + } + + private static NiloToonSurfaceTypePreset ResolveLilToonMultiSurfaceTypePreset(Material matOriginal) + { + int transparentMode = matOriginal.HasProperty("_TransparentMode") + ? Mathf.RoundToInt(matOriginal.GetFloat("_TransparentMode")) + : 0; + bool useOutline = matOriginal.HasProperty("_UseOutline") && matOriginal.GetFloat("_UseOutline") > 0.5f; + bool zWrite = !matOriginal.HasProperty("_ZWrite") || matOriginal.GetFloat("_ZWrite") > 0.5f; + bool isTransparentQueue = matOriginal.renderQueue > 2500; + + switch (transparentMode) + { + case 0: + return ResolveLilToonMultiOpaquePreset(useOutline, zWrite); + case 1: + return ResolveLilToonMultiCutoutPreset(useOutline, zWrite); + case 2: + return ResolveLilToonMultiTransparentPreset(useOutline, zWrite, isTransparentQueue); + case 3: + // lilToonMulti refraction uses its own shader path without outline and falls back closest to opaque surface family. + return ResolveLilToonMultiOpaquePreset(false, zWrite); + case 4: + // NiloToonFurPass renders opaque queue only, so converted fur must stay in the cutout/opaque family. + return ResolveLilToonMultiCutoutPreset(false, true); + case 5: + // lilToonMulti fur cutout uses alpha clip but does not expose an outline variant. + return ResolveLilToonMultiCutoutPreset(false, zWrite); + case 6: + // lilToonMulti gem is additive/transparent and does not expose an outline variant. + return ResolveLilToonMultiTransparentPreset(false, zWrite, isTransparentQueue); + default: + Debug.LogWarning( + $"Unsupported lilToonMulti _TransparentMode '{transparentMode}' on material '{matOriginal.name}'. Falling back to opaque surface family."); + return ResolveLilToonMultiOpaquePreset(false, zWrite); + } + } + + private static NiloToonSurfaceTypePreset ResolveLilToonMultiOpaquePreset( + bool useOutline, + bool zWrite) + { + if (!zWrite) + { + return NiloToonSurfaceTypePreset.Transparent; + } + + return useOutline + ? NiloToonSurfaceTypePreset.Opaque_Outline + : NiloToonSurfaceTypePreset.Opaque; + } + + private static NiloToonSurfaceTypePreset ResolveLilToonMultiTransparentPreset( + bool useOutline, + bool zWrite, + bool isTransparentQueue) + { + if (!zWrite) + { + return NiloToonSurfaceTypePreset.Transparent; + } + + if (isTransparentQueue) + { + return useOutline + ? NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite_Outline + : NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite; + } + + return useOutline + ? NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline + : NiloToonSurfaceTypePreset.Transparent_ZWrite; + } + + private static NiloToonSurfaceTypePreset ResolveLilToonMultiCutoutPreset( + bool useOutline, + bool zWrite) + { + if (!zWrite) + { + return NiloToonSurfaceTypePreset.CutoutTransparent; + } + + // NiloToon has no cutout-opaque + transparent-queue preset, so the closest representable family stays in cutout opaque. + return useOutline + ? NiloToonSurfaceTypePreset.CutoutOpaque_Outline + : NiloToonSurfaceTypePreset.CutoutOpaque; + } + + private static void SetKeyword(Material material, string keyword, bool enabled) + { + if (enabled) + { + material.EnableKeyword(keyword); + } + else + { + material.DisableKeyword(keyword); + } + } + + private static readonly Vector4 DefaultTextureScaleOffset = new Vector4(1f, 1f, 0f, 0f); + + private static bool HasShaderProperty(Material material, string property, ShaderPropertyType propertyType) + { + if (!material || !material.shader) + { + return false; + } + + int propertyIndex = material.shader.FindPropertyIndex(property); + return propertyIndex >= 0 && material.shader.GetPropertyType(propertyIndex) == propertyType; + } + + private static bool HasFloatProperty(Material material, string property) + { + if (!material || !material.shader) + { + return false; + } + + int propertyIndex = material.shader.FindPropertyIndex(property); + if (propertyIndex < 0) + { + return false; + } + + ShaderPropertyType propertyType = material.shader.GetPropertyType(propertyIndex); + return propertyType == ShaderPropertyType.Float || + propertyType == ShaderPropertyType.Range || + propertyType.ToString() == "Int"; + } + + private static float GetFloatOrDefault(Material material, string property, float defaultValue = 0f) + { + return HasFloatProperty(material, property) ? material.GetFloat(property) : defaultValue; + } + + private static Color GetColorOrDefault(Material material, string property, Color defaultValue) + { + return HasShaderProperty(material, property, ShaderPropertyType.Color) ? material.GetColor(property) : defaultValue; + } + + private static Vector4 GetVectorOrDefault(Material material, string property, Vector4 defaultValue) + { + return HasShaderProperty(material, property, ShaderPropertyType.Vector) ? material.GetVector(property) : defaultValue; + } + + private static Texture GetTextureOrNull(Material material, string property) + { + return HasShaderProperty(material, property, ShaderPropertyType.Texture) ? material.GetTexture(property) : null; + } + + private static Vector4 GetTextureScaleOffsetOrDefault(Material material, string textureProperty) + { + if (!HasShaderProperty(material, textureProperty, ShaderPropertyType.Texture)) + { + return DefaultTextureScaleOffset; + } + + Vector2 scale = material.GetTextureScale(textureProperty); + Vector2 offset = material.GetTextureOffset(textureProperty); + return new Vector4(scale.x, scale.y, offset.x, offset.y); + } + + private static void CopyFloat(Material source, Material destination, string sourceProperty, string destinationProperty) + { + if (!HasFloatProperty(source, sourceProperty) || !HasFloatProperty(destination, destinationProperty)) + { + return; + } + + destination.SetFloat(destinationProperty, source.GetFloat(sourceProperty)); + } + + private static void CopyColor(Material source, Material destination, string sourceProperty, string destinationProperty) + { + if (!HasShaderProperty(source, sourceProperty, ShaderPropertyType.Color) || + !HasShaderProperty(destination, destinationProperty, ShaderPropertyType.Color)) + { + return; + } + + destination.SetColor(destinationProperty, source.GetColor(sourceProperty)); + } + + private static void CopyVector(Material source, Material destination, string sourceProperty, string destinationProperty) + { + if (!HasShaderProperty(source, sourceProperty, ShaderPropertyType.Vector) || + !HasShaderProperty(destination, destinationProperty, ShaderPropertyType.Vector)) + { + return; + } + + destination.SetVector(destinationProperty, source.GetVector(sourceProperty)); + } + + private static void CopyTextureWithScaleOffset(Material source, Material destination, string sourceProperty, string destinationProperty) + { + if (!HasShaderProperty(source, sourceProperty, ShaderPropertyType.Texture) || + !HasShaderProperty(destination, destinationProperty, ShaderPropertyType.Texture)) + { + return; + } + + destination.SetTexture(destinationProperty, source.GetTexture(sourceProperty)); + destination.SetTextureScale(destinationProperty, source.GetTextureScale(sourceProperty)); + destination.SetTextureOffset(destinationProperty, source.GetTextureOffset(sourceProperty)); + } + + private static void SetFloatIfHasProperty(Material material, string property, float value) + { + if (!HasFloatProperty(material, property)) + { + return; + } + + material.SetFloat(property, value); + } + + private static void SetColorIfHasProperty(Material material, string property, Color value) + { + if (!material.HasProperty(property)) + { + return; + } + + material.SetColor(property, value); + } + + private static void SetTextureIfHasProperty(Material material, string property, Texture value) + { + if (!material.HasProperty(property)) + { + return; + } + + material.SetTexture(property, value); + } + + private static void SetLilToonShadowAOMinMax(Material material, string minProperty, string maxProperty, float scale, float offset) + { + if (Mathf.Abs(scale) < 0.00001f) + { + SetFloatIfHasProperty(material, minProperty, 0f); + SetFloatIfHasProperty(material, maxProperty, 1f); + return; + } + + SetFloatIfHasProperty(material, minProperty, Mathf.Clamp(-offset / scale, -0.01f, 1.01f)); + SetFloatIfHasProperty(material, maxProperty, Mathf.Clamp((1f - offset) / scale, -0.01f, 1.01f)); + } + + private static void PortLilToonShadowAORemap(Material source, Material destination) + { + if (HasShaderProperty(source, "_ShadowAOShift", ShaderPropertyType.Vector)) + { + Vector4 shadowAOShift = source.GetVector("_ShadowAOShift"); + SetLilToonShadowAOMinMax(destination, "_lilShadowAO1Min", "_lilShadowAO1Max", shadowAOShift.x, shadowAOShift.y); + SetLilToonShadowAOMinMax(destination, "_lilShadowAO2Min", "_lilShadowAO2Max", shadowAOShift.z, shadowAOShift.w); + } + + if (HasShaderProperty(source, "_ShadowAOShift2", ShaderPropertyType.Vector)) + { + Vector4 shadowAOShift2 = source.GetVector("_ShadowAOShift2"); + SetLilToonShadowAOMinMax(destination, "_lilShadowAO3Min", "_lilShadowAO3Max", shadowAOShift2.x, shadowAOShift2.y); + } + } + + private static void PortLilToonShadowModeProperties(Material source, Material destination) + { + CopyFloat(source, destination, "_ShadowMaskType", "_lilShadowMaskType"); + CopyTextureWithScaleOffset(source, destination, "_ShadowStrengthMask", "_lilShadowStrengthMask"); + CopyFloat(source, destination, "_ShadowStrength", "_lilShadowStrength"); + CopyFloat(source, destination, "_ShadowStrengthMaskLOD", "_lilShadowStrengthMaskLOD"); + CopyFloat(source, destination, "_ShadowFlatBorder", "_lilShadowFlatBorder"); + CopyFloat(source, destination, "_ShadowFlatBlur", "_lilShadowFlatBlur"); + + CopyFloat(source, destination, "_ShadowColorType", "_lilShadowColorType"); + CopyTextureWithScaleOffset(source, destination, "_ShadowColorTex", "_lilShadowColorTex"); + CopyTextureWithScaleOffset(source, destination, "_Shadow2ndColorTex", "_lilShadow2ndColorTex"); + CopyTextureWithScaleOffset(source, destination, "_Shadow3rdColorTex", "_lilShadow3rdColorTex"); + CopyColor(source, destination, "_ShadowColor", "_lilShadowColor"); + CopyColor(source, destination, "_Shadow2ndColor", "_lilShadow2ndColor"); + CopyColor(source, destination, "_Shadow3rdColor", "_lilShadow3rdColor"); + CopyFloat(source, destination, "_ShadowBorder", "_lilShadowBorder"); + CopyFloat(source, destination, "_ShadowBlur", "_lilShadowBlur"); + CopyFloat(source, destination, "_ShadowNormalStrength", "_lilShadowNormalStrength"); + CopyFloat(source, destination, "_ShadowReceive", "_lilShadowReceive"); + CopyFloat(source, destination, "_Shadow2ndBorder", "_lilShadow2ndBorder"); + CopyFloat(source, destination, "_Shadow2ndBlur", "_lilShadow2ndBlur"); + CopyFloat(source, destination, "_Shadow2ndNormalStrength", "_lilShadow2ndNormalStrength"); + CopyFloat(source, destination, "_Shadow2ndReceive", "_lilShadow2ndReceive"); + CopyFloat(source, destination, "_Shadow3rdBorder", "_lilShadow3rdBorder"); + CopyFloat(source, destination, "_Shadow3rdBlur", "_lilShadow3rdBlur"); + CopyFloat(source, destination, "_Shadow3rdNormalStrength", "_lilShadow3rdNormalStrength"); + CopyFloat(source, destination, "_Shadow3rdReceive", "_lilShadow3rdReceive"); + + CopyColor(source, destination, "_ShadowBorderColor", "_lilShadowBorderColor"); + CopyFloat(source, destination, "_ShadowBorderRange", "_lilShadowBorderRange"); + CopyFloat(source, destination, "_ShadowMainStrength", "_lilShadowMainStrength"); + CopyFloat(source, destination, "_ShadowEnvStrength", "_lilShadowEnvStrength"); + CopyFloat(source, destination, "_AAStrength", "_lilAAStrength"); + + CopyTextureWithScaleOffset(source, destination, "_ShadowBlurMask", "_lilShadowBlurMask"); + CopyFloat(source, destination, "_ShadowBlurMaskLOD", "_lilShadowBlurMaskLOD"); + CopyTextureWithScaleOffset(source, destination, "_ShadowBorderMask", "_lilShadowBorderMask"); + CopyFloat(source, destination, "_ShadowBorderMaskLOD", "_lilShadowBorderMaskLOD"); + CopyFloat(source, destination, "_ShadowPostAO", "_lilShadowPostAO"); + } + + private static void DisableNativeNiloMatCapGroups(Material material) + { + material.SetFloat("_UseMatCapAlphaBlend", 0); + material.SetFloat("_UseMatCapAdditive", 0); + material.SetFloat("_UseMatCapOcclusion", 0); + material.DisableKeyword("_MATCAP_BLEND"); + material.DisableKeyword("_MATCAP_ADD"); + material.DisableKeyword("_MATCAP_OCCLUSION"); + } + + private static void PortLilToonMatCapLayerToGeneric( + Material source, + Material destination, + string sourceUse, + string destinationUse, + string destinationKeyword, + string sourceColor, + string destinationColor, + string sourceMap, + string destinationMap, + string sourceMainStrength, + string destinationMainStrength, + string sourceBlendUv1, + string destinationBlendUv1, + string sourceZRotCancel, + string destinationZRotCancel, + string sourcePerspective, + string destinationPerspective, + string sourceVrParallaxStrength, + string destinationVrParallaxStrength, + string sourceBlend, + string destinationBlend, + string sourceMask, + string destinationMask, + string sourceEnableLighting, + string destinationEnableLighting, + string sourceShadowMask, + string destinationShadowMask, + string sourceBackfaceMask, + string destinationBackfaceMask, + string sourceLod, + string destinationLod, + string sourceBlendMode, + string destinationBlendMode, + string sourceApplyTransparency, + string destinationApplyTransparency, + string sourceNormalStrength, + string destinationNormalStrength, + string sourceUseCustomNormal, + string destinationUseCustomNormal, + string destinationCustomNormalKeyword, + string sourceBumpMap, + string destinationBumpMap, + string sourceBumpScale, + string destinationBumpScale) + { + CopyFloat(source, destination, sourceUse, destinationUse); + CopyColor(source, destination, sourceColor, destinationColor); + CopyTextureWithScaleOffset(source, destination, sourceMap, destinationMap); + CopyFloat(source, destination, sourceMainStrength, destinationMainStrength); + CopyVector(source, destination, sourceBlendUv1, destinationBlendUv1); + CopyFloat(source, destination, sourceZRotCancel, destinationZRotCancel); + CopyFloat(source, destination, sourcePerspective, destinationPerspective); + CopyFloat(source, destination, sourceVrParallaxStrength, destinationVrParallaxStrength); + CopyFloat(source, destination, sourceBlend, destinationBlend); + CopyTextureWithScaleOffset(source, destination, sourceMask, destinationMask); + CopyFloat(source, destination, sourceEnableLighting, destinationEnableLighting); + CopyFloat(source, destination, sourceShadowMask, destinationShadowMask); + CopyFloat(source, destination, sourceBackfaceMask, destinationBackfaceMask); + CopyFloat(source, destination, sourceLod, destinationLod); + CopyFloat(source, destination, sourceBlendMode, destinationBlendMode); + CopyFloat(source, destination, sourceApplyTransparency, destinationApplyTransparency); + CopyFloat(source, destination, sourceNormalStrength, destinationNormalStrength); + CopyFloat(source, destination, sourceUseCustomNormal, destinationUseCustomNormal); + CopyTextureWithScaleOffset(source, destination, sourceBumpMap, destinationBumpMap); + CopyFloat(source, destination, sourceBumpScale, destinationBumpScale); + + bool isEnabled = HasFloatProperty(source, sourceUse) && source.GetFloat(sourceUse) > 0.5f; + bool useCustomNormal = HasFloatProperty(source, sourceUseCustomNormal) && source.GetFloat(sourceUseCustomNormal) > 0.5f; + + SetKeyword(destination, destinationKeyword, isEnabled); + SetKeyword(destination, destinationCustomNormalKeyword, isEnabled && useCustomNormal); + } + + private static void PortLilToonRimToGenericRimLight3D(Material source, Material destination) + { + CopyFloat(source, destination, "_UseRim", "_UseGenericRimLight3D"); + CopyColor(source, destination, "_RimColor", "_GenericRimLight3DColor"); + CopyTextureWithScaleOffset(source, destination, "_RimColorTex", "_GenericRimLight3DColorTex"); + CopyFloat(source, destination, "_RimMainStrength", "_GenericRimLight3DMainStrength"); + CopyFloat(source, destination, "_RimEnableLighting", "_GenericRimLight3DEnableLighting"); + CopyFloat(source, destination, "_RimShadowMask", "_GenericRimLight3DShadowMask"); + CopyFloat(source, destination, "_RimBackfaceMask", "_GenericRimLight3DBackfaceMask"); + CopyFloat(source, destination, "_RimBlendMode", "_GenericRimLight3DBlendMode"); + CopyFloat(source, destination, "_RimDirStrength", "_GenericRimLight3DDirStrength"); + CopyFloat(source, destination, "_RimDirRange", "_GenericRimLight3DDirRange"); + CopyFloat(source, destination, "_RimBorder", "_GenericRimLight3DBorder"); + CopyFloat(source, destination, "_RimBlur", "_GenericRimLight3DBlur"); + CopyFloat(source, destination, "_RimIndirRange", "_GenericRimLight3DIndirRange"); + CopyColor(source, destination, "_RimIndirColor", "_GenericRimLight3DIndirColor"); + CopyFloat(source, destination, "_RimIndirBorder", "_GenericRimLight3DIndirBorder"); + CopyFloat(source, destination, "_RimIndirBlur", "_GenericRimLight3DIndirBlur"); + CopyFloat(source, destination, "_RimNormalStrength", "_GenericRimLight3DNormalStrength"); + CopyFloat(source, destination, "_RimFresnelPower", "_GenericRimLight3DFresnelPower"); + CopyFloat(source, destination, "_RimVRParallaxStrength", "_GenericRimLight3DVRParallaxStrength"); + + if (destination.HasProperty("_GenericRimLight3DAlpha")) + { + destination.SetFloat("_GenericRimLight3DAlpha", 1f); + } + + bool isEnabled = HasFloatProperty(source, "_UseRim") && source.GetFloat("_UseRim") > 0.5f; + SetKeyword(destination, "_GENERIC_RIMLIGHT3D", isEnabled); + } + + private static void SetFloatClampedIfHasProperty(Material source, Material destination, string sourceProperty, string destinationProperty, float min, float max) + { + if (!source.HasProperty(sourceProperty) || !destination.HasProperty(destinationProperty)) + { + return; + } + + destination.SetFloat(destinationProperty, Mathf.Clamp(source.GetFloat(sourceProperty), min, max)); + } + + private static void SetNiloFurNoiseTilingFromLilToon(Material source, Material destination) + { + if (!source.HasProperty("_FurNoiseMask") || !destination.HasProperty("_NiloFurNoiseTiling")) + { + return; + } + + Vector2 scale = source.GetTextureScale("_FurNoiseMask"); + Vector2 offset = source.GetTextureOffset("_FurNoiseMask"); + destination.SetVector("_NiloFurNoiseTiling", new Vector4(scale.x, scale.y, offset.x, offset.y)); + } + + private static void SetDefaultFurNoiseIfNeeded(Material destination) + { + if (!destination.HasProperty("_NiloFurNoiseTex") || destination.GetTexture("_NiloFurNoiseTex") != null) + { + return; + } + + Texture2D defaultFurNoise = + AssetDatabase.LoadAssetAtPath("Assets/NiloToonURP/Textures/NiloFurNoise.png"); + if (defaultFurNoise != null) + { + destination.SetTexture("_NiloFurNoiseTex", defaultFurNoise); + } + } + + private static void PortLilToonFurProperties(Material source, Material destination) + { + if (!IsLilToonFurMaterial(source)) + { + return; + } + + SetMaterialNiloToonSurfaceTypeAndProperties(destination, NiloToonSurfaceTypePreset.CutoutOpaque); + + SetFloatIfHasProperty(destination, "_EnableFur", 1f); + SetFloatIfHasProperty(destination, "_NiloFurStrength", 1f); + SetFloatIfHasProperty(destination, "_AllowRenderURPUniversalForwardOnlyPass", 1f); + SetKeyword(destination, "_NILOTOON_FUR", true); + + destination.SetShaderPassEnabled("UniversalForwardOnly", true); + destination.SetShaderPassEnabled("NiloToonFur", true); + destination.SetShaderPassEnabled("NiloToonFurDepthPrepass", true); + destination.SetShaderPassEnabled("NiloToonFurPrepassBufferDepth", true); + destination.SetShaderPassEnabled("NiloToonFurPrepassBufferAlpha", true); + + CopyTextureWithScaleOffset(source, destination, "_FurNoiseMask", "_NiloFurNoiseTex"); + SetNiloFurNoiseTilingFromLilToon(source, destination); + SetDefaultFurNoiseIfNeeded(destination); + + CopyTextureWithScaleOffset(source, destination, "_FurMask", "_NiloFurMask"); + CopyTextureWithScaleOffset(source, destination, "_FurLengthMask", "_NiloFurLengthMask"); + CopyTextureWithScaleOffset(source, destination, "_FurVectorTex", "_NiloFurVectorTex"); + bool hasVectorTexture = destination.HasProperty("_NiloFurVectorTex") && + destination.GetTexture("_NiloFurVectorTex") != null; + SetKeyword(destination, "_NILOTOON_FUR_VECTORTEX", hasVectorTexture); + + CopyFloat(source, destination, "_FurVectorScale", "_NiloFurVectorScale"); + if (source.HasProperty("_FurVector") && destination.HasProperty("_NiloFurVector")) + { + Vector4 furVector = source.GetVector("_FurVector"); + destination.SetVector("_NiloFurVector", new Vector4(furVector.x, furVector.y, furVector.z, 0f)); + SetFloatIfHasProperty(destination, "_NiloFurLength", Mathf.Max(0f, furVector.w)); + } + + CopyFloat(source, destination, "_VertexColor2FurVector", "_VertexColor2FurVector"); + CopyFloat(source, destination, "_FurGravity", "_NiloFurGravity"); + CopyFloat(source, destination, "_FurRandomize", "_NiloFurRandomize"); + CopyFloat(source, destination, "_FurRootOffset", "_NiloFurRootOffset"); + CopyFloat(source, destination, "_FurCutoutLength", "_NiloFurCutoutLength"); + CopyFloat(source, destination, "_FurCull", "_NiloFurCull"); + CopyColor(source, destination, "_FurRimColor", "_NiloFurRimColor"); + CopyFloat(source, destination, "_FurRimFresnelPower", "_NiloFurRimFresnelPower"); + CopyFloat(source, destination, "_FurRimAntiLight", "_NiloFurRimAntiLight"); + + if (source.HasProperty("_FurAO")) + { + float furAO = source.GetFloat("_FurAO"); + SetFloatIfHasProperty(destination, "_NiloFurOcclusionShadowAO", furAO); + SetFloatIfHasProperty(destination, "_NiloFurColorDarkenAO", furAO); + } + + SetFloatClampedIfHasProperty(source, destination, "_FurLayerNum", "_NiloFurLayerNum", 1f, 2f); + } + + private static void PortLilToonEnvironmentReflectionProperties(Material source, Material destination) + { + float useEnvironmentReflection = + GetFloatOrDefault(source, "_UseReflection", 0f) * + GetFloatOrDefault(source, "_ApplyReflection", 0f); + // Keep the native NiloToon environment reflection group as data-only for lilToon conversion. + // The actual lilToon-compatible shading path is handled separately by Generic Reflection. + SetFloatIfHasProperty(destination, "_ReceiveEnvironmentReflection", 0f); + SetKeyword(destination, "_ENVIRONMENTREFLECTIONS", false); + + Color reflectionColor = GetColorOrDefault(source, "_ReflectionColor", Color.white); + Color cubeColor = GetColorOrDefault(source, "_ReflectionCubeColor", Color.white); + SetFloatIfHasProperty(destination, "_EnvironmentReflectionUsage", reflectionColor.a); + // lilToon uses _Reflectance as the dielectric Fresnel input, not as total environment brightness. + SetFloatIfHasProperty(destination, "_EnvironmentReflectionBrightness", 1f); + SetFloatIfHasProperty(destination, "_EnvironmentReflectionTintAlbedo", + GetFloatOrDefault(source, "_Metallic", 0f)); + SetColorIfHasProperty(destination, "_EnvironmentReflectionColor", + new Color( + reflectionColor.r * cubeColor.r, + reflectionColor.g * cubeColor.g, + reflectionColor.b * cubeColor.b, + 1f)); + + Texture reflectionColorTex = source.HasProperty("_ReflectionColorTex") + ? source.GetTexture("_ReflectionColorTex") + : null; + SetTextureIfHasProperty(destination, "_EnvironmentReflectionColorMaskMap", reflectionColorTex); + + float lilToonBlendMode = GetFloatOrDefault(source, "_ReflectionBlendMode", 1f); + bool useAdditiveBlend = Mathf.Approximately(lilToonBlendMode, 1f) || Mathf.Approximately(lilToonBlendMode, 2f); + SetFloatIfHasProperty(destination, "_EnvironmentReflectionApplyReplaceBlending", useAdditiveBlend ? 0f : 1f); + SetFloatIfHasProperty(destination, "_EnvironmentReflectionApplyAddBlending", useAdditiveBlend ? 1f : 0f); + + Texture reflectionCubemap = source.HasProperty("_ReflectionCubeTex") + ? source.GetTexture("_ReflectionCubeTex") + : null; + SetTextureIfHasProperty(destination, "_EnvironmentReflectionOverrideCubemap", reflectionCubemap); + + bool useOverrideCubemap = + useEnvironmentReflection > 0.5f && + GetFloatOrDefault(source, "_ReflectionCubeOverride", 0f) > 0.5f && + reflectionCubemap != null; + SetFloatIfHasProperty(destination, "_EnvironmentReflectionOverrideCubemapOn", useOverrideCubemap ? 1f : 0f); + SetKeyword(destination, "_ENVIRONMENTREFLECTIONS_OVERRIDE_CUBEMAP", false); + } + + private static void PortLilToonReflectionToGenericReflection(Material source, Material destination) + { + float useReflection = GetFloatOrDefault(source, "_UseReflection", 0f); + float applySpecular = GetFloatOrDefault(source, "_ApplySpecular", 1f); + float applyReflection = GetFloatOrDefault(source, "_ApplyReflection", 0f); + Texture reflectionCubemap = source.HasProperty("_ReflectionCubeTex") + ? source.GetTexture("_ReflectionCubeTex") + : null; + bool useGenericReflection = useReflection > 0.5f; + + SetFloatIfHasProperty(destination, "_UseGenericReflection", useGenericReflection ? 1f : 0f); + SetKeyword(destination, "_GENERIC_REFLECTION", useGenericReflection); + + SetTextureIfHasProperty(destination, "_GenericReflectionCubemap", reflectionCubemap); + CopyTextureWithScaleOffset(source, destination, "_SmoothnessTex", "_GenericReflectionSmoothnessMap"); + CopyTextureWithScaleOffset(source, destination, "_ReflectionColorTex", "_GenericReflectionColorMaskMap"); + CopyTextureWithScaleOffset(source, destination, "_MetallicGlossMap", "_GenericReflectionMetallicMap"); + + Color reflectionColor = GetColorOrDefault(source, "_ReflectionColor", Color.white); + SetColorIfHasProperty(destination, "_GenericReflectionColor", reflectionColor); + SetColorIfHasProperty(destination, "_GenericReflectionCubeColor", + GetColorOrDefault(source, "_ReflectionCubeColor", Color.black)); + SetFloatIfHasProperty(destination, "_GenericReflectionBlend", 1f); + SetFloatIfHasProperty(destination, "_GenericReflectionBlendMode", + GetFloatOrDefault(source, "_ReflectionBlendMode", 1f)); + SetFloatIfHasProperty(destination, "_GenericReflectionSmoothness", + GetFloatOrDefault(source, "_Smoothness", 1f)); + SetFloatIfHasProperty(destination, "_GenericReflectionGSAAStrength", + GetFloatOrDefault(source, "_GSAAStrength", 0f)); + SetFloatIfHasProperty(destination, "_GenericReflectionApplySpecular", applySpecular); + SetFloatIfHasProperty(destination, "_GenericReflectionApplySpecularFA", + GetFloatOrDefault(source, "_ApplySpecularFA", 1f)); + SetFloatIfHasProperty(destination, "_GenericReflectionSpecularToon", + GetFloatOrDefault(source, "_SpecularToon", 1f)); + SetFloatIfHasProperty(destination, "_GenericReflectionSpecularNormalStrength", + GetFloatOrDefault(source, "_SpecularNormalStrength", 1f)); + SetFloatIfHasProperty(destination, "_GenericReflectionSpecularBorder", + GetFloatOrDefault(source, "_SpecularBorder", 0.5f)); + SetFloatIfHasProperty(destination, "_GenericReflectionSpecularBlur", + GetFloatOrDefault(source, "_SpecularBlur", 0f)); + SetFloatIfHasProperty(destination, "_GenericReflectionApplyReflection", applyReflection); + SetFloatIfHasProperty(destination, "_GenericReflectionReflectance", + GetFloatOrDefault(source, "_Reflectance", 0.04f)); + SetFloatIfHasProperty(destination, "_GenericReflectionMetallic", + GetFloatOrDefault(source, "_Metallic", 0f)); + SetFloatIfHasProperty(destination, "_GenericReflectionCubeOverride", + GetFloatOrDefault(source, "_ReflectionCubeOverride", 0f)); + SetFloatIfHasProperty(destination, "_GenericReflectionCubeEnableLighting", + GetFloatOrDefault(source, "_ReflectionCubeEnableLighting", 1f)); + SetFloatIfHasProperty(destination, "_GenericReflectionApplyTransparency", + GetFloatOrDefault(source, "_ReflectionApplyTransparency", 1f)); + SetFloatIfHasProperty(destination, "_GenericReflectionNormalStrength", + GetFloatOrDefault(source, "_ReflectionNormalStrength", 1f)); } private static void Port_lilToon_properties_To_NiloToon(Material fromlilToonMat, Material toNiloToonMat) @@ -975,20 +1797,22 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------------------------------------------------------------------------- // Base toNiloToonMat.SetFloat("_EnableRendering", - fromlilToonMat.GetFloat("_Invisible") > 0.5 + GetFloatOrDefault(fromlilToonMat, "_Invisible") > 0.5 ? 0 : 1); // (lilToon: early return "init as 0 struct" in vertex shader, same as NiloToon) // (XV) _AsUnlit (lilToon: lerp main light color to white, lerp additional light color to black) + SetFloatIfHasProperty(toNiloToonMat, "_AsUnlit", 0f); // (Same)_Cutoff (lilToon: standard alpha clip threshold, same as NiloToon/Lit) // (?) _SubpassCutoff (NiloToon: similar to _CutOff, but only for "subpass", not sure what Subpass is) // (X) _FlipNormal (NiloToon: always perform flipNormal, there is no option in material) (lilToon: sFlipBackfaceNormal -> N = facing < (_FlipNormal-1.0) ? -N : N. Similar to NiloToon) // (?) _ShiftBackfaceUV (NiloToon: too specific, not sure if it is a good idea to add it) (lilToon: back face UV += (1,0) or not. lilToon's doc: Shift the UVs on the back by 1.0 in the X-axis direction. By turning this on and setting the Tiling's X to 0.5, and doubling the texture's resolution horizontally to place two textures side by side, you can create an expression where different textures are applied to the front and back.) toNiloToonMat.SetFloat("_BackFaceForceShadow", - fromlilToonMat.GetFloat( + GetFloatOrDefault(fromlilToonMat, "_BackfaceForceShadow")); // lilToon: float bfshadow = (fd.facing < 0.0) ? 1.0 - _BackfaceForceShadow : 1.0; toNiloToonMat.SetColor("_BackFaceBaseMapReplaceColor", - fromlilToonMat.GetColor( - "_BackfaceColor")); // lilToon: fd.col.rgb = (fd.facing < 0.0) ? lerp(fd.col.rgb, _BackfaceColor.rgb * fd.lightColor, _BackfaceColor.a) : fd.col.rgb; + GetColorOrDefault(fromlilToonMat, + "_BackfaceColor", + Color.clear)); // lilToon: fd.col.rgb = (fd.facing < 0.0) ? lerp(fd.col.rgb, _BackfaceColor.rgb * fd.lightColor, _BackfaceColor.a) : fd.col.rgb; // (X) _VertexLightStrength (NiloToon: this lil prop is for BRP only, ignored) (lilToon: for BRP only) // (XV) _LightMinLimit (lilToon: lightColor = clamp(lightColor, _LightMinLimit, _LightMaxLimit);) // (XV) _LightMaxLimit (lilToon: lightColor = clamp(lightColor, _LightMinLimit, _LightMaxLimit);) @@ -997,25 +1821,42 @@ namespace NiloToon.NiloToonURP // (X) _AlphaBoostFA (NiloToon: this lilToon prop is for forward add (FA) pass, ignored)(lilToon: fd.col.rgb *= saturate(fd.col.a * _AlphaBoostFA);) // (XV) _lilDirectionalLightStrength (lilToon: lightColor *= _lilDirectionalLightStrength) // (XV) _LightDirectionOverride (lilToon: add a object->world space light vector to light dir, re-normalize? (not sure)) - // (?) _AAStrength (lilToon: for value with sharp change, apply fwidth AA by -> (value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * aascale)) + // (Same via lilToon shadow mode) _lilAAStrength // (?) _UseDither (lilToon: dither fade0out per material) // (?) _DitherTex (lilToon: dither fadeout per material) // (?) _DitherMaxValue (lilToon: dither fadeout per material) //---------------------------------------------------------------------------------------------------------------------- // Main - toNiloToonMat.SetColor("_BaseColor", fromlilToonMat.GetColor("_Color")); - toNiloToonMat.SetTexture("_BaseMap", fromlilToonMat.GetTexture("_MainTex")); - toNiloToonMat.SetVector("_BaseMap_ST", fromlilToonMat.GetVector("_MainTex_ST")); // auto uniform by Unity + toNiloToonMat.SetColor("_BaseColor", GetColorOrDefault(fromlilToonMat, "_Color", Color.white)); + toNiloToonMat.SetTexture("_BaseMap", GetTextureOrNull(fromlilToonMat, "_MainTex")); + toNiloToonMat.SetVector("_BaseMap_ST", GetTextureScaleOffsetOrDefault(fromlilToonMat, "_MainTex")); // auto uniform by Unity // (!) _MainTex_ScrollRotate // TODO: apply the BaseMap's uv, not UV0! - // (?) _MainTexHSVG (lilToon: hsv = float3(hsv.x+hsvg.x,saturate(hsv.y*hsvg.y),saturate(hsv.z*hsvg.z));) + if (HasShaderProperty(fromlilToonMat, "_MainTexHSVG", ShaderPropertyType.Vector)) + { + Vector4 mainTexHSVG = GetVectorOrDefault(fromlilToonMat, "_MainTexHSVG", new Vector4(0f, 1f, 1f, 1f)); + toNiloToonMat.SetFloat("_BaseMapHue", mainTexHSVG.x); + toNiloToonMat.SetFloat("_BaseMapSaturation", mainTexHSVG.y); + toNiloToonMat.SetFloat("_BaseMapValue", mainTexHSVG.z); + toNiloToonMat.SetFloat("_BaseMapGamma", mainTexHSVG.w); + } // (X) _MainGradationStrength (NiloToon: too specific, ignored)(lilToon: rgb per channel color 1D remap) // (X) _MainGradationTex (NiloToon: too specific, ignored)(lilToon: rgb per channel color 1D remap) - // (?) _MainColorAdjustMask (lilToon: mask of _MainTexHSVG) + Texture baseMapHSVGMaskTex = GetTextureOrNull(fromlilToonMat, "_MainColorAdjustMask"); + toNiloToonMat.SetFloat("_UseBaseMapHSVGMask", baseMapHSVGMaskTex ? 1 : 0); + toNiloToonMat.SetTexture("_BaseMapHSVGMaskTex", baseMapHSVGMaskTex); + if (baseMapHSVGMaskTex) + { + toNiloToonMat.EnableKeyword("_BASEMAP_HSVG_MASK"); + } + else + { + toNiloToonMat.DisableKeyword("_BASEMAP_HSVG_MASK"); + } //---------------------------------------------------------------------------------------------------------------------- // Main2nd (port to NiloToon's BaseMapStackingLayer1) - float _UseMain2ndTex = fromlilToonMat.GetFloat("_UseMain2ndTex"); + float _UseMain2ndTex = GetFloatOrDefault(fromlilToonMat, "_UseMain2ndTex"); toNiloToonMat.SetFloat("_BaseMapStackingLayer1Enable", _UseMain2ndTex); if (_UseMain2ndTex > 0.5) { @@ -1026,17 +1867,17 @@ namespace NiloToon.NiloToonURP toNiloToonMat.DisableKeyword("_BASEMAP_STACKING_LAYER1"); } - toNiloToonMat.SetColor("_BaseMapStackingLayer1TintColor", fromlilToonMat.GetColor("_Color2nd")); - toNiloToonMat.SetTexture("_BaseMapStackingLayer1Tex", fromlilToonMat.GetTexture("_Main2ndTex")); + toNiloToonMat.SetColor("_BaseMapStackingLayer1TintColor", GetColorOrDefault(fromlilToonMat, "_Color2nd", Color.white)); + toNiloToonMat.SetTexture("_BaseMapStackingLayer1Tex", GetTextureOrNull(fromlilToonMat, "_Main2ndTex")); toNiloToonMat.SetVector("_BaseMapStackingLayer1TexUVScaleOffset", - fromlilToonMat.GetVector("_Main2ndTex_ST")); + GetTextureScaleOffsetOrDefault(fromlilToonMat, "_Main2ndTex")); // liltoon / nilotoon are both in degree toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVRotatedAngle", - fromlilToonMat.GetFloat("_Main2ndTexAngle") * 180f / Mathf.PI); + GetFloatOrDefault(fromlilToonMat, "_Main2ndTexAngle") * 180f / Mathf.PI); { - Vector4 _Main2ndTex_ScrollRotate = fromlilToonMat.GetVector("_Main2ndTex_ScrollRotate"); + Vector4 _Main2ndTex_ScrollRotate = GetVectorOrDefault(fromlilToonMat, "_Main2ndTex_ScrollRotate", Vector4.zero); toNiloToonMat.SetVector("_BaseMapStackingLayer1TexUVAnimSpeed", new Vector4(_Main2ndTex_ScrollRotate.x, _Main2ndTex_ScrollRotate.y, 0, 0)); @@ -1049,8 +1890,8 @@ namespace NiloToon.NiloToonURP } // liltoon's _Main2ndTex_UVMode = UV0|UV1|UV2|UV3|MatCap - toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVIndex", fromlilToonMat.GetFloat("_Main2ndTex_UVMode")); - toNiloToonMat.SetFloat("_BaseMapStackingLayer1ApplytoFaces", fromlilToonMat.GetFloat("_Main2ndTex_Cull")); + toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVIndex", GetFloatOrDefault(fromlilToonMat, "_Main2ndTex_UVMode")); + toNiloToonMat.SetFloat("_BaseMapStackingLayer1ApplytoFaces", GetFloatOrDefault(fromlilToonMat, "_Main2ndTex_Cull")); // (X) _Main2ndTexDecalAnimation // (X) _Main2ndTexDecalSubParam // (X) _Main2ndTexIsDecal @@ -1060,7 +1901,7 @@ namespace NiloToon.NiloToonURP // (X) _Main2ndTexShouldFlipMirror // (X) _Main2ndTexShouldFlipCopy // (X) _Main2ndTexIsMSDF - toNiloToonMat.SetTexture("_BaseMapStackingLayer1MaskTex", fromlilToonMat.GetTexture("_Main2ndBlendMask")); + toNiloToonMat.SetTexture("_BaseMapStackingLayer1MaskTex", GetTextureOrNull(fromlilToonMat, "_Main2ndBlendMask")); { // liltoon's blend mode: // 0: Normal @@ -1075,7 +1916,7 @@ namespace NiloToon.NiloToonURP // 3: Screen (same as liltoon) // 4: Multiply (same as liltoon) // 5: None - float _Main2ndTexBlendMode = fromlilToonMat.GetFloat("_Main2ndTexBlendMode"); + float _Main2ndTexBlendMode = GetFloatOrDefault(fromlilToonMat, "_Main2ndTexBlendMode"); float NiloToonBlendMode = 0; // default 0 (Normal RGBA) switch (_Main2ndTexBlendMode) { @@ -1108,7 +1949,7 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------------------------------------------------------------------------- // Main3rd (port to NiloToon's BaseMapStackingLayer2) - float _UseMain3rdTex = fromlilToonMat.GetFloat("_UseMain3rdTex"); + float _UseMain3rdTex = GetFloatOrDefault(fromlilToonMat, "_UseMain3rdTex"); toNiloToonMat.SetFloat("_BaseMapStackingLayer2Enable", _UseMain3rdTex); if (_UseMain3rdTex == 1) { @@ -1119,17 +1960,17 @@ namespace NiloToon.NiloToonURP toNiloToonMat.DisableKeyword("_BASEMAP_STACKING_LAYER2"); } - toNiloToonMat.SetColor("_BaseMapStackingLayer2TintColor", fromlilToonMat.GetColor("_Color3rd")); - toNiloToonMat.SetTexture("_BaseMapStackingLayer2Tex", fromlilToonMat.GetTexture("_Main3rdTex")); + toNiloToonMat.SetColor("_BaseMapStackingLayer2TintColor", GetColorOrDefault(fromlilToonMat, "_Color3rd", Color.white)); + toNiloToonMat.SetTexture("_BaseMapStackingLayer2Tex", GetTextureOrNull(fromlilToonMat, "_Main3rdTex")); toNiloToonMat.SetVector("_BaseMapStackingLayer2TexUVScaleOffset", - fromlilToonMat.GetVector("_Main3rdTex_ST")); + GetTextureScaleOffsetOrDefault(fromlilToonMat, "_Main3rdTex")); // liltoon / nilotoon are both in degree toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVRotatedAngle", - fromlilToonMat.GetFloat("_Main3rdTexAngle")); + GetFloatOrDefault(fromlilToonMat, "_Main3rdTexAngle")); { - Vector4 _Main3rdTex_ScrollRotate = fromlilToonMat.GetVector("_Main3rdTex_ScrollRotate"); + Vector4 _Main3rdTex_ScrollRotate = GetVectorOrDefault(fromlilToonMat, "_Main3rdTex_ScrollRotate", Vector4.zero); toNiloToonMat.SetVector("_BaseMapStackingLayer2TexUVAnimSpeed", new Vector4(_Main3rdTex_ScrollRotate.x, _Main3rdTex_ScrollRotate.y, 0, 0)); @@ -1142,8 +1983,8 @@ namespace NiloToon.NiloToonURP } // liltoon's _Main3rdTex_UVMode = UV0|UV1|UV2|UV3|MatCap - toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVIndex", fromlilToonMat.GetFloat("_Main3rdTex_UVMode")); - toNiloToonMat.SetFloat("_BaseMapStackingLayer2ApplytoFaces", fromlilToonMat.GetFloat("_Main3rdTex_Cull")); + toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVIndex", GetFloatOrDefault(fromlilToonMat, "_Main3rdTex_UVMode")); + toNiloToonMat.SetFloat("_BaseMapStackingLayer2ApplytoFaces", GetFloatOrDefault(fromlilToonMat, "_Main3rdTex_Cull")); // (X) _Main3rdTexDecalAnimation // (X) _Main3rdTexDecalSubParam // (X) _Main3rdTexIsDecal @@ -1153,7 +1994,7 @@ namespace NiloToon.NiloToonURP // (X) _Main3rdTexShouldFlipMirror // (X) _Main3rdTexShouldFlipCopy // (X) _Main3rdTexIsMSDF - toNiloToonMat.SetTexture("_BaseMapStackingLayer2MaskTex", fromlilToonMat.GetTexture("_Main3rdBlendMask")); + toNiloToonMat.SetTexture("_BaseMapStackingLayer2MaskTex", GetTextureOrNull(fromlilToonMat, "_Main3rdBlendMask")); { // liltoon's blend mode: // 0: Normal @@ -1168,7 +2009,7 @@ namespace NiloToon.NiloToonURP // 3: Screen (same as liltoon) // 4: Multiply (same as liltoon) // 5: None - float _Main3rdTexBlendMode = fromlilToonMat.GetFloat("_Main3rdTexBlendMode"); + float _Main3rdTexBlendMode = GetFloatOrDefault(fromlilToonMat, "_Main3rdTexBlendMode"); float NiloToonBlendMode = 0; // default 0 (Normal RGBA) switch (_Main3rdTexBlendMode) { @@ -1208,7 +2049,7 @@ namespace NiloToon.NiloToonURP // 2 = Multiply // 3 = Add // 4 = Subtract - int _AlphaMaskMode = (int)fromlilToonMat.GetFloat("_AlphaMaskMode"); + int _AlphaMaskMode = (int)GetFloatOrDefault(fromlilToonMat, "_AlphaMaskMode"); if (_AlphaMaskMode != 0) { toNiloToonMat.SetFloat("_UseAlphaOverrideTex", 1); @@ -1228,15 +2069,15 @@ namespace NiloToon.NiloToonURP toNiloToonMat.DisableKeyword("_ALPHAOVERRIDEMAP"); } - toNiloToonMat.SetTexture("_AlphaOverrideTex", fromlilToonMat.GetTexture("_AlphaMask")); + toNiloToonMat.SetTexture("_AlphaOverrideTex", GetTextureOrNull(fromlilToonMat, "_AlphaMask")); // liltoon GUI's invert toggle is not a property, it translate to a MAD (* scale + value) - toNiloToonMat.SetFloat("_AlphaOverrideTexValueScale", fromlilToonMat.GetFloat("_AlphaMaskScale")); - toNiloToonMat.SetFloat("_AlphaOverrideTexValueOffset", fromlilToonMat.GetFloat("_AlphaMaskValue")); + toNiloToonMat.SetFloat("_AlphaOverrideTexValueScale", GetFloatOrDefault(fromlilToonMat, "_AlphaMaskScale", 1f)); + toNiloToonMat.SetFloat("_AlphaOverrideTexValueOffset", GetFloatOrDefault(fromlilToonMat, "_AlphaMaskValue")); //---------------------------------------------------------------------------------------------------------------------- // NormalMap - int _UseBumpMap = (int)fromlilToonMat.GetFloat("_UseBumpMap"); + int _UseBumpMap = (int)GetFloatOrDefault(fromlilToonMat, "_UseBumpMap"); if (_UseBumpMap == 1) { toNiloToonMat.SetFloat("_UseNormalMap", 1); @@ -1265,39 +2106,202 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------------------------------------------------------------------------- // Shadow - toNiloToonMat.SetFloat("_EnableShadowColor", fromlilToonMat.GetFloat("_UseShadow")); + toNiloToonMat.SetFloat("_EnableShadowColor", GetFloatOrDefault(fromlilToonMat, "_UseShadow")); + SetFloatIfHasProperty(toNiloToonMat, "_ShadowColorMode", 1f); + SetKeyword(toNiloToonMat, "_SHADOW_MODE_LILTOON", true); - Texture2D occlusionMap = fromlilToonMat.GetTexture("_ShadowBorderMask") as Texture2D; + PortLilToonShadowModeProperties(fromlilToonMat, toNiloToonMat); + + float shadowNormalStrength = GetFloatOrDefault(fromlilToonMat, "_ShadowNormalStrength", 1f); + toNiloToonMat.SetFloat("_MainLightSkinDiffuseNormalMapStrength", shadowNormalStrength); + toNiloToonMat.SetFloat("_MainLightNonSkinDiffuseNormalMapStrength", shadowNormalStrength); + PortLilToonShadowAORemap(fromlilToonMat, toNiloToonMat); + + Texture2D occlusionMap = GetTextureOrNull(fromlilToonMat, "_ShadowBorderMask") as Texture2D; toNiloToonMat.SetTexture("_OcclusionMap", occlusionMap); - if (occlusionMap) - { - toNiloToonMat.SetFloat("_UseOcclusion", 1); - toNiloToonMat.EnableKeyword("_OCCLUSIONMAP"); - } - else - { - toNiloToonMat.SetFloat("_UseOcclusion", 0); - toNiloToonMat.DisableKeyword("_OCCLUSIONMAP"); - } + toNiloToonMat.SetFloat("_UseOcclusion", 0); + toNiloToonMat.DisableKeyword("_OCCLUSIONMAP"); + + // _ShadowMainStrength -> _SelfShadowAlbedoMulStrength (both Range(0,1), copied 1:1). + // Note: lite variants (ltsl_*) don't declare _ShadowMainStrength; CopyFloat silently no-ops via HasProperty. + CopyFloat(fromlilToonMat, toNiloToonMat, "_ShadowMainStrength", "_SelfShadowAlbedoMulStrength"); //---------------------------------------------------------------------------------------------------------------------- // Rim Shade //---------------------------------------------------------------------------------------------------------------------- // Reflection - // TODO + PortLilToonEnvironmentReflectionProperties(fromlilToonMat, toNiloToonMat); + PortLilToonReflectionToGenericReflection(fromlilToonMat, toNiloToonMat); + + bool genericReflectionOwnsLilToonSpecular = + GetFloatOrDefault(toNiloToonMat, "_UseGenericReflection", 0f) > 0.5f; + float useLilToonDirectSpecular = + genericReflectionOwnsLilToonSpecular + ? 0f + : GetFloatOrDefault(fromlilToonMat, "_UseReflection") * GetFloatOrDefault(fromlilToonMat, "_ApplySpecular"); + toNiloToonMat.SetFloat("_UseSpecular", useLilToonDirectSpecular); + if (useLilToonDirectSpecular > 0.5f) + { + toNiloToonMat.EnableKeyword("_SPECULARHIGHLIGHTS"); + } + else + { + toNiloToonMat.DisableKeyword("_SPECULARHIGHLIGHTS"); + } + + toNiloToonMat.SetFloat("_UseGGXDirectSpecular", GetFloatOrDefault(fromlilToonMat, "_SpecularToon", 1f) > 0.5f ? 0 : 1); + toNiloToonMat.SetFloat("_Smoothness", GetFloatOrDefault(fromlilToonMat, "_Smoothness", toNiloToonMat.GetFloat("_Smoothness"))); + + Texture2D smoothnessMap = GetTextureOrNull(fromlilToonMat, "_SmoothnessTex") as Texture2D; + toNiloToonMat.SetTexture("_SmoothnessMap", smoothnessMap); + if (smoothnessMap) + { + toNiloToonMat.SetFloat("_UseSmoothnessMap", 1); + toNiloToonMat.EnableKeyword("_SMOOTHNESSMAP"); + toNiloToonMat.SetFloat("_SmoothnessMapInputIsRoughnessMap", 0); + toNiloToonMat.SetVector("_SmoothnessMapChannelMask", new Vector4(1, 0, 0, 0)); + } + else + { + toNiloToonMat.SetFloat("_UseSmoothnessMap", 0); + toNiloToonMat.DisableKeyword("_SMOOTHNESSMAP"); + } + + Color reflectionColor = GetColorOrDefault(fromlilToonMat, "_ReflectionColor", Color.white); + toNiloToonMat.SetFloat("_SpecularIntensity", + GetFloatOrDefault(fromlilToonMat, "_Reflectance") * reflectionColor.a); + toNiloToonMat.SetColor("_SpecularColor", + new Color(reflectionColor.r, reflectionColor.g, reflectionColor.b, 1)); + toNiloToonMat.SetFloat("_MultiplyBaseColorToSpecularColor", GetFloatOrDefault(fromlilToonMat, "_Metallic")); + + Texture2D reflectionColorTintMap = GetTextureOrNull(fromlilToonMat, "_ReflectionColorTex") as Texture2D; + toNiloToonMat.SetTexture("_SpecularColorTintMap", reflectionColorTintMap); + if (reflectionColorTintMap && !genericReflectionOwnsLilToonSpecular) + { + toNiloToonMat.SetFloat("_UseSpecularColorTintMap", 1); + toNiloToonMat.EnableKeyword("_SPECULARHIGHLIGHTS_TEX_TINT"); + toNiloToonMat.SetFloat("_SpecularColorTintMapUsage", 1); + + string reflectionColorTintMapPath = AssetDatabase.GetAssetPath(reflectionColorTintMap); + TextureImporter reflectionColorTintMapImporter = + string.IsNullOrEmpty(reflectionColorTintMapPath) + ? null + : AssetImporter.GetAtPath(reflectionColorTintMapPath) as TextureImporter; + bool reflectionColorTintMapHasAlpha = reflectionColorTintMapImporter != null && + reflectionColorTintMapImporter.DoesSourceTextureHaveAlpha(); + if (reflectionColorTintMapHasAlpha) + { + toNiloToonMat.SetTexture("_SpecularMap", reflectionColorTintMap); + toNiloToonMat.SetVector("_SpecularMapChannelMask", new Vector4(0, 0, 0, 1)); + } + } + else + { + toNiloToonMat.SetFloat("_UseSpecularColorTintMap", 0); + toNiloToonMat.DisableKeyword("_SPECULARHIGHLIGHTS_TEX_TINT"); + } //---------------------------------------------------------------------------------------------------------------------- // MatCap - // TODO (apply to basemap stacking layer3, base on blend mode) + DisableNativeNiloMatCapGroups(toNiloToonMat); + PortLilToonMatCapLayerToGeneric( + fromlilToonMat, + toNiloToonMat, + "_UseMatCap", + "_UseGenericMatCap1", + "_GENERIC_MATCAP1", + "_MatCapColor", + "_GenericMatCap1Color", + "_MatCapTex", + "_GenericMatCap1Map", + "_MatCapMainStrength", + "_GenericMatCap1MainStrength", + "_MatCapBlendUV1", + "_GenericMatCap1BlendUV1", + "_MatCapZRotCancel", + "_GenericMatCap1ZRotCancel", + "_MatCapPerspective", + "_GenericMatCap1Perspective", + "_MatCapVRParallaxStrength", + "_GenericMatCap1VRParallaxStrength", + "_MatCapBlend", + "_GenericMatCap1Blend", + "_MatCapBlendMask", + "_GenericMatCap1Mask", + "_MatCapEnableLighting", + "_GenericMatCap1EnableLighting", + "_MatCapShadowMask", + "_GenericMatCap1ShadowMask", + "_MatCapBackfaceMask", + "_GenericMatCap1BackfaceMask", + "_MatCapLod", + "_GenericMatCap1Lod", + "_MatCapBlendMode", + "_GenericMatCap1BlendMode", + "_MatCapApplyTransparency", + "_GenericMatCap1ApplyTransparency", + "_MatCapNormalStrength", + "_GenericMatCap1NormalStrength", + "_MatCapCustomNormal", + "_UseGenericMatCap1CustomNormal", + "_GENERIC_MATCAP1_CUSTOM_NORMAL", + "_MatCapBumpMap", + "_GenericMatCap1BumpMap", + "_MatCapBumpScale", + "_GenericMatCap1BumpScale"); //---------------------------------------------------------------------------------------------------------------------- // MatCap 2nd - // TODO (apply to basemap stacking layer4, apply base on blend mode) + PortLilToonMatCapLayerToGeneric( + fromlilToonMat, + toNiloToonMat, + "_UseMatCap2nd", + "_UseGenericMatCap2", + "_GENERIC_MATCAP2", + "_MatCap2ndColor", + "_GenericMatCap2Color", + "_MatCap2ndTex", + "_GenericMatCap2Map", + "_MatCap2ndMainStrength", + "_GenericMatCap2MainStrength", + "_MatCap2ndBlendUV1", + "_GenericMatCap2BlendUV1", + "_MatCap2ndZRotCancel", + "_GenericMatCap2ZRotCancel", + "_MatCap2ndPerspective", + "_GenericMatCap2Perspective", + "_MatCap2ndVRParallaxStrength", + "_GenericMatCap2VRParallaxStrength", + "_MatCap2ndBlend", + "_GenericMatCap2Blend", + "_MatCap2ndBlendMask", + "_GenericMatCap2Mask", + "_MatCap2ndEnableLighting", + "_GenericMatCap2EnableLighting", + "_MatCap2ndShadowMask", + "_GenericMatCap2ShadowMask", + "_MatCap2ndBackfaceMask", + "_GenericMatCap2BackfaceMask", + "_MatCap2ndLod", + "_GenericMatCap2Lod", + "_MatCap2ndBlendMode", + "_GenericMatCap2BlendMode", + "_MatCap2ndApplyTransparency", + "_GenericMatCap2ApplyTransparency", + "_MatCap2ndNormalStrength", + "_GenericMatCap2NormalStrength", + "_MatCap2ndCustomNormal", + "_UseGenericMatCap2CustomNormal", + "_GENERIC_MATCAP2_CUSTOM_NORMAL", + "_MatCap2ndBumpMap", + "_GenericMatCap2BumpMap", + "_MatCap2ndBumpScale", + "_GenericMatCap2BumpScale"); //---------------------------------------------------------------------------------------------------------------------- // Rim - // TODO (we should write a ALU rim in NiloToon, similar to lilToon) + PortLilToonRimToGenericRimLight3D(fromlilToonMat, toNiloToonMat); //---------------------------------------------------------------------------------------------------------------------- // Glitter @@ -1305,7 +2309,7 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------------------------------------------------------------------------- // Emission - int _UseEmission = (int)fromlilToonMat.GetFloat("_UseEmission"); + int _UseEmission = (int)GetFloatOrDefault(fromlilToonMat, "_UseEmission"); if (_UseEmission == 1) { toNiloToonMat.SetFloat("_UseEmission", 1); @@ -1319,14 +2323,14 @@ namespace NiloToon.NiloToonURP // (Same)_EmissionColor toNiloToonMat.SetFloat("_EmissionIntensity", - fromlilToonMat.GetColor("_EmissionColor").a); // lilToon's _EmissionColor.a is the intensity + GetColorOrDefault(fromlilToonMat, "_EmissionColor", Color.clear).a); // lilToon's _EmissionColor.a is the intensity // (Same)_EmissionMap toNiloToonMat.SetVector("_EmissionMapUVScrollSpeed", - fromlilToonMat.GetVector("_EmissionMap_ScrollRotate")); + GetVectorOrDefault(fromlilToonMat, "_EmissionMap_ScrollRotate", Vector4.zero)); // (X) _EmissionMap_UVMode toNiloToonMat.SetFloat("_MultiplyBaseColorToEmissionColor", - fromlilToonMat.GetFloat("_EmissionMainStrength")); + GetFloatOrDefault(fromlilToonMat, "_EmissionMainStrength")); //_EmissionBlend //_EmissionBlendMask // (X) _EmissionBlendMask_ScrollRot @@ -1344,7 +2348,7 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------------------------------------------------------------------------- // Parallax - int _UseParallax = (int)fromlilToonMat.GetFloat("_UseParallax"); + int _UseParallax = (int)GetFloatOrDefault(fromlilToonMat, "_UseParallax"); if (_UseParallax == 1) { toNiloToonMat.SetFloat("_ParallaxMapEnable", 1); @@ -1384,12 +2388,12 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------------------------------------------------------------------------- // Outline - toNiloToonMat.SetColor("_OutlineTintColor", fromlilToonMat.GetColor("_OutlineColor")); + toNiloToonMat.SetColor("_OutlineTintColor", GetColorOrDefault(fromlilToonMat, "_OutlineColor", Color.white)); // _OutlineWidth (same, no need to convert) // make 2 outline system's width matching - float _OutlineWidth = fromlilToonMat.GetFloat("_OutlineWidth"); + float _OutlineWidth = GetFloatOrDefault(fromlilToonMat, "_OutlineWidth"); const float niloToonWidthRelativeTolilToon = 4; toNiloToonMat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeTolilToon); @@ -1398,7 +2402,7 @@ namespace NiloToon.NiloToonURP float finalWidth = Mathf.Min(maxFinalWidth, _OutlineWidth * niloToonWidthRelativeTolilToon); toNiloToonMat.SetFloat("_OutlineWidth", finalWidth / niloToonWidthRelativeTolilToon); - Texture2D _OutlineWidthMask = fromlilToonMat.GetTexture("_OutlineWidthMask") as Texture2D; + Texture2D _OutlineWidthMask = GetTextureOrNull(fromlilToonMat, "_OutlineWidthMask") as Texture2D; if (_OutlineWidthMask) { toNiloToonMat.SetFloat("_UseOutlineWidthTex", 1); @@ -1413,7 +2417,7 @@ namespace NiloToon.NiloToonURP toNiloToonMat.SetVector("_OutlineWidthTexChannelMask", new Vector4(0, 1, 0, 0)); } - float _OutlineVertexR2Width = fromlilToonMat.GetFloat("_OutlineVertexR2Width"); + float _OutlineVertexR2Width = GetFloatOrDefault(fromlilToonMat, "_OutlineVertexR2Width"); if (_OutlineVertexR2Width == 0) { // no vertex color used @@ -1435,7 +2439,7 @@ namespace NiloToon.NiloToonURP toNiloToonMat.SetVector("_OutlineWidthMaskFromVertexColor", new Vector4(0, 0, 0, 1)); } - toNiloToonMat.SetFloat("_OutlineBaseZOffset", fromlilToonMat.GetFloat("_OutlineZBias")); + toNiloToonMat.SetFloat("_OutlineBaseZOffset", GetFloatOrDefault(fromlilToonMat, "_OutlineZBias")); //---------------------------------------------------------------------------------------------------------------------- // Tessellation @@ -1452,11 +2456,16 @@ namespace NiloToon.NiloToonURP //---------------------------------------------------------------------------------------------------------------------- // Outline Advanced + PortLilToonFurProperties(fromlilToonMat, toNiloToonMat); } static void SetMaterialAsIsSkin(Material m) { m.SetFloat(IsSkin, 1); + if (m.HasProperty(DepthTexRimLight3DRimMaskEnable)) + { + m.SetFloat(DepthTexRimLight3DRimMaskEnable, 1); + } // no keyword on/off is needed for _IsSkin // ... @@ -1485,11 +2494,14 @@ namespace NiloToon.NiloToonURP public static void SetMaterialNiloToonSurfaceTypeAndProperties(Material m, NiloToonSurfaceTypePreset niloToonSurfaceTypePreset) { + int? clampedRenderQueue = null; + // fix render queue when it is out of expected range void ClampRenderQueueMinMax(Material m, int minRenderQueue, int maxRenderQueue) { if (m.renderQueue < minRenderQueue) m.renderQueue = minRenderQueue; if (m.renderQueue > maxRenderQueue) m.renderQueue = maxRenderQueue; + clampedRenderQueue = m.renderQueue; } void ClampRenderQueueToGroup(Material m, RenderQueueGroup renderQueueGroup) @@ -1514,15 +2526,14 @@ namespace NiloToon.NiloToonURP switch (renderQueueGroup) { case RenderQueueGroup.Opaque: - ClampRenderQueueMinMax(m, 2000, 2450 - 1); + // Preserve user-authored opaque/cutout ordering (e.g. 1999/2000 or 2450/2452) while keeping queues in Unity's opaque range. + ClampRenderQueueMinMax(m, 0, (int)RenderQueue.GeometryLast); break; case RenderQueueGroup.Cutout: - ClampRenderQueueMinMax(m, 2450, 2500 - 1); + ClampRenderQueueMinMax(m, 0, (int)RenderQueue.GeometryLast); break; - // 2500 is SkyBox - case RenderQueueGroup.Transparent: ClampRenderQueueMinMax(m, 2501, 4000 - 1); break; @@ -1720,38 +2731,13 @@ namespace NiloToon.NiloToonURP default: throw new NotImplementedException("Contact NiloToon's developer to support a new SurfaceType."); } - } - static bool TextureHasAlpha(Texture2D texture) - { - // Blit texture to a new RT to avoid non-Readable texture problem - RenderTexture tempRT = RenderTexture.GetTemporary(texture.width, texture.height); - Graphics.Blit(texture, tempRT); - RenderTexture RTactiveCache = RenderTexture.active; - RenderTexture.active = tempRT; - - // apply RT to our new Texture2D, so we can read it's per pixel alpha - Texture2D readableTexture = new Texture2D(texture.width, texture.height); - readableTexture.ReadPixels(new Rect(0, 0, tempRT.width, tempRT.height), 0, 0); - readableTexture.Apply(); - - RenderTexture.active = RTactiveCache; - RenderTexture.ReleaseTemporary(tempRT); - - Color[] pixels = readableTexture.GetPixels(); - - // this loop maybe slow depending on Texture size - foreach (Color pixel in pixels) + if (clampedRenderQueue.HasValue) { - if (pixel.a < 1f) - { - return true; - } + m.renderQueue = clampedRenderQueue.Value; } - - return false; } - + /// /// Breaks the variant link of a material /// @@ -1766,6 +2752,34 @@ namespace NiloToon.NiloToonURP #endif } + static bool IsMaterialVariant(Material mat) + { + if (mat == null) + return false; + +#if UNITY_2022_1_OR_NEWER + return mat.isVariant; +#else + return false; +#endif + } + + static bool HasUsableShader(Material mat) + { + return mat != null && mat.shader != null; + } + + static bool ShouldUpgradeMaterialNonInteractively(Material material, HashSet shaderNamesToIgnore) + { + if (!HasUsableShader(material)) + return false; + + if (IsMaterialVariant(material)) + return false; + + return !shaderNamesToIgnore.Contains(material.shader.name); + } + //////////////////////////////////////////////////////////////////////////////////////////////////////// // copy from UniversalRenderPipelineMaterialUpgrader.cs //////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1858,4 +2872,4 @@ namespace NiloToon.NiloToonURP } #endif } -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Editor/NiloToonEditorPerCharacterRenderControllerCustomEditor.cs b/Assets/NiloToonURP/Editor/NiloToonEditorPerCharacterRenderControllerCustomEditor.cs index 8e6e51d2e..e51ac5273 100644 --- a/Assets/NiloToonURP/Editor/NiloToonEditorPerCharacterRenderControllerCustomEditor.cs +++ b/Assets/NiloToonURP/Editor/NiloToonEditorPerCharacterRenderControllerCustomEditor.cs @@ -168,6 +168,14 @@ namespace NiloToon.NiloToonURP } public static void AutoSetupCharacterGameObject(GameObject gameobject) + { + AutoSetupCharacterGameObject(gameobject, shouldPromptMaterialEditConfirmation: true); + } + + public static void AutoSetupCharacterGameObject( + GameObject gameobject, + bool shouldPromptMaterialEditConfirmation, + bool shouldEditMaterialWhenConfirmationSkipped = true) { var charScript = gameobject.GetComponent(); if (!charScript) @@ -175,9 +183,20 @@ namespace NiloToon.NiloToonURP charScript = gameobject.AddComponent(); } - AutoSetupCharacterGameObject(charScript); + AutoSetupCharacterGameObject( + charScript, + shouldPromptMaterialEditConfirmation, + shouldEditMaterialWhenConfirmationSkipped); } public static void AutoSetupCharacterGameObject(NiloToonPerCharacterRenderController perCharScript) + { + AutoSetupCharacterGameObject(perCharScript, shouldPromptMaterialEditConfirmation: true); + } + + public static void AutoSetupCharacterGameObject( + NiloToonPerCharacterRenderController perCharScript, + bool shouldPromptMaterialEditConfirmation, + bool shouldEditMaterialWhenConfirmationSkipped = true) { if (!perCharScript) { @@ -188,14 +207,17 @@ namespace NiloToon.NiloToonURP } perCharScript.RefillAllRenderers(); - bool shouldEditMaterial = EditorUtility.DisplayDialog( - $"Auto setup character - {perCharScript.gameObject.name}", - "Set up NiloToon's script on this character completed.\n\n" + - "Do you want to convert the materials to NiloToon also?\n" + - "(convert from lilToon/MToon/UniUnlit/URP Lit/URP Unlit to NiloToon_Character)", - "Yes, convert the materials to NiloToon.", - "No, DO NOT edit any materials." - ); + bool shouldEditMaterial = ResolveShouldEditMaterialDecision( + shouldPromptMaterialEditConfirmation, + shouldEditMaterialWhenConfirmationSkipped, + () => EditorUtility.DisplayDialog( + $"Auto setup character - {perCharScript.gameObject.name}", + "Set up NiloToon's script on this character completed.\n\n" + + "Do you want to convert the materials to NiloToon also?\n" + + "(convert from lilToon/MToon/UniUnlit/URP Lit/URP Unlit to NiloToon_Character)", + "Yes, convert the materials to NiloToon.", + "No, DO NOT edit any materials." + )); if (shouldEditMaterial) { @@ -255,6 +277,19 @@ namespace NiloToon.NiloToonURP //Debug.Log($"NiloToon: Auto setup {perCharScript.gameObject.name} completed."); } + + static bool ResolveShouldEditMaterialDecision( + bool shouldPromptMaterialEditConfirmation, + bool shouldEditMaterialWhenConfirmationSkipped, + Func showConfirmationDialog) + { + if (!shouldPromptMaterialEditConfirmation) + { + return shouldEditMaterialWhenConfirmationSkipped; + } + + return showConfirmationDialog(); + } static void DiscardAndRefillAllRenderersList(NiloToonPerCharacterRenderController t) { @@ -414,4 +449,3 @@ namespace NiloToon.NiloToonURP } } - diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ExcludeFromBuild.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ExcludeFromBuild.cs index 0071e61d0..8a6741c08 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ExcludeFromBuild.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ExcludeFromBuild.cs @@ -1,4 +1,4 @@ -// using System.Collections.Generic; +// using System.Collections.Generic; // using System.IO; // using UnityEditor; // using UnityEditor.Build; diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ShaderModifyListener.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ShaderModifyListener.cs index 7b019d847..5d877f6c5 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ShaderModifyListener.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/AssetProcessor/ShaderModifyListener.cs @@ -1,6 +1,7 @@ // Copyright (c) Jason Ma using System; using System.IO; +using LWGUI.PerformanceMonitor; using UnityEditor; using UnityEngine; @@ -15,10 +16,14 @@ namespace LWGUI { foreach (var assetPath in importedAssets) { - if (Path.GetExtension(assetPath).Equals(".shader", StringComparison.OrdinalIgnoreCase)) + var ext = Path.GetExtension(assetPath); + if (ext.Equals(".shader", StringComparison.OrdinalIgnoreCase) + || ext.Equals(".shadergraph", StringComparison.OrdinalIgnoreCase) + ) { var shader = AssetDatabase.LoadAssetAtPath(assetPath); MetaDataHelper.ReleaseShaderMetadataCache(shader); + ShaderPerfMonitor.ClearShaderPerfCache(shader); ReflectionHelper.InvalidatePropertyCache(shader); } } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/CustomGUISample/CustomFooter.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/CustomGUISample/CustomFooter.cs index 1364ce972..e27b95913 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/CustomGUISample/CustomFooter.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/CustomGUISample/CustomFooter.cs @@ -1,4 +1,4 @@ -using UnityEngine; +using UnityEngine; using UnityEditor; namespace LWGUI.CustomGUISample diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ContextMenuHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ContextMenuHelper.cs new file mode 100644 index 000000000..0a9777413 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ContextMenuHelper.cs @@ -0,0 +1,308 @@ +// Copyright (c) Jason Ma + +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + public class ContextMenuHelper + { + #region Copy and Paste + + private static Material _copiedMaterial; + private static List _copiedProps = new(); + + public static void CopyMaterial(Material mat) + { + _copiedMaterial = Object.Instantiate(mat); + } + + public static void PastePropertiesToMaterials(LWGUIMetaDatas metaDatas, uint valueMask) + { + if (!_copiedMaterial) + { + Debug.LogError("LWGUI: Please copy Material Properties first!"); + return; + } + + var targetMaterials = metaDatas.GetMaterialEditor().targets; + if (!VersionControlHelper.Checkout(targetMaterials)) + { + Debug.LogError("LWGUI: One or more materials unable to write!"); + return; + } + + Undo.RecordObjects(targetMaterials, "LWGUI: Paste Material Properties"); + foreach (Material material in targetMaterials) + { + PastePropertiesToMaterial(material, valueMask); + } + } + + public static void PastePropertiesToMaterial(Material target, uint valueMask = ToolbarHelper.CopyMaterialValueMaskAll) + { + if (!_copiedMaterial) + { + Debug.LogError("LWGUI: Please copy Material Properties first!"); + return; + } + if (!VersionControlHelper.Checkout(target)) + { + Debug.LogError("LWGUI: Unable to write material!"); + return; + } + Undo.RecordObject(target, "LWGUI: Paste Material Properties"); + for (int i = 0; i < _copiedMaterial.shader.GetPropertyCount(); i++) + { + var name = _copiedMaterial.shader.GetPropertyName(i); + var type = _copiedMaterial.shader.GetPropertyType(i); + PastePropertyValueToMaterial(target, name, name, type, valueMask); + } + if ((valueMask & (uint)ToolbarHelper.CopyMaterialValueMask.Keyword) != 0) + target.shaderKeywords = _copiedMaterial.shaderKeywords; + if ((valueMask & (uint)ToolbarHelper.CopyMaterialValueMask.RenderQueue) != 0) + target.renderQueue = _copiedMaterial.renderQueue; + } + + private static void PastePropertyValueToMaterial(Material material, string srcName, string dstName) + { + for (int i = 0; i < _copiedMaterial.shader.GetPropertyCount(); i++) + { + var name = _copiedMaterial.shader.GetPropertyName(i); + if (name == srcName) + { + var type = _copiedMaterial.shader.GetPropertyType(i); + PastePropertyValueToMaterial(material, srcName, dstName, type); + return; + } + } + } + + private static void PastePropertyValueToMaterial(Material material, string srcName, string dstName, ShaderPropertyType type, uint valueMask = (uint)ToolbarHelper.CopyMaterialValueMask.All) + { + switch (type) + { + case ShaderPropertyType.Color: + if ((valueMask & (uint)ToolbarHelper.CopyMaterialValueMask.Vector) != 0) + material.SetColor(dstName, _copiedMaterial.GetColor(srcName)); + break; + case ShaderPropertyType.Vector: + if ((valueMask & (uint)ToolbarHelper.CopyMaterialValueMask.Vector) != 0) + material.SetVector(dstName, _copiedMaterial.GetVector(srcName)); + break; + case ShaderPropertyType.Texture: + if ((valueMask & (uint)ToolbarHelper.CopyMaterialValueMask.Texture) != 0) + material.SetTexture(dstName, _copiedMaterial.GetTexture(srcName)); + break; + // Float + default: + if ((valueMask & (uint)ToolbarHelper.CopyMaterialValueMask.Float) != 0) + material.SetFloat(dstName, _copiedMaterial.GetFloat(srcName)); + break; + } + } + + #endregion + + private static void EditPresetEvent(string mode, LwguiShaderPropertyPreset presetAsset, List targetPresets, MaterialProperty prop, LWGUIMetaDatas metaDatas) + { + if (!VersionControlHelper.Checkout(presetAsset)) + { + Debug.LogError("LWGUI: Can not edit the preset: " + presetAsset); + return; + } + foreach (var targetPreset in targetPresets) + { + switch (mode) + { + case "Add": + case "Update": + targetPreset.AddOrUpdateIncludeExtraProperties(metaDatas, prop); + break; + case "Remove": + targetPreset.RemoveIncludeExtraProperties(metaDatas, prop.name); + break; + } + } + EditorUtility.SetDirty(presetAsset); + metaDatas.perMaterialData.InvalidateDefaultMaterialCache(); + MetaDataHelper.ForceUpdateMaterialMetadataCache(metaDatas.GetMaterial()); + } + + public static void DoPropertyContextMenus(Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) + { + if (Event.current.type != EventType.ContextClick || !rect.Contains(Event.current.mousePosition)) return; + + Event.current.Use(); + + var (perShaderData, perMaterialData, perInspectorData) = metaDatas.GetDatas(); + var (propStaticData, propDynamicData) = metaDatas.GetPropDatas(prop); + var menu = new GenericMenu(); + + // 2022+ Material Varant Menus +#if UNITY_2022_1_OR_NEWER + ReflectionHelper.HandleApplyRevert(menu, prop); +#endif + + // Copy + menu.AddItem(new GUIContent("Copy"), false, () => + { + _copiedMaterial = UnityEngine.Object.Instantiate(metaDatas.GetMaterial()); + _copiedProps.Clear(); + _copiedProps.Add(prop.name); + foreach (var extraPropName in propStaticData.extraPropNames) + { + _copiedProps.Add(extraPropName); + } + + // Copy Children + foreach (var childPropStaticData in propStaticData.children) + { + _copiedProps.Add(childPropStaticData.name); + foreach (var extraPropName in childPropStaticData.extraPropNames) + { + _copiedProps.Add(extraPropName); + } + + foreach (var childChildPropStaticData in childPropStaticData.children) + { + _copiedProps.Add(childChildPropStaticData.name); + foreach (var extraPropName in childChildPropStaticData.extraPropNames) + { + _copiedProps.Add(extraPropName); + } + } + } + }); + + // Paste + GenericMenu.MenuFunction pasteAction = () => + { + if (!VersionControlHelper.Checkout(prop.targets)) + { + Debug.LogError("LWGUI: One or more materials unable to write!"); + return; + } + + Undo.RecordObjects(prop.targets, "LWGUI: Paste Material Properties"); + + foreach (Material material in prop.targets) + { + var index = 0; + + PastePropertyValueToMaterial(material, _copiedProps[index++], prop.name); + foreach (var extraPropName in propStaticData.extraPropNames) + { + if (index == _copiedProps.Count) break; + PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName); + } + + // Paste Children + foreach (var childPropStaticData in propStaticData.children) + { + if (index == _copiedProps.Count) break; + PastePropertyValueToMaterial(material, _copiedProps[index++], childPropStaticData.name); + foreach (var extraPropName in childPropStaticData.extraPropNames) + { + if (index == _copiedProps.Count) break; + PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName); + } + + foreach (var childChildPropStaticData in childPropStaticData.children) + { + if (index == _copiedProps.Count) break; + PastePropertyValueToMaterial(material, _copiedProps[index++], childChildPropStaticData.name); + foreach (var extraPropName in childChildPropStaticData.extraPropNames) + { + if (index == _copiedProps.Count) break; + PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName); + } + } + } + MetaDataHelper.ForceUpdateMaterialMetadataCache(material); + } + }; + + if (_copiedMaterial != null && _copiedProps.Count > 0 && GUI.enabled) + menu.AddItem(new GUIContent("Paste"), false, pasteAction); + else + menu.AddDisabledItem(new GUIContent("Paste")); + + menu.AddSeparator(""); + + // Copy Display Name + menu.AddItem(new GUIContent("Copy Display Name"), false, () => + { + EditorGUIUtility.systemCopyBuffer = propStaticData.displayName; + }); + + // Copy Property Names + menu.AddItem(new GUIContent("Copy Property Names"), false, () => + { + EditorGUIUtility.systemCopyBuffer = prop.name; + foreach (var extraPropName in propStaticData.extraPropNames) + { + EditorGUIUtility.systemCopyBuffer += ", " + extraPropName; + } + }); + + // menus.AddSeparator(""); + // + // // Add to Favorites + // menus.AddItem(new GUIContent("Add to Favorites"), false, () => + // { + // }); + // + // // Remove from Favorites + // menus.AddItem(new GUIContent("Remove from Favorites"), false, () => + // { + // }); + + // Preset + if (GUI.enabled) + { + menu.AddSeparator(""); + foreach (var activePresetData in perMaterialData.activePresetDatas) + { + // Cull self + if (activePresetData.property == prop) continue; + + var activePreset = activePresetData.preset; + var (presetPropStaticData, presetPropDynamicData) = metaDatas.GetPropDatas(activePresetData.property); + var presetAsset = presetPropStaticData.propertyPresetAsset; + var presetPropDisplayName = presetPropStaticData.displayName; + + // Cull invisible presets + if (!presetPropDynamicData.isShowing) continue; + + if (activePreset.GetPropertyValue(prop.name) != null) + { + menu.AddItem(new GUIContent("Update to Preset/" + presetPropDisplayName + "/" + "All"), false, () => EditPresetEvent("Update", presetAsset, presetAsset.GetPresets(), prop, metaDatas)); + menu.AddItem(new GUIContent("Update to Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Update", presetAsset, new List(){activePreset}, prop, metaDatas)); + menu.AddItem(new GUIContent("Remove from Preset/" + presetPropDisplayName + "/" + "All"), false, () => EditPresetEvent("Remove", presetAsset, presetAsset.GetPresets(), prop, metaDatas)); + menu.AddItem(new GUIContent("Remove from Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Remove", presetAsset, new List(){activePreset}, prop, metaDatas)); + } + else + { + menu.AddItem(new GUIContent("Add to Preset/" + presetPropDisplayName + "/" + "All"), false, () => EditPresetEvent("Add", presetAsset, presetAsset.GetPresets(), prop, metaDatas)); + menu.AddItem(new GUIContent("Add to Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Add", presetAsset, new List(){activePreset}, prop, metaDatas)); + } + } + } + + // Custom + if (propStaticData.baseDrawers != null) + { + foreach (var baseDrawer in propStaticData.baseDrawers) + { + baseDrawer.GetCustomContextMenus(menu, rect, prop, metaDatas); + } + } + + menu.ShowAsContext(); + } + + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ContextMenuHelper.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ContextMenuHelper.cs.meta new file mode 100644 index 000000000..569138b3b --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ContextMenuHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: aedae295d18e4884bc12b86aadfbab80 +timeCreated: 1760781897 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/GUIStyles.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/GUIStyles.cs new file mode 100644 index 000000000..3a57f71dc --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/GUIStyles.cs @@ -0,0 +1,84 @@ +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + public static class GUIStyles + { + // Tips: Use properties to fix null reference errors + private static GUIStyle _title; + private static GUIStyle _iconButton; + private static GUIStyle _foldout; + private static GUIStyle _helpbox; + private static GUIStyle _rampSelectButton; + private static GUIStyle _objectFieldButton; + private static GUIStyle _toolbarSearchTextFieldPopup; + private static GUIStyle _label_monospace; + + + public static GUIStyle title => _title ?? new GUIStyle(EditorStyles.boldLabel) + { + alignment = TextAnchor.LowerLeft, + border = + { + bottom = 2 + } + }; + + public static GUIStyle iconButton => _iconButton ?? new GUIStyle(EditorStyles.iconButton) { fixedHeight = 0, fixedWidth = 0 }; + + public static GUIStyle foldout => _foldout ?? new GUIStyle(EditorStyles.miniButton) + { + contentOffset = new Vector2(22, 0), + fixedHeight = 27, + alignment = TextAnchor.MiddleLeft, + font = EditorStyles.boldLabel.font, + fontSize = EditorStyles.boldLabel.fontSize + 1 + }; + + public static GUIStyle helpbox => _helpbox ?? new GUIStyle(EditorStyles.helpBox) { fontSize = 12 }; + + public static GUIStyle rampSelectButton => _rampSelectButton ?? new GUIStyle(EditorStyles.miniButton) + { + fixedHeight = 0, + stretchHeight = true, + alignment = TextAnchor.MiddleLeft + }; + + public static GUIStyle objectFieldButton => _objectFieldButton ?? new GUIStyle("ObjectFieldButton") + { + fixedHeight = 0, + stretchHeight = true + }; + + public static GUIStyle toolbarSearchTextFieldPopup + { + get + { + if (_toolbarSearchTextFieldPopup == null) + { + string toolbarSeachTextFieldPopupStr = "ToolbarSeachTextFieldPopup"; + { + // ToolbarSeachTextFieldPopup has renamed at Unity 2021.3.28+ +#if !UNITY_2022_3_OR_NEWER + string[] versionParts = Application.unityVersion.Split('.'); + int majorVersion = int.Parse(versionParts[0]); + int minorVersion = int.Parse(versionParts[1]); + Match patchVersionMatch = Regex.Match(versionParts[2], @"\d+"); + int patchVersion = int.Parse(patchVersionMatch.Value); + if (majorVersion >= 2021 && minorVersion >= 3 && patchVersion >= 28) +#endif + { + toolbarSeachTextFieldPopupStr = "ToolbarSearchTextFieldPopup"; + } + } + _toolbarSearchTextFieldPopup = new GUIStyle(toolbarSeachTextFieldPopupStr); + } + return _toolbarSearchTextFieldPopup; + } + } + + public static GUIStyle label_monospace => _label_monospace ?? new GUIStyle(EditorStyles.label) { font = EditorGUIUtility.Load("Fonts/RobotoMono/RobotoMono-Regular.ttf") as Font }; + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/GUIStyles.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/GUIStyles.cs.meta new file mode 100644 index 000000000..ff32cc4bf --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/GUIStyles.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 09e9a4a53c4e4d36b20c466825f07a63 +timeCreated: 1760968069 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/Helper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/Helper.cs index 01d5824c5..0b83ee767 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/Helper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/Helper.cs @@ -20,29 +20,11 @@ namespace LWGUI #region Misc - public static readonly string ProjectPath = Application.dataPath.Substring(0, Application.dataPath.Length - 6); - public static bool IsPropertyHideInInspector(MaterialProperty prop) { return (prop.GetPropertyFlags() & ShaderPropertyFlags.HideInInspector) != 0; } - public static bool StringToBool(string str) => str?.ToLower() is "on" or "true"; - - public static string GetKeywordName(string keyword, string propName) - { - string k; - if (string.IsNullOrEmpty(keyword) || keyword == "__") - { - k = propName.ToUpperInvariant() + "_ON"; - } - else - { - k = keyword.ToUpperInvariant(); - } - return k; - } - public static void SetShaderKeywordEnabled(Object[] materials, string keywordName, bool isEnable) { if (string.IsNullOrEmpty(keywordName) || string.IsNullOrEmpty(keywordName)) return; @@ -90,6 +72,7 @@ namespace LWGUI { material.SetShaderPassEnabled(lightModeNames[i], enabled); } + EditorUtility.SetDirty(material); } } @@ -110,13 +93,6 @@ namespace LWGUI public static LWGUIMetaDatas GetLWGUIMetadatas(MaterialEditor editor) => GetLWGUI(editor).metaDatas; - public static void AdaptiveFieldWidth(GUIStyle style, GUIContent content) - { - var extraTextWidth = Mathf.Max(0, style.CalcSize(content).x - (EditorGUIUtility.fieldWidth - RevertableHelper.revertButtonWidth)); - EditorGUIUtility.labelWidth -= extraTextWidth; - EditorGUIUtility.fieldWidth += extraTextWidth; - } - public static void BeginProperty(Rect rect, MaterialProperty property, LWGUIMetaDatas metaDatas) { #if UNITY_2022_1_OR_NEWER @@ -148,6 +124,43 @@ namespace LWGUI #endregion + #region String + + public static bool StringToBool(string str) => str?.ToLower() is "on" or "true"; + + public static string FillStringLengthBySpace(string str, int minStringLength) + { + if (str.Length >= minStringLength) + return str; + + return str + string.Concat(Enumerable.Repeat(' ', minStringLength - str.Length)); + } + + public static string GetKeywordName(string keyword, string propName) + { + string k; + if (string.IsNullOrEmpty(keyword) || keyword == "__") + { + k = propName.ToUpperInvariant() + "_ON"; + } + else + { + k = keyword.ToUpperInvariant(); + } + return k; + } + + public static void AdaptiveFieldWidth(GUIStyle style, GUIContent content) + { + var extraTextWidth = Mathf.Max(0, style.CalcSize(content).x - (EditorGUIUtility.fieldWidth - RevertableHelper.revertButtonWidth)); + EditorGUIUtility.labelWidth -= extraTextWidth; + EditorGUIUtility.fieldWidth += extraTextWidth; + } + + + #endregion + + #region Math public const double Float_Epsilon = 1e-10; @@ -178,60 +191,6 @@ namespace LWGUI #endregion - #region GUI Styles - - // Tips: Use properties to fix null reference errors - - private static GUIStyle _guiStyles_IconButton; - public static GUIStyle guiStyles_IconButton => _guiStyles_IconButton ?? new GUIStyle(EditorStyles.iconButton) { fixedHeight = 0, fixedWidth = 0 }; - - private static GUIStyle _guiStyle_Foldout; - public static GUIStyle guiStyle_Foldout => _guiStyle_Foldout ?? new GUIStyle(EditorStyles.miniButton) - { - contentOffset = new Vector2(22, 0), - fixedHeight = 27, - alignment = TextAnchor.MiddleLeft, - font = EditorStyles.boldLabel.font, - fontSize = EditorStyles.boldLabel.fontSize + 1 - }; - - private static GUIStyle _guiStyle_Helpbox; - public static GUIStyle guiStyle_Helpbox => _guiStyle_Helpbox ?? new GUIStyle(EditorStyles.helpBox) { fontSize = 12 }; - - private static GUIStyle _guiStyle_RampSelectButton; - public static GUIStyle guiStyle_RampSelectButton => _guiStyle_RampSelectButton ?? new GUIStyle(EditorStyles.miniButton) { alignment = TextAnchor.MiddleLeft }; - - private static GUIStyle _guiStyles_ToolbarSearchTextFieldPopup; - public static GUIStyle guiStyles_ToolbarSearchTextFieldPopup - { - get - { - if (_guiStyles_ToolbarSearchTextFieldPopup == null) - { - string toolbarSeachTextFieldPopupStr = "ToolbarSeachTextFieldPopup"; - { - // ToolbarSeachTextFieldPopup has renamed at Unity 2021.3.28+ -#if !UNITY_2022_3_OR_NEWER - string[] versionParts = Application.unityVersion.Split('.'); - int majorVersion = int.Parse(versionParts[0]); - int minorVersion = int.Parse(versionParts[1]); - Match patchVersionMatch = Regex.Match(versionParts[2], @"\d+"); - int patchVersion = int.Parse(patchVersionMatch.Value); - if (majorVersion >= 2021 && minorVersion >= 3 && patchVersion >= 28) -#endif - { - toolbarSeachTextFieldPopupStr = "ToolbarSearchTextFieldPopup"; - } - } - _guiStyles_ToolbarSearchTextFieldPopup = new GUIStyle(toolbarSeachTextFieldPopupStr); - } - return _guiStyles_ToolbarSearchTextFieldPopup; - } - } - - #endregion - - #region Draw GUI for Drawers // TODO: use Reflection @@ -285,7 +244,7 @@ namespace LWGUI GUI.enabled = true; var guiColor = GUI.backgroundColor; GUI.backgroundColor = isFolding ? Color.white : new Color(0.85f, 0.85f, 0.85f); - if (GUI.Button(rect, label, guiStyle_Foldout)) + if (GUI.Button(rect, label, GUIStyles.foldout)) { isFolding = !isFolding; GUI.changed = false; @@ -349,10 +308,10 @@ namespace LWGUI { var content = new GUIContent(helpboxStr, _helpboxIcon); var textWidth = GetCurrentPropertyLayoutWidth(); - var textHeight = guiStyle_Helpbox.CalcHeight(content, textWidth); + var textHeight = GUIStyles.helpbox.CalcHeight(content, textWidth); var helpboxRect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(true, textHeight)); helpboxRect.xMax -= RevertableHelper.revertButtonWidth; - GUI.Label(helpboxRect, content, guiStyle_Helpbox); + GUI.Label(helpboxRect, content, GUIStyles.helpbox); // EditorGUI.HelpBox(helpboxRect, helpboxStr, MessageType.Info); } } @@ -372,610 +331,20 @@ namespace LWGUI logoRect.xMin += w * 0.5f - _logo.width * 0.5f; logoRect.xMax -= w * 0.5f - _logo.width * 0.5f; - if (EditorGUIUtility.currentViewWidth >= logoRect.width && GUI.Button(logoRect, _logoGuiContent, guiStyles_IconButton)) + if (EditorGUIUtility.currentViewWidth >= logoRect.width && GUI.Button(logoRect, _logoGuiContent, GUIStyles.iconButton)) { Application.OpenURL("https://github.com/JasonMa0012/LWGUI"); } } #endregion - - - #region Toolbar Buttons - - private static Material _copiedMaterial; - private static List _copiedProps = new List(); - - private const string _iconCopyGUID = "9cdef444d18d2ce4abb6bbc4fed4d109"; - private const string _iconPasteGUID = "8e7a78d02e4c3574998524a0842a8ccb"; - private const string _iconSelectGUID = "6f44e40b24300974eb607293e4224ecc"; - private const string _iconCheckoutGUID = "72488141525eaa8499e65e52755cb6d0"; - private const string _iconExpandGUID = "2382450e7f4ddb94c9180d6634c41378"; - private const string _iconCollapseGUID = "929b6e5dfacc42b429d715a3e1ca2b57"; - private const string _iconVisibilityGUID = "9576e23a695b35d49a9fc55c9a948b4f"; - - private const string _iconCopyTooltip = "Copy Material Properties"; - private const string _iconPasteTooltip = "Paste Material Properties\n\nRight-click to paste values by type."; - private const string _iconSelectTooltip = "Select the Material Asset\n\nUsed to jump from a Runtime Material Instance to a Material Asset."; - private const string _iconCheckoutTooltip = "Checkout selected Material Assets"; - private const string _iconExpandTooltip = "Expand All Groups"; - private const string _iconCollapseTooltip = "Collapse All Groups"; - private const string _iconVisibilityTooltip = "Display Mode"; - - private static GUIContent _guiContentCopyCache; - private static GUIContent _guiContentPasteCache; - private static GUIContent _guiContentSelectCache; - private static GUIContent _guiContentChechoutCache; - private static GUIContent _guiContentExpandCache; - private static GUIContent _guiContentCollapseCache; - private static GUIContent _guiContentVisibilityCache; - private static GUIContent _guiContentCopy => _guiContentCopyCache = _guiContentCopyCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconCopyGUID)), _iconCopyTooltip); - private static GUIContent _guiContentPaste => _guiContentPasteCache = _guiContentPasteCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconPasteGUID)), _iconPasteTooltip); - private static GUIContent _guiContentSelect => _guiContentSelectCache = _guiContentSelectCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconSelectGUID)), _iconSelectTooltip); - private static GUIContent _guiContentChechout => _guiContentChechoutCache = _guiContentChechoutCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconCheckoutGUID)), _iconCheckoutTooltip); - private static GUIContent _guiContentExpand => _guiContentExpandCache = _guiContentExpandCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconExpandGUID)), _iconExpandTooltip); - private static GUIContent _guiContentCollapse => _guiContentCollapseCache = _guiContentCollapseCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconCollapseGUID)), _iconCollapseTooltip); - private static GUIContent _guiContentVisibility => _guiContentVisibilityCache = _guiContentVisibilityCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconVisibilityGUID)), _iconVisibilityTooltip); - - - private enum CopyMaterialValueMask - { - Float = 1 << 0, - Vector = 1 << 1, - Texture = 1 << 2, - Keyword = 1 << 3, - RenderQueue = 1 << 4, - Number = Float | Vector, - All = (1 << 5) - 1, - } - - private static GUIContent[] _pasteMaterialMenus = new[] - { - new GUIContent("Paste Number Values"), - new GUIContent("Paste Texture Values"), - new GUIContent("Paste Keywords"), - new GUIContent("Paste RenderQueue"), - }; - - private static uint[] _pasteMaterialMenuValueMasks = new[] - { - (uint)CopyMaterialValueMask.Number, - (uint)CopyMaterialValueMask.Texture, - (uint)CopyMaterialValueMask.Keyword, - (uint)CopyMaterialValueMask.RenderQueue, - }; - - private static void DoPasteMaterialProperties(LWGUIMetaDatas metaDatas, uint valueMask) - { - if (!_copiedMaterial) - { - Debug.LogError("LWGUI: Please copy Material Properties first!"); - return; - } - - var targetMaterials = metaDatas.GetMaterialEditor().targets; - if (!VersionControlHelper.Checkout(targetMaterials)) - { - Debug.LogError("LWGUI: One or more materials unable to write!"); - return; - } - - Undo.RecordObjects(targetMaterials, "LWGUI: Paste Material Properties"); - foreach (Material material in targetMaterials) - { - for (int i = 0; i < _copiedMaterial.shader.GetPropertyCount(); i++) - { - var name = _copiedMaterial.shader.GetPropertyName(i); - var type = _copiedMaterial.shader.GetPropertyType(i); - PastePropertyValueToMaterial(material, name, name, type, valueMask); - } - if ((valueMask & (uint)CopyMaterialValueMask.Keyword) != 0) - material.shaderKeywords = _copiedMaterial.shaderKeywords; - if ((valueMask & (uint)CopyMaterialValueMask.RenderQueue) != 0) - material.renderQueue = _copiedMaterial.renderQueue; - } - } - - private static void PastePropertyValueToMaterial(Material material, string srcName, string dstName) - { - for (int i = 0; i < _copiedMaterial.shader.GetPropertyCount(); i++) - { - var name = _copiedMaterial.shader.GetPropertyName(i); - if (name == srcName) - { - var type = _copiedMaterial.shader.GetPropertyType(i); - PastePropertyValueToMaterial(material, srcName, dstName, type); - return; - } - } - } - - private static void PastePropertyValueToMaterial(Material material, string srcName, string dstName, ShaderPropertyType type, uint valueMask = (uint)CopyMaterialValueMask.All) - { - switch (type) - { - case ShaderPropertyType.Color: - if ((valueMask & (uint)CopyMaterialValueMask.Vector) != 0) - material.SetColor(dstName, _copiedMaterial.GetColor(srcName)); - break; - case ShaderPropertyType.Vector: - if ((valueMask & (uint)CopyMaterialValueMask.Vector) != 0) - material.SetVector(dstName, _copiedMaterial.GetVector(srcName)); - break; - case ShaderPropertyType.Texture: - if ((valueMask & (uint)CopyMaterialValueMask.Texture) != 0) - material.SetTexture(dstName, _copiedMaterial.GetTexture(srcName)); - break; - // Float - default: - if ((valueMask & (uint)CopyMaterialValueMask.Float) != 0) - material.SetFloat(dstName, _copiedMaterial.GetFloat(srcName)); - break; - } - } - - public static void DrawToolbarButtons(ref Rect toolBarRect, LWGUIMetaDatas metaDatas) - { - var (perShaderData, perMaterialData, perInspectorData) = metaDatas.GetDatas(); - - // Copy - var buttonRectOffset = toolBarRect.height + 2; - var buttonRect = new Rect(toolBarRect.x, toolBarRect.y, toolBarRect.height, toolBarRect.height); - toolBarRect.xMin += buttonRectOffset; - if (GUI.Button(buttonRect, _guiContentCopy, Helper.guiStyles_IconButton)) - { - _copiedMaterial = UnityEngine.Object.Instantiate(metaDatas.GetMaterial()); - } - - // Paste - buttonRect.x += buttonRectOffset; - toolBarRect.xMin += buttonRectOffset; - // Right Click - if (Event.current.type == EventType.MouseDown - && Event.current.button == 1 - && buttonRect.Contains(Event.current.mousePosition)) - { - EditorUtility.DisplayCustomMenu(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0), _pasteMaterialMenus, -1, - (data, options, selected) => - { - DoPasteMaterialProperties(metaDatas, _pasteMaterialMenuValueMasks[selected]); - }, null); - Event.current.Use(); - } - // Left Click - if (GUI.Button(buttonRect, _guiContentPaste, Helper.guiStyles_IconButton)) - { - DoPasteMaterialProperties(metaDatas, (uint)CopyMaterialValueMask.All); - } - - // Select Material Asset, jump from a Runtime Material Instance to a Material Asset - buttonRect.x += buttonRectOffset; - toolBarRect.xMin += buttonRectOffset; - if (GUI.Button(buttonRect, _guiContentSelect, Helper.guiStyles_IconButton)) - { - var material = metaDatas.GetMaterial(); - - if (AssetDatabase.Contains(material)) - { - Selection.activeObject = material; - } - else - { - if (FindMaterialAssetByMaterialInstance(material, metaDatas, out var materialAsset)) - { - Selection.activeObject = materialAsset; - } - } - } - - // Checkout - buttonRect.x += buttonRectOffset; - toolBarRect.xMin += buttonRectOffset; - if (GUI.Button(buttonRect, _guiContentChechout, Helper.guiStyles_IconButton)) - { - VersionControlHelper.Checkout(metaDatas.GetMaterialEditor().targets); - } - - // Expand - buttonRect.x += buttonRectOffset; - toolBarRect.xMin += buttonRectOffset; - if (GUI.Button(buttonRect, _guiContentExpand, Helper.guiStyles_IconButton)) - { - foreach (var propStaticDataKVPair in perShaderData.propStaticDatas) - { - if (propStaticDataKVPair.Value.isMain || propStaticDataKVPair.Value.isAdvancedHeader) - propStaticDataKVPair.Value.isExpanding = true; - } - } - - // Collapse - buttonRect.x += buttonRectOffset; - toolBarRect.xMin += buttonRectOffset; - if (GUI.Button(buttonRect, _guiContentCollapse, Helper.guiStyles_IconButton)) - { - foreach (var propStaticDataKVPair in perShaderData.propStaticDatas) - { - if (propStaticDataKVPair.Value.isMain || propStaticDataKVPair.Value.isAdvancedHeader) - propStaticDataKVPair.Value.isExpanding = false; - } - } - - // Display Mode - buttonRect.x += buttonRectOffset; - toolBarRect.xMin += buttonRectOffset; - var color = GUI.color; - var displayModeData = perShaderData.displayModeData; - if (!displayModeData.IsDefaultDisplayMode()) - GUI.color = Color.yellow; - if (GUI.Button(buttonRect, _guiContentVisibility, Helper.guiStyles_IconButton)) - { - // Build Display Mode Menu Items - var displayModeMenus = new[] - { - $"Show All Advanced Properties ({ displayModeData.advancedCount } - { perShaderData.propStaticDatas.Count })", - $"Show All Hidden Properties ({ displayModeData.hiddenCount } - { perShaderData.propStaticDatas.Count })", - $"Show Only Modified Properties ({ perMaterialData.modifiedCount } - { perShaderData.propStaticDatas.Count })", - $"Show Only Modified Properties by Group ({ perMaterialData.modifiedCount } - { perShaderData.propStaticDatas.Count })", - }; - var enabled = new[] { true, true, true, true }; - var separator = new bool[4]; - var selected = new[] - { - displayModeData.showAllAdvancedProperties ? 0 : -1, - displayModeData.showAllHiddenProperties ? 1 : -1, - displayModeData.showOnlyModifiedProperties ? 2 : -1, - displayModeData.showOnlyModifiedGroups ? 3 : -1, - }; - - - // Click Event - void OnSwitchDisplayMode(object data, string[] options, int selectedIndex) - { - switch (selectedIndex) - { - case 0: // Show All Advanced Properties - displayModeData.showAllAdvancedProperties = !displayModeData.showAllAdvancedProperties; - perShaderData.ToggleShowAllAdvancedProperties(); - break; - case 1: // Show All Hidden Properties - displayModeData.showAllHiddenProperties = !displayModeData.showAllHiddenProperties; - break; - case 2: // Show Only Modified Properties - displayModeData.showOnlyModifiedProperties = !displayModeData.showOnlyModifiedProperties; - if (displayModeData.showOnlyModifiedProperties) displayModeData.showOnlyModifiedGroups = false; - MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(metaDatas.GetShader()); - break; - case 3: // Show Only Modified Groups - displayModeData.showOnlyModifiedGroups = !displayModeData.showOnlyModifiedGroups; - if (displayModeData.showOnlyModifiedGroups) displayModeData.showOnlyModifiedProperties = false; - MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(metaDatas.GetShader()); - break; - } - } - - ReflectionHelper.DisplayCustomMenuWithSeparators(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0), - displayModeMenus, enabled, separator, selected, OnSwitchDisplayMode); - } - GUI.color = color; - - toolBarRect.xMin += 2; - } - - public static Func onFindMaterialAssetInRendererByMaterialInstance; - - private static bool FindMaterialAssetByMaterialInstance(Material material, LWGUIMetaDatas metaDatas, out Material materialAsset) - { - materialAsset = null; - - var renderers = metaDatas.perInspectorData.materialEditor.GetMeshRenderersByMaterialEditor(); - foreach (var renderer in renderers) - { - if (onFindMaterialAssetInRendererByMaterialInstance != null) - { - materialAsset = onFindMaterialAssetInRendererByMaterialInstance(renderer, material); - } - - if (materialAsset == null) - { - int index = renderer.materials.ToList().FindIndex(materialInstance => materialInstance == material); - if (index >= 0 && index < renderer.sharedMaterials.Length) - { - materialAsset = renderer.sharedMaterials[index]; - } - } - - if (materialAsset != null && AssetDatabase.Contains(materialAsset)) - return true; - } - - Debug.LogError("LWGUI: Can not find the Material Assets of: " + material.name); - - return false; - } - - #endregion - - - #region Search Field - - private static readonly int s_TextFieldHash = "EditorTextField".GetHashCode(); - private static readonly GUIContent[] _searchModeMenus = Enumerable.Range(0, (int)SearchMode.Num - 1).Select(i => - new GUIContent(((SearchMode)i).ToString())).ToArray(); - - /// is has changed? - public static bool DrawSearchField(Rect rect, LWGUIMetaDatas metaDatas) - { - var (perShaderData, perMaterialData, perInspectorData) = metaDatas.GetDatas(); - - bool hasChanged = false; - EditorGUI.BeginChangeCheck(); - - var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect); - - // Get internal TextField ControlID - int controlId = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, rect) + 1; - - // searching mode - Rect modeRect = new Rect(rect); - modeRect.width = 20f; - if (Event.current.type == UnityEngine.EventType.MouseDown && modeRect.Contains(Event.current.mousePosition)) - { - EditorUtility.DisplayCustomMenu(rect, _searchModeMenus, (int)perShaderData.searchMode, - (data, options, selected) => - { - perShaderData.searchMode = (SearchMode)selected; - hasChanged = true; - }, null); - Event.current.Use(); - } - - perShaderData.searchString = EditorGUI.TextField(rect, String.Empty, perShaderData.searchString, guiStyles_ToolbarSearchTextFieldPopup); - - if (EditorGUI.EndChangeCheck()) - hasChanged = true; - - // revert button - if (!string.IsNullOrEmpty(perShaderData.searchString) - && RevertableHelper.DrawRevertButton(revertButtonRect)) - { - perShaderData.searchString = string.Empty; - hasChanged = true; - GUIUtility.keyboardControl = 0; - } - - // display search mode - if (GUIUtility.keyboardControl != controlId - && string.IsNullOrEmpty(perShaderData.searchString) - && Event.current.type == UnityEngine.EventType.Repaint) - { - using (new EditorGUI.DisabledScope(true)) - { - var disableTextRect = new Rect(rect.x, rect.y, rect.width, - guiStyles_ToolbarSearchTextFieldPopup.fixedHeight > 0.0 - ? guiStyles_ToolbarSearchTextFieldPopup.fixedHeight - : rect.height); - disableTextRect = guiStyles_ToolbarSearchTextFieldPopup.padding.Remove(disableTextRect); - int fontSize = EditorStyles.label.fontSize; - EditorStyles.label.fontSize = guiStyles_ToolbarSearchTextFieldPopup.fontSize; - EditorStyles.label.Draw(disableTextRect, new GUIContent(perShaderData.searchMode.ToString()), false, false, false, false); - EditorStyles.label.fontSize = fontSize; - } - } - - if (hasChanged) perShaderData.UpdateSearchFilter(); - - return hasChanged; - } - - #endregion - - - #region Context Menu - - private static void EditPresetEvent(string mode, LwguiShaderPropertyPreset presetAsset, List targetPresets, MaterialProperty prop, LWGUIMetaDatas metaDatas) - { - if (!VersionControlHelper.Checkout(presetAsset)) - { - Debug.LogError("LWGUI: Can not edit the preset: " + presetAsset); - return; - } - foreach (var targetPreset in targetPresets) - { - switch (mode) - { - case "Add": - case "Update": - targetPreset.AddOrUpdateIncludeExtraProperties(metaDatas, prop); - break; - case "Remove": - targetPreset.RemoveIncludeExtraProperties(metaDatas, prop.name); - break; - } - } - EditorUtility.SetDirty(presetAsset); - MetaDataHelper.ForceUpdateMaterialMetadataCache(metaDatas.GetMaterial()); - } - - public static void DoPropertyContextMenus(Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) - { - if (Event.current.type != EventType.ContextClick || !rect.Contains(Event.current.mousePosition)) return; - - Event.current.Use(); - - var (perShaderData, perMaterialData, perInspectorData) = metaDatas.GetDatas(); - var (propStaticData, propDynamicData) = metaDatas.GetPropDatas(prop); - var menu = new GenericMenu(); - - // 2022+ Material Varant Menus -#if UNITY_2022_1_OR_NEWER - ReflectionHelper.HandleApplyRevert(menu, prop); -#endif - - // Copy - menu.AddItem(new GUIContent("Copy"), false, () => - { - _copiedMaterial = UnityEngine.Object.Instantiate(metaDatas.GetMaterial()); - _copiedProps.Clear(); - _copiedProps.Add(prop.name); - foreach (var extraPropName in propStaticData.extraPropNames) - { - _copiedProps.Add(extraPropName); - } - - // Copy Children - foreach (var childPropStaticData in propStaticData.children) - { - _copiedProps.Add(childPropStaticData.name); - foreach (var extraPropName in childPropStaticData.extraPropNames) - { - _copiedProps.Add(extraPropName); - } - - foreach (var childChildPropStaticData in childPropStaticData.children) - { - _copiedProps.Add(childChildPropStaticData.name); - foreach (var extraPropName in childChildPropStaticData.extraPropNames) - { - _copiedProps.Add(extraPropName); - } - } - } - }); - - // Paste - GenericMenu.MenuFunction pasteAction = () => - { - if (!VersionControlHelper.Checkout(prop.targets)) - { - Debug.LogError("LWGUI: One or more materials unable to write!"); - return; - } - - Undo.RecordObjects(prop.targets, "LWGUI: Paste Material Properties"); - - foreach (Material material in prop.targets) - { - var index = 0; - - PastePropertyValueToMaterial(material, _copiedProps[index++], prop.name); - foreach (var extraPropName in propStaticData.extraPropNames) - { - if (index == _copiedProps.Count) break; - PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName); - } - - // Paste Children - foreach (var childPropStaticData in propStaticData.children) - { - if (index == _copiedProps.Count) break; - PastePropertyValueToMaterial(material, _copiedProps[index++], childPropStaticData.name); - foreach (var extraPropName in childPropStaticData.extraPropNames) - { - if (index == _copiedProps.Count) break; - PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName); - } - - foreach (var childChildPropStaticData in childPropStaticData.children) - { - if (index == _copiedProps.Count) break; - PastePropertyValueToMaterial(material, _copiedProps[index++], childChildPropStaticData.name); - foreach (var extraPropName in childChildPropStaticData.extraPropNames) - { - if (index == _copiedProps.Count) break; - PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName); - } - } - } - MetaDataHelper.ForceUpdateMaterialMetadataCache(material); - } - }; - - if (_copiedMaterial != null && _copiedProps.Count > 0 && GUI.enabled) - menu.AddItem(new GUIContent("Paste"), false, pasteAction); - else - menu.AddDisabledItem(new GUIContent("Paste")); - - menu.AddSeparator(""); - - // Copy Display Name - menu.AddItem(new GUIContent("Copy Display Name"), false, () => - { - EditorGUIUtility.systemCopyBuffer = propStaticData.displayName; - }); - - // Copy Property Names - menu.AddItem(new GUIContent("Copy Property Names"), false, () => - { - EditorGUIUtility.systemCopyBuffer = prop.name; - foreach (var extraPropName in propStaticData.extraPropNames) - { - EditorGUIUtility.systemCopyBuffer += ", " + extraPropName; - } - }); - - // menus.AddSeparator(""); - // - // // Add to Favorites - // menus.AddItem(new GUIContent("Add to Favorites"), false, () => - // { - // }); - // - // // Remove from Favorites - // menus.AddItem(new GUIContent("Remove from Favorites"), false, () => - // { - // }); - - // Preset - if (GUI.enabled) - { - menu.AddSeparator(""); - foreach (var activePresetData in perMaterialData.activePresetDatas) - { - // Cull self - if (activePresetData.property == prop) continue; - - var activePreset = activePresetData.preset; - var (presetPropStaticData, presetPropDynamicData) = metaDatas.GetPropDatas(activePresetData.property); - var presetAsset = presetPropStaticData.propertyPresetAsset; - var presetPropDisplayName = presetPropStaticData.displayName; - - // Cull invisible presets - if (!presetPropDynamicData.isShowing) continue; - - if (activePreset.GetPropertyValue(prop.name) != null) - { - menu.AddItem(new GUIContent("Update to Preset/" + presetPropDisplayName + "/" + "All"), false, () => EditPresetEvent("Update", presetAsset, presetAsset.GetPresets(), prop, metaDatas)); - menu.AddItem(new GUIContent("Update to Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Update", presetAsset, new List(){activePreset}, prop, metaDatas)); - menu.AddItem(new GUIContent("Remove from Preset/" + presetPropDisplayName + "/" + "All"), false, () => EditPresetEvent("Remove", presetAsset, presetAsset.GetPresets(), prop, metaDatas)); - menu.AddItem(new GUIContent("Remove from Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Remove", presetAsset, new List(){activePreset}, prop, metaDatas)); - } - else - { - menu.AddItem(new GUIContent("Add to Preset/" + presetPropDisplayName + "/" + "All"), false, () => EditPresetEvent("Add", presetAsset, presetAsset.GetPresets(), prop, metaDatas)); - menu.AddItem(new GUIContent("Add to Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Add", presetAsset, new List(){activePreset}, prop, metaDatas)); - } - } - } - - // Custom - if (propStaticData.baseDrawers != null) - { - foreach (var baseDrawer in propStaticData.baseDrawers) - { - baseDrawer.GetCustomContextMenus(menu, rect, prop, metaDatas); - } - } - - menu.ShowAsContext(); - } - - #endregion #region Importer // https://docs.unity3d.com/ScriptReference/TextureImporter.GetPlatformTextureSettings.html - public static string[] platformNamesForTextureSettings => new[] { "DefaultTexturePlatform", "Standalone", "Web", "iPhone", "Android", "WebGL", "Windows Store Apps", "PS4", "XboxOne", "Nintendo Switch", "tvOS" }; + public static string[] platformNamesForTextureSettings => + new[] { "DefaultTexturePlatform", "Standalone", "Web", "iPhone", "Android", "WebGL", "Windows Store Apps", "PS4", "XboxOne", "Nintendo Switch", "tvOS" }; #endregion } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/IOHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/IOHelper.cs new file mode 100644 index 000000000..060b312a7 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/IOHelper.cs @@ -0,0 +1,215 @@ +// Copyright (c) Jason Ma + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using LWGUI.PerformanceMonitor; +using UnityEditor; +using UnityEngine; +using Debug = UnityEngine.Debug; + +namespace LWGUI +{ + public static class IOHelper + { + #region Paths + + private static string _cachedProjectPath; + + // D:/Unity/ProjectName/ + public static string ProjectPath + { + get + { + if (string.IsNullOrEmpty(_cachedProjectPath)) + _cachedProjectPath = Application.dataPath[..^6]; + return _cachedProjectPath; + } + } + + public static string GetAbsPath(string unityProjectRelativePath) => Path.Combine(ProjectPath, unityProjectRelativePath); + + public static string GetRelativePath(string absPath) => Path.GetFullPath(absPath).Replace(Path.GetFullPath(ProjectPath), string.Empty); + + private static string _cachedCompiledShaderCachePath; + + public static string CompiledShaderCacheRootPath + { + get + { + if (string.IsNullOrEmpty(_cachedCompiledShaderCachePath)) + _cachedCompiledShaderCachePath = Path.Combine(ProjectPath, "Library", "LWGUI", "ShaderPerfCache"); + return _cachedCompiledShaderCachePath; + } + } + + public static string GetValidFileName(string text) + { + StringBuilder str = new StringBuilder(); + var invalidFileNameChars = Path.GetInvalidFileNameChars(); + foreach (var c in text) + { + if (!invalidFileNameChars.Contains(c)) + { + str.Append(c); + } + } + + return str.ToString(); + } + + #endregion + + #region File + + public static bool ExistAndNotEmpty(string filePath) => File.Exists(filePath) && new FileInfo(filePath).Length > 1; + + public static void WriteBinaryFile(string filePath, byte[] bytes) + { + try + { + Directory.CreateDirectory(Path.GetDirectoryName(filePath) ?? string.Empty); + File.WriteAllBytes(filePath, bytes ?? Array.Empty()); + } + catch (Exception e) + { + Debug.LogError(e.Message); + } + } + + public static void WriteTextFile(string filePath, string text) + { + try + { + Directory.CreateDirectory(Path.GetDirectoryName(filePath) ?? string.Empty); + File.WriteAllText(filePath, text ?? string.Empty, Encoding.UTF8); + } + catch (Exception e) + { + Debug.LogError(e.Message); + } + } + + public static string ReadTextFile(string filePath) + { + try + { + return File.ReadAllText(filePath, Encoding.UTF8); + } + catch (Exception e) + { + Debug.LogError(e.Message); + return null; + } + } + + #endregion + + #region Process + + public static bool RunProcess(string file, string args, + out string output) + { + output = string.Empty; + + var p = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = file, + Arguments = args, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + StandardOutputEncoding = Encoding.UTF8, + StandardErrorEncoding = Encoding.UTF8 + } + }; + + var stdout = new StringBuilder(); + var stderr = new StringBuilder(); + + p.OutputDataReceived += (_, e) => stdout.AppendLine(e.Data); + p.ErrorDataReceived += (_, e) => stderr.AppendLine(e.Data); + + p.Start(); + p.BeginOutputReadLine(); + p.BeginErrorReadLine(); + p.WaitForExit(); + + output = stdout.ToString(); + + if (p.ExitCode != 0) + { + output = stderr.ToString() + output; + Debug.LogError($"LWGUI: Process Exit Code {p.ExitCode}: {output}" + + $"File: {file}\n" + + $"Args: {args}"); + return false; + } + + if (string.IsNullOrWhiteSpace(output)) + { + output = stderr.ToString(); + return false; + } + + return true; + } + + public static bool RunCMD(string args, + out string output) + { + return RunProcess("cmd.exe", $"/C {args}", + out output); + } + + public static void OpenFile(string filePath) + { + Process.Start(filePath); + } + + #endregion + + #region Performance Monitor + + public static string GetCompiledShaderCacheRootDirectory(Shader shader) + { + var shaderPath = AssetDatabase.Contains(shader) ? AssetDatabase.GetAssetPath(shader) : null; + var shaderCachePath = shaderPath != null + // Assets/Shaders/Lit.shader => Shaders/Lit + ? Path.Combine(Path.GetDirectoryName(shaderPath[7..]) ?? string.Empty, Path.GetFileNameWithoutExtension(shaderPath)) + : GetValidFileName(shader.name.Replace('/', '_').Replace('\\', '_')); + + return Path.Combine(CompiledShaderCacheRootPath, shaderCachePath); + } + + public static string GetCompiledShaderVariantCacheDirectory(Shader shader, ShaderPerfData shaderPerfData) + { + return Path.Combine( + GetCompiledShaderCacheRootDirectory(shader), + shaderPerfData.subshaderIndex.ToString(), + shaderPerfData.passName, + shaderPerfData.hash); + } + + public static void ClearShaderPerfCache(Shader shader) + { + try + { + var shaderDir = GetCompiledShaderCacheRootDirectory(shader); + if (Directory.Exists(shaderDir)) + Directory.Delete(shaderDir, true); + } + catch (Exception e) + { + Debug.LogWarning($"LWGUI: Cleaning the Shader({shader.name}) cache failed: {e.Message}"); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/IOHelper.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/IOHelper.cs.meta new file mode 100644 index 000000000..5841049d5 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/IOHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d97df5d9f08d48ac9dedc5b421b936dc +timeCreated: 1760615660 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/MetaDataHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/MetaDataHelper.cs index 5275ade33..7b82285bb 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/MetaDataHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/MetaDataHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using System; using System.Collections.Generic; @@ -14,7 +14,6 @@ namespace LWGUI public PerMaterialData perMaterialData; public PerInspectorData perInspectorData; - #region Get Prop Data public PropertyStaticData GetPropStaticData(string propName) => perShaderData?.GetPropStaticData(propName); @@ -27,7 +26,7 @@ namespace LWGUI public MaterialProperty GetProperty(string propName) => GetPropDynamicData(propName)?.property; - public MaterialProperty GetDefaultProperty(string propName) => GetPropDynamicData(propName)?.defualtProperty; + public MaterialProperty GetDefaultProperty(string propName) => GetPropDynamicData(propName)?.defaultProperty; #endregion @@ -47,6 +46,8 @@ namespace LWGUI public Material GetMaterial() => perMaterialData.material; public Shader GetShader() => perShaderData.shader; + + public string GetShaderUID() => perShaderData.shaderUID; public MaterialEditor GetMaterialEditor() => perInspectorData.materialEditor; } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/PresetHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/PresetHelper.cs index 44eeb3bb7..62f541633 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/PresetHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/PresetHelper.cs @@ -53,14 +53,18 @@ namespace LWGUI if (!_loadedPresets.ContainsKey(presetFileName) || !_loadedPresets[presetFileName]) { - Debug.LogError("LWGUI: Invalid ShaderPropertyPreset path: ‘" + presetFileName + "’ !"); + if (!BuildPipeline.isBuildingPlayer) + Debug.LogError("LWGUI: Invalid ShaderPropertyPreset path: ‘" + presetFileName + "’ !"); return null; } return _loadedPresets[presetFileName]; } - // For Developers: Call this after a material has modified in code + // For Developers: Call this function after creating a material, + // This applies all active presets and may modify some other properties. + // Usually called after the material is created, otherwise the material default value will not contain the results of Preset Drawers. + // If you only want to apply Keywords without modifying other properties, call UnityEditorExtension.ApplyMaterialPropertyAndDecoratorDrawers() public static void ApplyPresetsInMaterial(Material material) { var props = MaterialEditor.GetMaterialProperties(new UnityEngine.Object[] { material }); @@ -69,11 +73,10 @@ namespace LWGUI var drawer = ReflectionHelper.GetPropertyDrawer(material.shader, prop, out _); // Apply active preset - if (drawer != null && drawer is IPresetDrawer) + if (drawer is IPresetDrawer presetDrawer) { - var activePreset = (drawer as IPresetDrawer).GetActivePreset(prop, PresetHelper.GetPresetAsset((drawer as PresetDrawer).presetFileName)); - if (activePreset != null) - activePreset.ApplyToDefaultMaterial(material); + var activePreset = presetDrawer.GetActivePreset(prop, GetPresetAsset(presetDrawer.GetPresetFileName())); + activePreset?.ApplyToDefaultMaterial(material); } } UnityEditorExtension.ApplyMaterialPropertyAndDecoratorDrawers(material); diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RampHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RampHelper.cs index a17678b6c..82d8c7598 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RampHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RampHelper.cs @@ -1,12 +1,10 @@ -// Copyright (c) Jason Ma -using System; +// Copyright (c) Jason Ma using System.IO; using System.Linq; using LWGUI.LwguiGradientEditor; using LWGUI.Runtime.LwguiGradient; using UnityEditor; using UnityEngine; -using Object = UnityEngine.Object; namespace LWGUI { @@ -14,10 +12,13 @@ namespace LWGUI { #region RampEditor - private static readonly GUIContent _iconAdd = new GUIContent(EditorGUIUtility.IconContent("d_Toolbar Plus").image, "Add"), - _iconEdit = new GUIContent(EditorGUIUtility.IconContent("editicon.sml").image, "Edit"), - _iconDiscard = new GUIContent(EditorGUIUtility.IconContent("d_TreeEditor.Refresh").image, "Discard"), - _iconSave = new GUIContent(EditorGUIUtility.IconContent("SaveActive").image, "Save"); + private const string _iconCloneGUID = "9cdef444d18d2ce4abb6bbc4fed4d109"; + + private static readonly GUIContent _iconAdd = new (EditorGUIUtility.IconContent("d_Toolbar Plus").image, "Add"), + _iconClone = new (EditorGUIUtility.IconContent("AnimatorController Icon").image, "Clone"), + _iconEdit = new (EditorGUIUtility.IconContent("editicon.sml").image, "Edit"), + _iconDiscard = new (EditorGUIUtility.IconContent("d_TreeEditor.Refresh").image, "Discard"), + _iconSave = new (EditorGUIUtility.IconContent("SaveActive").image, "Save"); public static void RampEditor( Rect buttonRect, @@ -29,6 +30,7 @@ namespace LWGUI out bool hasChange, out bool doEditWhenNoGradient, out bool doRegisterUndo, + out bool doClone, out bool doCreate, out bool doSave, out bool doDiscard, @@ -38,11 +40,12 @@ namespace LWGUI var hasNoGradient = gradient == null; var _doEditWhenNoGradient = false; var doOpenWindow = false; - var singleButtonWidth = buttonRect.width * 0.25f; + var singleButtonWidth = buttonRect.width * 0.2f; var editRect = new Rect(buttonRect.x + singleButtonWidth * 0, buttonRect.y, singleButtonWidth, buttonRect.height); var saveRect = new Rect(buttonRect.x + singleButtonWidth * 1, buttonRect.y, singleButtonWidth, buttonRect.height); - var addRect = new Rect(buttonRect.x + singleButtonWidth * 2, buttonRect.y, singleButtonWidth, buttonRect.height); - var discardRect = new Rect(buttonRect.x + singleButtonWidth * 3, buttonRect.y, singleButtonWidth, buttonRect.height); + var cloneRect = new Rect(buttonRect.x + singleButtonWidth * 2, buttonRect.y, singleButtonWidth, buttonRect.height); + var addRect = new Rect(buttonRect.x + singleButtonWidth * 3, buttonRect.y, singleButtonWidth, buttonRect.height); + var discardRect = new Rect(buttonRect.x + singleButtonWidth * 4, buttonRect.y, singleButtonWidth, buttonRect.height); // Edit button event hasChange = false; @@ -76,6 +79,8 @@ namespace LWGUI } doEditWhenNoGradient = _doEditWhenNoGradient; + // Clone button + doClone = GUI.Button(cloneRect, _iconClone); // Create button doCreate = GUI.Button(addRect, _iconAdd); @@ -143,9 +148,8 @@ namespace LWGUI // Save texture to disk if (doSaveToDisk) { - var systemPath = Helper.ProjectPath + path; VersionControlHelper.Checkout(path); - File.WriteAllBytes(systemPath, texture2D.EncodeToPNG()); + File.WriteAllBytes(IOHelper.GetAbsPath(path), texture2D.EncodeToPNG()); assetImporter.SaveAndReimport(); } } @@ -190,15 +194,14 @@ namespace LWGUI return subJSONs[0] != subJSONs[1]; } - public static bool CreateAndSaveNewGradientTexture(int width, int height, string unityPath, bool isLinear) + public static bool CreateAndSaveNewGradientTexture(int width, int height, string unityPath, bool isLinear, LwguiGradient sourceGradient = null) { - var gradient = new LwguiGradient(); + var gradient = sourceGradient != null ? new LwguiGradient(sourceGradient) : new LwguiGradient(); var ramp = gradient.GetPreviewRampTexture(width, height, ColorSpace.Linear); var png = ramp.EncodeToPNG(); - var systemPath = Helper.ProjectPath + unityPath; - File.WriteAllBytes(systemPath, png); + File.WriteAllBytes(IOHelper.GetAbsPath(unityPath), png); AssetDatabase.ImportAsset(unityPath); SetRampTextureImporter(unityPath, true, isLinear, EncodeGradientToJSON(gradient, gradient)); @@ -262,33 +265,40 @@ namespace LWGUI } } - public static void RampIndexSelectorOverride(Rect rect, MaterialProperty prop, LwguiRampAtlas rampAtlas, RampSelectorWindow.SwitchRampMapCallback switchRampMapEvent) - { - if (!rampAtlas) - return; - - var e = Event.current; - if (e.type == UnityEngine.EventType.MouseDown && rect.Contains(e.mousePosition)) - { - e.Use(); - RampSelectorWindow.ShowWindow(prop, rampAtlas.GetTexture2Ds(LwguiGradient.ChannelMask.RGB), switchRampMapEvent); - } - } #endregion } public class RampSelectorWindow : EditorWindow { public delegate void SwitchRampMapCallback(MaterialProperty prop, Texture2D newRampMap, int index); - + public delegate void SwitchRampCallback(MaterialProperty prop, int rampIndex); + + private LwguiRampAtlas _rampAtlas; private Texture2D[] _rampMaps; private Vector2 _scrollPosition; private MaterialProperty _prop; + private SwitchRampCallback _switchRampEvent; private SwitchRampMapCallback _switchRampMapEvent; + private const float RowHeight = 18f; + private const float RowSpacing = 2f; + + public static void ShowWindow(MaterialProperty prop, LwguiRampAtlas rampAtlas, SwitchRampCallback switchRampEvent) + { + LwguiGradientWindow.CloseWindow(); + var window = CreateInstance(); + window.titleContent = new GUIContent("Ramp Selector (Atlas)"); + window.minSize = new Vector2(400, 500); + window._rampAtlas = rampAtlas; + window._prop = prop; + window._switchRampEvent = switchRampEvent; + window.ShowAuxWindow(); + } + public static void ShowWindow(MaterialProperty prop, Texture2D[] rampMaps, SwitchRampMapCallback switchRampMapEvent) { - RampSelectorWindow window = ScriptableObject.CreateInstance(); + LwguiGradientWindow.CloseWindow(); + var window = CreateInstance(); window.titleContent = new GUIContent("Ramp Selector"); window.minSize = new Vector2(400, 500); window._rampMaps = rampMaps; @@ -298,6 +308,62 @@ namespace LWGUI } private void OnGUI() + { + if (_rampAtlas != null) + DrawRampAtlasSelector(); + else if (_rampMaps != null) + DrawRampMapSelector(); + else + EditorGUILayout.HelpBox("No Ramp data available", MessageType.Error); + } + + private void DrawRampAtlasSelector() + { + EditorGUILayout.BeginVertical(); + _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition); + + for (int i = 0; i < _rampAtlas.RampCount; i++) + { + var ramp = _rampAtlas.GetRamp(i); + if (ramp == null) continue; + + var previewTextures = ramp.GetPreviewTexturesForRampSelector(_rampAtlas.rampAtlasWidth); + var textureCount = previewTextures?.Length ?? 0; + var totalHeight = Mathf.Max(1, textureCount) * RowHeight + Mathf.Max(0, textureCount - 1) * RowSpacing; + + var rect = EditorGUILayout.GetControlRect(GUILayout.Height(totalHeight)); + var guiContent = new GUIContent($"{i}. {ramp.Name}"); + var buttonWidth = Mathf.Min(300f, Mathf.Max(GUI.skin.button.CalcSize(guiContent).x, rect.width * 0.35f)); + var buttonRect = new Rect(rect.x + rect.width - buttonWidth, rect.y, buttonWidth, totalHeight); + var previewWidth = rect.width - buttonWidth - 3.0f; + + // Draw preview textures vertically + if (previewTextures != null) + { + for (int j = 0; j < previewTextures.Length; j++) + { + if (previewTextures[j] == null) continue; + var previewRect = new Rect(rect.x, rect.y + j * (RowHeight + RowSpacing), previewWidth, RowHeight); + EditorGUI.DrawPreviewTexture(previewRect, previewTextures[j]); + } + } + + // Draw button (stretches to cover all preview rows) + if (GUI.Button(buttonRect, guiContent, GUIStyles.rampSelectButton) && _switchRampEvent != null) + { + _switchRampEvent(_prop, i); + LwguiGradientWindow.CloseWindow(); + Close(); + } + + GUILayout.Space(RowSpacing); + } + + EditorGUILayout.EndScrollView(); + EditorGUILayout.EndVertical(); + } + + private void DrawRampMapSelector() { EditorGUILayout.BeginVertical(); _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition); @@ -305,26 +371,26 @@ namespace LWGUI for (int i = 0; i < _rampMaps.Length; i++) { var rampMap = _rampMaps[i]; - EditorGUILayout.BeginHorizontal(); - if (rampMap != null) + if (rampMap == null) continue; + + var rect = EditorGUILayout.GetControlRect(GUILayout.Height(RowHeight)); + var guiContent = new GUIContent($"{i}. {rampMap.name}"); + var buttonWidth = Mathf.Min(300f, Mathf.Max(GUI.skin.button.CalcSize(guiContent).x, rect.width * 0.35f)); + var buttonRect = new Rect(rect.x + rect.width - buttonWidth, rect.y, buttonWidth, RowHeight); + var previewRect = new Rect(rect.x, rect.y, rect.width - buttonWidth - 3.0f, RowHeight); + + EditorGUI.DrawPreviewTexture(previewRect, rampMap); + + if (GUI.Button(buttonRect, guiContent, GUIStyles.rampSelectButton) && _switchRampMapEvent != null) { - var guiContent = new GUIContent($"{ i }. { rampMap.name }"); - var rect = EditorGUILayout.GetControlRect(); - var buttonWidth = Mathf.Min(300f, Mathf.Max(GUI.skin.button.CalcSize(guiContent).x, rect.width * 0.35f)); - var buttonRect = new Rect(rect.x + rect.width - buttonWidth, rect.y, buttonWidth, rect.height); - var previewRect = new Rect(rect.x, rect.y, rect.width - buttonWidth - 3.0f, rect.height); - - if (GUI.Button(buttonRect, guiContent, Helper.guiStyle_RampSelectButton) && _switchRampMapEvent != null) - { - _switchRampMapEvent(_prop, rampMap, i); - LwguiGradientWindow.CloseWindow(); - Close(); - } - EditorGUI.DrawPreviewTexture(previewRect, rampMap); + _switchRampMapEvent(_prop, rampMap, i); + LwguiGradientWindow.CloseWindow(); + Close(); } - EditorGUILayout.EndHorizontal(); + + GUILayout.Space(RowSpacing); } - + EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RevertableHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RevertableHelper.cs index 0a9232262..dc16ec327 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RevertableHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/RevertableHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using System; using System.Linq; @@ -136,11 +136,24 @@ namespace LWGUI if (isHeader) { - foreach (var childStaticData in propStaticData.children) + RevertGroupChildren(propStaticData, metaDatas); + + // Reverting a group that contains a preset may change which preset is active, + // making the first-pass defaults stale. Re-init with fresh MaterialProperty + // objects to recalculate defaults, then re-revert to get correct final values. + // (Fresh props are needed because MaterialProperty.floatValue getter may + // return stale cached values after writes within the same GUI event.) + if (GroupContainsPreset(propStaticData)) { - DoRevertProperty(metaDatas.GetProperty(childStaticData.name), metaDatas); - foreach (var childChildStaticData in childStaticData.children) - DoRevertProperty(metaDatas.GetProperty(childChildStaticData.name), metaDatas); + var perMaterialData = metaDatas.perMaterialData; + var freshProps = MaterialEditor.GetMaterialProperties( + new UnityEngine.Object[] { perMaterialData.material }); + perMaterialData.InvalidateDefaultMaterialCache(); + perMaterialData.Init(metaDatas.GetShader(), perMaterialData.material, + metaDatas.GetMaterialEditor(), freshProps, metaDatas.perShaderData); + + DoRevertProperty(prop, metaDatas); + RevertGroupChildren(propStaticData, metaDatas); } } @@ -149,16 +162,43 @@ namespace LWGUI return false; } + private static void RevertGroupChildren(PropertyStaticData propStaticData, LWGUIMetaDatas metaDatas) + { + foreach (var childStaticData in propStaticData.children) + { + DoRevertProperty(metaDatas.GetProperty(childStaticData.name), metaDatas); + foreach (var childChildStaticData in childStaticData.children) + DoRevertProperty(metaDatas.GetProperty(childChildStaticData.name), metaDatas); + } + } + + private static bool GroupContainsPreset(PropertyStaticData propStaticData) + { + if (propStaticData.presetDrawer != null) + return true; + foreach (var child in propStaticData.children) + { + if (child.presetDrawer != null) + return true; + foreach (var grandchild in child.children) + { + if (grandchild.presetDrawer != null) + return true; + } + } + return false; + } + private static void DoRevertProperty(MaterialProperty prop, LWGUIMetaDatas metaDatas) { var propDynamicData = metaDatas.GetPropDynamicData(prop.name); propDynamicData.hasRevertChanged = true; - SetPropertyToDefault(propDynamicData.defualtProperty, prop); + SetPropertyToDefault(propDynamicData.defaultProperty, prop); foreach (var extraPropName in metaDatas.GetPropStaticData(prop.name).extraPropNames) { var extraPropDynamicData = metaDatas.GetPropDynamicData(extraPropName); extraPropDynamicData.hasRevertChanged = true; - SetPropertyToDefault(extraPropDynamicData.defualtProperty, extraPropDynamicData.property); + SetPropertyToDefault(extraPropDynamicData.defaultProperty, extraPropDynamicData.property); } } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ToolbarHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ToolbarHelper.cs new file mode 100644 index 000000000..088db86e6 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ToolbarHelper.cs @@ -0,0 +1,578 @@ +// Copyright (c) Jason Ma + +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; +using LWGUI.PerformanceMonitor; + +namespace LWGUI +{ + public static class ToolbarHelper + { + #region Toolbar Buttons + + internal enum CopyMaterialValueMask + { + Float = 1 << 0, + Vector = 1 << 1, + Texture = 1 << 2, + Keyword = 1 << 3, + RenderQueue = 1 << 4, + Number = Float | Vector, + All = (1 << 5) - 1, + } + + public const uint CopyMaterialValueMaskAll = (uint)CopyMaterialValueMask.All; + + private static GUIContent[] _pasteMaterialMenus = new[] + { + new GUIContent("Paste Number Values"), + new GUIContent("Paste Texture Values"), + new GUIContent("Paste Keywords"), + new GUIContent("Paste RenderQueue"), + }; + + private static uint[] _pasteMaterialMenuValueMasks = new[] + { + (uint)CopyMaterialValueMask.Number, + (uint)CopyMaterialValueMask.Texture, + (uint)CopyMaterialValueMask.Keyword, + (uint)CopyMaterialValueMask.RenderQueue, + }; + + + private const string _iconCopyGUID = "9cdef444d18d2ce4abb6bbc4fed4d109"; + private const string _iconPasteGUID = "8e7a78d02e4c3574998524a0842a8ccb"; + private const string _iconSelectGUID = "6f44e40b24300974eb607293e4224ecc"; + private const string _iconCheckoutGUID = "72488141525eaa8499e65e52755cb6d0"; + private const string _iconExpandGUID = "2382450e7f4ddb94c9180d6634c41378"; + private const string _iconCollapseGUID = "929b6e5dfacc42b429d715a3e1ca2b57"; + private const string _iconStatsGUID = "88909414120107547a673b8fcddc5236"; + private const string _iconVisibilityGUID = "9576e23a695b35d49a9fc55c9a948b4f"; + + private const string _iconCopyTooltip = "Copy Material Properties"; + private const string _iconPasteTooltip = "Paste Material Properties\n\nRight-click to paste values by type."; + private const string _iconSelectTooltip = "Select the Material Asset\n\nUsed to jump from a Runtime Material Instance to a Material Asset."; + private const string _iconCheckoutTooltip = "Checkout selected Material Assets"; + private const string _iconExpandTooltip = "Expand All Groups"; + private const string _iconCollapseTooltip = "Collapse All Groups"; + private const string _iconStatsTooltip = "Display Shader Performance Stats"; + private const string _iconVisibilityTooltip = "Display Mode"; + + private static GUIContent _guiContentCopyCache; + private static GUIContent _guiContentPasteCache; + private static GUIContent _guiContentSelectCache; + private static GUIContent _guiContentCheckoutCache; + private static GUIContent _guiContentExpandCache; + private static GUIContent _guiContentCollapseCache; + private static GUIContent _guiContentStatsCache; + private static GUIContent _guiContentVisibilityCache; + + private static GUIContent _guiContentCopy => _guiContentCopyCache = _guiContentCopyCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconCopyGUID)), _iconCopyTooltip); + private static GUIContent _guiContentPaste => _guiContentPasteCache = _guiContentPasteCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconPasteGUID)), _iconPasteTooltip); + private static GUIContent _guiContentSelect => _guiContentSelectCache = _guiContentSelectCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconSelectGUID)), _iconSelectTooltip); + private static GUIContent _guiContentChechout => _guiContentCheckoutCache = _guiContentCheckoutCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconCheckoutGUID)), _iconCheckoutTooltip); + private static GUIContent _guiContentExpand => _guiContentExpandCache = _guiContentExpandCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconExpandGUID)), _iconExpandTooltip); + private static GUIContent _guiContentCollapse => _guiContentCollapseCache = _guiContentCollapseCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconCollapseGUID)), _iconCollapseTooltip); + private static GUIContent _guiContentStats => _guiContentStatsCache = _guiContentStatsCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconStatsGUID)), _iconStatsTooltip); + private static GUIContent _guiContentVisibility => _guiContentVisibilityCache = _guiContentVisibilityCache ?? new GUIContent("", AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(_iconVisibilityGUID)), _iconVisibilityTooltip); + + + public static void DrawToolbarButtons(ref Rect toolBarRect, LWGUIMetaDatas metaDatas) + { + var (perShaderData, perMaterialData, perInspectorData) = metaDatas.GetDatas(); + var shader = metaDatas.GetShader(); + + //---------------------------------------------------------------------------------------------------------------- + // Copy + var buttonRectOffset = toolBarRect.height + 2; + var buttonRect = new Rect(toolBarRect.x, toolBarRect.y, toolBarRect.height, toolBarRect.height); + toolBarRect.xMin += buttonRectOffset; + if (GUI.Button(buttonRect, _guiContentCopy, GUIStyles.iconButton)) + { + ContextMenuHelper.CopyMaterial(metaDatas.GetMaterial()); + } + + //---------------------------------------------------------------------------------------------------------------- + // Paste + buttonRect.x += buttonRectOffset; + toolBarRect.xMin += buttonRectOffset; + // Right Click + if (Event.current.type == EventType.MouseDown + && Event.current.button == 1 + && buttonRect.Contains(Event.current.mousePosition)) + { + EditorUtility.DisplayCustomMenu(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0), _pasteMaterialMenus, -1, + (data, options, selected) => { ContextMenuHelper.PastePropertiesToMaterials(metaDatas, _pasteMaterialMenuValueMasks[selected]); }, null); + Event.current.Use(); + } + // Left Click + if (GUI.Button(buttonRect, _guiContentPaste, GUIStyles.iconButton)) + { + ContextMenuHelper.PastePropertiesToMaterials(metaDatas, (uint)CopyMaterialValueMask.All); + } + + //---------------------------------------------------------------------------------------------------------------- + // Select Material Asset, jump from a Runtime Material Instance to a Material Asset + buttonRect.x += buttonRectOffset; + toolBarRect.xMin += buttonRectOffset; + if (GUI.Button(buttonRect, _guiContentSelect, GUIStyles.iconButton)) + { + var material = metaDatas.GetMaterial(); + + if (AssetDatabase.Contains(material)) + { + Selection.activeObject = material; + } + else + { + if (FindMaterialAssetByMaterialInstance(material, metaDatas, out var materialAsset)) + { + Selection.activeObject = materialAsset; + } + } + } + + //---------------------------------------------------------------------------------------------------------------- + // Checkout + buttonRect.x += buttonRectOffset; + toolBarRect.xMin += buttonRectOffset; + if (GUI.Button(buttonRect, _guiContentChechout, GUIStyles.iconButton)) + { + VersionControlHelper.Checkout(metaDatas.GetMaterialEditor().targets); + } + + //---------------------------------------------------------------------------------------------------------------- + // Expand + buttonRect.x += buttonRectOffset; + toolBarRect.xMin += buttonRectOffset; + if (GUI.Button(buttonRect, _guiContentExpand, GUIStyles.iconButton)) + { + foreach (var propStaticDataKVPair in perShaderData.propStaticDatas) + { + if (propStaticDataKVPair.Value.isMain || propStaticDataKVPair.Value.isAdvancedHeader) + propStaticDataKVPair.Value.isExpanding = true; + } + } + + //---------------------------------------------------------------------------------------------------------------- + // Collapse + buttonRect.x += buttonRectOffset; + toolBarRect.xMin += buttonRectOffset; + if (GUI.Button(buttonRect, _guiContentCollapse, GUIStyles.iconButton)) + { + foreach (var propStaticDataKVPair in perShaderData.propStaticDatas) + { + if (propStaticDataKVPair.Value.isMain || propStaticDataKVPair.Value.isAdvancedHeader) + propStaticDataKVPair.Value.isExpanding = false; + } + } + + //---------------------------------------------------------------------------------------------------------------- + // Shader Perf Stats + buttonRect.x += buttonRectOffset; + toolBarRect.xMin += buttonRectOffset; + { + var color = GUI.color; + if (IsDisplayShaderPerfStatsEnabled(metaDatas.GetShaderUID())) + GUI.color = Color.yellow; + + if (GUI.Button(buttonRect, _guiContentStats, GUIStyles.iconButton)) + SwitchDisplayShaderPerfStatsEnabled(shader, metaDatas.GetShaderUID()); + + GUI.color = color; + } + + //---------------------------------------------------------------------------------------------------------------- + // Display Mode + buttonRect.x += buttonRectOffset; + toolBarRect.xMin += buttonRectOffset; + { + var color = GUI.color; + var displayModeData = perShaderData.displayModeData; + if (!displayModeData.IsDefaultDisplayMode()) + GUI.color = Color.yellow; + if (GUI.Button(buttonRect, _guiContentVisibility, GUIStyles.iconButton)) + { + // Build Display Mode Menu Items + var displayModeMenus = new[] + { + $"Show All Advanced Properties ({displayModeData.advancedCount} - {perShaderData.propStaticDatas.Count})", + $"Show All Hidden Properties ({displayModeData.hiddenCount} - {perShaderData.propStaticDatas.Count})", + $"Show Only Modified Properties ({perMaterialData.modifiedCount} - {perShaderData.propStaticDatas.Count})", + $"Show Only Modified Properties by Group ({perMaterialData.modifiedCount} - {perShaderData.propStaticDatas.Count})", + }; + var enabled = new[] { true, true, true, true }; + var separator = new bool[4]; + var selected = new[] + { + displayModeData.showAllAdvancedProperties ? 0 : -1, + displayModeData.showAllHiddenProperties ? 1 : -1, + displayModeData.showOnlyModifiedProperties ? 2 : -1, + displayModeData.showOnlyModifiedGroups ? 3 : -1, + }; + + + // Click Event + void OnSwitchDisplayMode(object data, string[] options, int selectedIndex) + { + switch (selectedIndex) + { + case 0: // Show All Advanced Properties + displayModeData.showAllAdvancedProperties = !displayModeData.showAllAdvancedProperties; + perShaderData.ToggleShowAllAdvancedProperties(); + break; + case 1: // Show All Hidden Properties + displayModeData.showAllHiddenProperties = !displayModeData.showAllHiddenProperties; + break; + case 2: // Show Only Modified Properties + displayModeData.showOnlyModifiedProperties = !displayModeData.showOnlyModifiedProperties; + if (displayModeData.showOnlyModifiedProperties) displayModeData.showOnlyModifiedGroups = false; + MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(shader); + break; + case 3: // Show Only Modified Groups + displayModeData.showOnlyModifiedGroups = !displayModeData.showOnlyModifiedGroups; + if (displayModeData.showOnlyModifiedGroups) displayModeData.showOnlyModifiedProperties = false; + MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(shader); + break; + } + } + + ReflectionHelper.DisplayCustomMenuWithSeparators(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0), + displayModeMenus, enabled, separator, selected, OnSwitchDisplayMode); + } + GUI.color = color; + } + + toolBarRect.xMin += 2; + } + + public static Func onFindMaterialAssetInRendererByMaterialInstance; + + public static bool FindMaterialAsset(LWGUIMetaDatas metaDatas, out Material materialAsset) + { + return FindMaterialAssetByMaterialInstance(metaDatas.GetMaterial(), metaDatas, out materialAsset); + } + + private static bool FindMaterialAssetByMaterialInstance(Material material, LWGUIMetaDatas metaDatas, out Material materialAsset) + { + materialAsset = null; + + var renderers = metaDatas.perInspectorData.materialEditor.GetMeshRenderersByMaterialEditor(); + foreach (var renderer in renderers) + { + if (onFindMaterialAssetInRendererByMaterialInstance != null) + { + materialAsset = onFindMaterialAssetInRendererByMaterialInstance(renderer, material); + } + + if (materialAsset == null) + { + int index = renderer.materials.ToList().FindIndex(materialInstance => materialInstance == material); + if (index >= 0 && index < renderer.sharedMaterials.Length) + { + materialAsset = renderer.sharedMaterials[index]; + } + } + + if (materialAsset != null && AssetDatabase.Contains(materialAsset)) + return true; + } + + Debug.LogError("LWGUI: Can not find the Material Assets of: " + material.name); + + return false; + } + + #endregion + + + #region Search Field + + private static readonly int s_TextFieldHash = "EditorTextField".GetHashCode(); + + private static readonly GUIContent[] _searchModeMenus = Enumerable.Range(0, (int)SearchMode.Num - 1).Select(i => + new GUIContent(((SearchMode)i).ToString())).ToArray(); + + /// is has changed? + public static bool DrawSearchField(Rect rect, LWGUIMetaDatas metaDatas) + { + var (perShaderData, perMaterialData, perInspectorData) = metaDatas.GetDatas(); + + bool hasChanged = false; + EditorGUI.BeginChangeCheck(); + + var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect); + + // Get internal TextField ControlID + int controlId = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, rect) + 1; + + // searching mode + Rect modeRect = new Rect(rect); + modeRect.width = 20f; + if (Event.current.type == UnityEngine.EventType.MouseDown && modeRect.Contains(Event.current.mousePosition)) + { + EditorUtility.DisplayCustomMenu(rect, _searchModeMenus, (int)perShaderData.searchMode, + (data, options, selected) => + { + perShaderData.searchMode = (SearchMode)selected; + hasChanged = true; + }, null); + Event.current.Use(); + } + + perShaderData.searchString = EditorGUI.TextField(rect, String.Empty, perShaderData.searchString, GUIStyles.toolbarSearchTextFieldPopup); + + if (EditorGUI.EndChangeCheck()) + hasChanged = true; + + // revert button + if (!string.IsNullOrEmpty(perShaderData.searchString) + && RevertableHelper.DrawRevertButton(revertButtonRect)) + { + perShaderData.searchString = string.Empty; + hasChanged = true; + GUIUtility.keyboardControl = 0; + } + + // display search mode + if (GUIUtility.keyboardControl != controlId + && string.IsNullOrEmpty(perShaderData.searchString) + && Event.current.type == UnityEngine.EventType.Repaint) + { + using (new EditorGUI.DisabledScope(true)) + { + var disableTextRect = new Rect(rect.x, rect.y, rect.width, + GUIStyles.toolbarSearchTextFieldPopup.fixedHeight > 0.0 + ? GUIStyles.toolbarSearchTextFieldPopup.fixedHeight + : rect.height); + disableTextRect = GUIStyles.toolbarSearchTextFieldPopup.padding.Remove(disableTextRect); + int fontSize = EditorStyles.label.fontSize; + EditorStyles.label.fontSize = GUIStyles.toolbarSearchTextFieldPopup.fontSize; + EditorStyles.label.Draw(disableTextRect, new GUIContent(perShaderData.searchMode.ToString()), false, false, false, false); + EditorStyles.label.fontSize = fontSize; + } + } + + if (hasChanged) perShaderData.UpdateSearchFilter(); + + return hasChanged; + } + + #endregion + + #region Shader Perf Stats + + #region Keyword Overrides + + private static string GetShowKeywordOverridesPreferenceKey(string shaderUID) => $"LWGUI/{shaderUID}/ShowKeywordOverrides"; + + private static string GetKeywordOverridePreferenceKey(string shaderUID, string keyword) => $"LWGUI/{shaderUID}/KeywordOverride/{keyword}/IsOverride"; + + private static string GetKeywordEnabledPreferenceKey(string shaderUID, string keyword) => $"LWGUI/{shaderUID}/KeywordOverride/{keyword}/IsEnabled"; + + private static bool IsShowKeywordOverridesEnabled(string shaderUID) => EditorPrefs.GetBool(GetShowKeywordOverridesPreferenceKey(shaderUID), false); + + public static bool IsUserKeywordOverride(string shaderUID, string keyword) => EditorPrefs.HasKey(GetKeywordOverridePreferenceKey(shaderUID, keyword)); + + public static bool IsUserKeywordEnabled(string shaderUID, string keyword) => EditorPrefs.GetBool(GetKeywordEnabledPreferenceKey(shaderUID, keyword), false); + + private static void SetShowKeywordOverridesEnabled(string shaderUID, bool enabled) + { + if (enabled) + EditorPrefs.SetBool(GetShowKeywordOverridesPreferenceKey(shaderUID), true); + else + EditorPrefs.DeleteKey(GetShowKeywordOverridesPreferenceKey(shaderUID)); + } + + private static void SetUserKeywordOverride(Shader shader, string shaderUID, string keyword, bool isOverride) + { + var overrideKey = GetKeywordOverridePreferenceKey(shaderUID, keyword); + + if (isOverride) + EditorPrefs.SetBool(overrideKey, true); + else + EditorPrefs.DeleteKey(overrideKey); + + MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(shader); + } + + private static void SetUserKeywordEnabled(Shader shader, string shaderUID, string keyword, bool isEnabled) + { + EditorPrefs.SetBool(GetKeywordEnabledPreferenceKey(shaderUID, keyword), isEnabled); + MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(shader); + } + + private static void DrawKeywordOverridesList(LWGUIMetaDatas metaDatas) + { + var shader = metaDatas.GetShader(); + var shaderUID = metaDatas.GetShaderUID(); + if (!shader) return; + + var showKeywordOverrides = IsShowKeywordOverridesEnabled(shaderUID); + + EditorGUI.indentLevel++; + var newShowKeywordOverrides = EditorGUILayout.Foldout(showKeywordOverrides, "Keyword Overrides"); + if (newShowKeywordOverrides != showKeywordOverrides) + SetShowKeywordOverridesEnabled(shaderUID, newShowKeywordOverrides); + if (newShowKeywordOverrides) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Enabled"); + EditorGUILayout.LabelField(" Override"); + EditorGUILayout.EndHorizontal(); + + var activeKeywords = metaDatas.perMaterialData.activeKeywords; + var allKeywords = shader.keywordSpace.keywords.Select(k => k.name).ToList(); + foreach (var keyword in allKeywords) + { + var rect = EditorGUILayout.BeginHorizontal(); + + // Context Menu + if (Event.current.type == EventType.ContextClick && rect.Contains(Event.current.mousePosition)) + { + Event.current.Use(); + var menu = new GenericMenu(); + menu.AddItem(new GUIContent("Copy Keyword"), false, () => + { + EditorGUIUtility.systemCopyBuffer = keyword; + }); + menu.ShowAsContext(); + } + + bool currentOverride = IsUserKeywordOverride(shaderUID, keyword); + bool currentEnabled = currentOverride ? IsUserKeywordEnabled(shaderUID, keyword) : activeKeywords.Contains(keyword); + + using (new EditorGUI.DisabledGroupScope(!currentOverride)) + { + var newEnabled = EditorGUILayout.ToggleLeft(keyword, currentEnabled); + if (newEnabled != currentEnabled) + SetUserKeywordEnabled(shader, shaderUID, keyword, newEnabled); + } + + bool newOverride = EditorGUILayout.Toggle(string.Empty, currentOverride); + if (newOverride != currentOverride) + SetUserKeywordOverride(shader, shaderUID, keyword, newOverride); + + EditorGUILayout.EndHorizontal(); + } + } + EditorGUI.indentLevel--; + } + + #endregion + + #region Compiler Settings + + private static string GetShowCompilerSettingsPreferenceKey(string shaderUID) => $"LWGUI/{shaderUID}/ShowCompilerSettings"; + private static bool IsShowCompilerSettingsEnabled(string shaderUID) => EditorPrefs.GetBool(GetShowCompilerSettingsPreferenceKey(shaderUID), false); + private static void SetShowCompilerSettingsEnabled(string shaderUID, bool enabled) + { + if (enabled) + EditorPrefs.SetBool(GetShowCompilerSettingsPreferenceKey(shaderUID), true); + else + EditorPrefs.DeleteKey(GetShowCompilerSettingsPreferenceKey(shaderUID)); + } + + private static void DrawCompilerSettings(LWGUIMetaDatas metaDatas) + { + var shaderUID = metaDatas.GetShaderUID(); + var showCompilerSettings = IsShowCompilerSettingsEnabled(shaderUID); + + EditorGUI.indentLevel++; + var newShowCompilerSettings = EditorGUILayout.Foldout(showCompilerSettings, "Compiler Settings"); + if (newShowCompilerSettings != showCompilerSettings) + SetShowCompilerSettingsEnabled(shaderUID, newShowCompilerSettings); + if (newShowCompilerSettings) + { + if (GUILayout.Button("Install Mali Offline Compiler", GUILayout.ExpandWidth(false))) + { + Application.OpenURL("https://developer.arm.com/documentation/101863/8-8/Using-Mali-Offline-Compiler/Install-Mali-Offline-Compiler"); + } + } + EditorGUI.indentLevel--; + } + + #endregion + private static string GetDisplayShaderPerfStatsPreferenceKey(string shaderUID) => $"LWGUI/{shaderUID}/DisplayShaderPerformanceStats"; + + public static bool IsDisplayShaderPerfStatsEnabled(string shaderUID) => EditorPrefs.HasKey(GetDisplayShaderPerfStatsPreferenceKey(shaderUID)); + + public static void SetDisplayShaderPerfStatsEnabled(Shader shader, string shaderUID, bool enabled) + { + if (enabled) + EditorPrefs.SetBool(GetDisplayShaderPerfStatsPreferenceKey(shaderUID), true); + else + EditorPrefs.DeleteKey(GetDisplayShaderPerfStatsPreferenceKey(shaderUID)); + MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(shader); + } + + public static void SwitchDisplayShaderPerfStatsEnabled(Shader shader, string shaderUID) + { + var key = GetDisplayShaderPerfStatsPreferenceKey(shaderUID); + if (EditorPrefs.HasKey(key)) + EditorPrefs.DeleteKey(key); + else + EditorPrefs.SetBool(key, true); + MetaDataHelper.ForceUpdateAllMaterialsMetadataCache(shader); + } + + public static void DrawShaderPerformanceStats(LWGUIMetaDatas metaDatas) + { + if (!IsDisplayShaderPerfStatsEnabled(metaDatas.GetShaderUID()) || metaDatas.perMaterialData.shaderPerfDatas == null) + return; + + var fieldWidth = EditorGUIUtility.fieldWidth; + EditorGUIUtility.fieldWidth = 0; + + var compiler = ShaderPerfMonitor.GetActiveCompiler(); + if (compiler != null) + EditorGUILayout.LabelField($"Shader Performance Stats (Compiler: {compiler?.compilerName ?? "NULL"}, API: {compiler.api}, Target: {compiler.target})", GUIStyles.title); + else + EditorGUILayout.LabelField($"Shader Performance Stats (Compiler: NULL)", GUIStyles.title); + + if (compiler != null) + { + DrawCompilerSettings(metaDatas); + DrawKeywordOverridesList(metaDatas); + compiler.DrawShaderPerformanceStatsHeader(metaDatas); + + var lastPassName = string.Empty; + foreach (var shaderPerfData in metaDatas.perMaterialData.shaderPerfDatas) + { + if (lastPassName == string.Empty) + lastPassName = shaderPerfData.passName; + + if (lastPassName != shaderPerfData.passName) + { + lastPassName = shaderPerfData.passName; + EditorGUILayout.Space(); + } + + compiler.DrawShaderPerformanceStatsLine(metaDatas, shaderPerfData); + } + compiler.DrawShaderPerformanceStatsFooter(metaDatas); + } + else + { + Debug.LogError("LWGUI: Can NOT get Shader Compiler!"); + } + + EditorGUIUtility.fieldWidth = fieldWidth; + EditorGUILayout.Space(); + Helper.DrawSplitLine(); + } + + + public static void DrawShaderPerformanceStatsLineButtons(ShaderPerfData shaderPerfData) + { + if (GUILayout.Button("Find", GUILayout.MaxWidth(40))) + EditorUtility.RevealInFinder(shaderPerfData.compiledShaderPath); + // if (GUILayout.Button("Open", GUILayout.MaxWidth(40))) + // IOHelper.OpenFile(shaderPerfData.compiledShaderPath); + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ToolbarHelper.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ToolbarHelper.cs.meta new file mode 100644 index 000000000..d546365fa --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Helper/ToolbarHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a055ea55b4f0432d872562e7c2e2c296 +timeCreated: 1760781507 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Checkout.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Checkout.png.meta index 424b9b744..7646e6f85 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Checkout.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Checkout.png.meta @@ -1,13 +1,13 @@ fileFormatVersion: 2 guid: 72488141525eaa8499e65e52755cb6d0 TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -20,7 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -51,21 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - - buildTarget: Standalone + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -74,13 +90,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Collapse.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Collapse.png.meta index 2f33681d9..816fce945 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Collapse.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Collapse.png.meta @@ -1,13 +1,13 @@ fileFormatVersion: 2 guid: 929b6e5dfacc42b429d715a3e1ca2b57 TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -20,7 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -51,21 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - - buildTarget: Standalone + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -74,13 +90,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Copy.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Copy.png.meta index 5c9c2d2d4..4d3cedd2b 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Copy.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Copy.png.meta @@ -1,13 +1,13 @@ fileFormatVersion: 2 guid: 9cdef444d18d2ce4abb6bbc4fed4d109 TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -20,7 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -51,21 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - - buildTarget: Standalone + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -74,13 +90,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Expand.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Expand.png.meta index c29152005..7c699658d 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Expand.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Expand.png.meta @@ -1,13 +1,13 @@ fileFormatVersion: 2 guid: 2382450e7f4ddb94c9180d6634c41378 TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -20,7 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -51,21 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - - buildTarget: Standalone + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -74,13 +90,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo.png.meta index a7924caa8..a96b35e76 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo.png.meta @@ -3,7 +3,7 @@ guid: 2a220687c380819438534e206c94960d TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 11 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 @@ -20,11 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMasterTextureLimit: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -63,10 +64,12 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 8192 + maxTextureSize: 256 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -74,6 +77,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -86,6 +90,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -98,6 +103,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -110,6 +116,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -122,6 +129,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -134,6 +142,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -150,9 +159,8 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - spritePackingTag: + mipmapLimitGroupName: pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo2.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo2.png.meta index 7f60efbb9..b71de770a 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo2.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Logo2.png.meta @@ -1,14 +1,13 @@ fileFormatVersion: 2 guid: 26b9d845eb7b1a747bf04dc84e5bcc2c TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 - mipMapLayout: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -21,8 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 1 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -31,12 +34,12 @@ TextureImporter: maxTextureSize: 2048 textureSettings: serializedVersion: 2 - filterMode: -1 + filterMode: 1 aniso: 1 - mipBias: -1 + mipBias: 0 wrapU: 1 wrapV: 1 - wrapW: -1 + wrapW: 0 nPOTScale: 0 lightmap: 0 compressionQuality: 50 @@ -53,11 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -66,9 +90,11 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 - platformFilterMode: 1 - - buildTarget: Standalone + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -77,9 +103,11 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 - platformFilterMode: 1 - - buildTarget: iPhone + forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: tvOS maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -88,9 +116,11 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 - platformFilterMode: 1 - - buildTarget: tvOS + forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: Android maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -99,9 +129,11 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 - platformFilterMode: 1 - - buildTarget: Android + forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: WebGL maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -110,9 +142,11 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 - platformFilterMode: 1 - - buildTarget: WebGL + forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: PS4 maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -121,27 +155,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 - platformFilterMode: 1 - - buildTarget: PS4 - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - platformFilterMode: 1 + forceMaximumCompressionQuality_BC6H_BC7: 1 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: - useMipMapOverrideTexture: 0 - mipMapOverrideTextureNames: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Paste.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Paste.png.meta index 539397984..3dae93ee1 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Paste.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Paste.png.meta @@ -1,13 +1,13 @@ fileFormatVersion: 2 guid: 8e7a78d02e4c3574998524a0842a8ccb TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -20,7 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -51,21 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - - buildTarget: Standalone + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -74,13 +90,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/RevertIcon.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/RevertIcon.png.meta index 7141f6aa9..63a58704f 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/RevertIcon.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/RevertIcon.png.meta @@ -3,7 +3,7 @@ guid: e7bc1130858d984488bca32b8512ca96 TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 11 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 @@ -20,11 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMasterTextureLimit: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -63,10 +64,12 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 8192 + maxTextureSize: 128 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -74,6 +77,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -86,6 +90,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -98,6 +103,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -110,6 +116,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -122,6 +129,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -134,6 +142,7 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -150,9 +159,8 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - spritePackingTag: + mipmapLimitGroupName: pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/SelectMaterialAsset.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/SelectMaterialAsset.png.meta index f58d807b6..28d417aaa 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/SelectMaterialAsset.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/SelectMaterialAsset.png.meta @@ -1,13 +1,13 @@ fileFormatVersion: 2 guid: 6f44e40b24300974eb607293e4224ecc TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -20,7 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -51,21 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - - buildTarget: Standalone + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -74,13 +90,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Stats.png b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Stats.png new file mode 100644 index 000000000..71b6bc0d9 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Stats.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dad5572032521d7305b51bf975e939cae82118e5b36f7a8682ac9c1a80e2396b +size 1959 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Stats.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Stats.png.meta new file mode 100644 index 000000000..e41687cc7 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Stats.png.meta @@ -0,0 +1,114 @@ +fileFormatVersion: 2 +guid: 88909414120107547a673b8fcddc5236 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Visibility.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Visibility.png.meta index 8e9762073..a9676f2d1 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Visibility.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Icon/Visibility.png.meta @@ -1,13 +1,13 @@ fileFormatVersion: 2 guid: 9576e23a695b35d49a9fc55c9a948b4f TextureImporter: - fileIDToRecycleName: {} + internalIDToNameTable: [] externalObjects: {} - serializedVersion: 4 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 - sRGBTexture: 0 + sRGBTexture: 1 linearTexture: 0 fadeOut: 0 borderMipMap: 0 @@ -20,7 +20,12 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 + flipGreenChannel: 0 isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -29,12 +34,12 @@ TextureImporter: maxTextureSize: 2048 textureSettings: serializedVersion: 2 - filterMode: -1 + filterMode: 1 aniso: 1 - mipBias: -1 + mipBias: 0 wrapU: 1 wrapV: 1 - wrapW: -1 + wrapW: 0 nPOTScale: 0 lightmap: 0 compressionQuality: 50 @@ -51,21 +56,32 @@ TextureImporter: spriteTessellationDetail: -1 textureType: 2 textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 maxTextureSizeSet: 0 compressionQualitySet: 0 textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 1 + swizzle: 50462976 + cookieLightType: 1 platformSettings: - - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - - buildTarget: Standalone + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 128 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone maxTextureSize: 2048 resizeAlgorithm: 0 textureFormat: -1 @@ -74,13 +90,25 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 + ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] outline: [] physicsShape: [] - spritePackingTag: + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.asmdef b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.asmdef index 16cf91385..a97a4299e 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.asmdef +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.asmdef @@ -4,7 +4,8 @@ "references": [ "LWGUI.Runtime", "LWGUI.Timeline", - "Unity.InternalAPIEditorBridge.020" + "Unity.InternalAPIEditorBridge.020", + "LWGUI.Runtime.Timeline" ], "includePlatforms": [ "Editor" diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.cs index 4e603a6ea..f495817ab 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/LWGUI.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using UnityEditor; using UnityEngine; @@ -7,6 +7,7 @@ using UnityEngine.Rendering; namespace LWGUI { public delegate void LWGUICustomGUIEvent(LWGUI lwgui); + public delegate void LWGUIToolbarExtensionEvent(LWGUI lwgui, ref Rect toolBarRect); public class LWGUI : ShaderGUI { @@ -15,6 +16,8 @@ namespace LWGUI public static LWGUICustomGUIEvent onDrawCustomHeader; public static LWGUICustomGUIEvent onDrawCustomFooter; + public static LWGUIToolbarExtensionEvent onDrawToolbarLeft; + public static LWGUIToolbarExtensionEvent onDrawToolbarRight; /// /// Called when switch to a new Material Window, each window has a LWGUI instance @@ -44,19 +47,24 @@ namespace LWGUI onDrawCustomHeader(this); // Toolbar - bool enabled = GUI.enabled; - GUI.enabled = true; - var toolBarRect = EditorGUILayout.GetControlRect(); - toolBarRect.xMin = 2; + { + bool enabled = GUI.enabled; + GUI.enabled = true; + var toolBarRect = EditorGUILayout.GetControlRect(); + toolBarRect.xMin = 2; - Helper.DrawToolbarButtons(ref toolBarRect, metaDatas); + onDrawToolbarLeft?.Invoke(this, ref toolBarRect); + ToolbarHelper.DrawToolbarButtons(ref toolBarRect, metaDatas); + onDrawToolbarRight?.Invoke(this, ref toolBarRect); + ToolbarHelper.DrawSearchField(toolBarRect, metaDatas); - Helper.DrawSearchField(toolBarRect, metaDatas); - - GUILayoutUtility.GetRect(0, 0); // Space(0) - GUI.enabled = enabled; - Helper.DrawSplitLine(); + GUILayoutUtility.GetRect(0, 0); // Space(0) + GUI.enabled = enabled; + Helper.DrawSplitLine(); + ToolbarHelper.DrawShaderPerformanceStats(metaDatas); + } + //----------------------------------------------------------------------------- // Draw Properties @@ -147,7 +155,7 @@ namespace LWGUI if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && rect.Contains(Event.current.mousePosition)) propStaticData.isExpanding = !propStaticData.isExpanding; RevertableHelper.DrawRevertableProperty(revertButtonRect, prop, metaDatas, true); - Helper.DoPropertyContextMenus(rect, prop, metaDatas); + ContextMenuHelper.DoPropertyContextMenus(rect, prop, metaDatas); } private void DrawProperty(MaterialProperty prop) @@ -167,9 +175,10 @@ namespace LWGUI var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect); var enabled = GUI.enabled; - if (propStaticData.isReadOnly) GUI.enabled = false; + if (propStaticData.isReadOnly || !propDynamicData.isActive) + GUI.enabled = false; Helper.BeginProperty(rect, prop, metaDatas); - Helper.DoPropertyContextMenus(rect, prop, metaDatas); + ContextMenuHelper.DoPropertyContextMenus(rect, prop, metaDatas); RevertableHelper.FixGUIWidthMismatch(prop.GetPropertyType(), materialEditor); if (propStaticData.isAdvancedHeaderProperty) @@ -229,5 +238,19 @@ namespace LWGUI if (!hasChange) hasChange = true; } } + + [MenuItem("CONTEXT/Material/Reimport Shader", false, 100)] + static void MenuItem_ReimportShader(MenuCommand command) + { + var mat = command.context as Material; + if (mat != null) + { + var path = AssetDatabase.GetAssetPath(mat.shader); + if (!string.IsNullOrEmpty(path)) + { + AssetDatabase.ImportAsset(path); + } + } + } } } \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerMaterialData.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerMaterialData.cs index 3b6ecceed..178bb484b 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerMaterialData.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerMaterialData.cs @@ -1,212 +1,273 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma // Per Shader > Per Material > Per Inspector using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; +using LWGUI.PerformanceMonitor; namespace LWGUI { - public class PersetDynamicData - { - public LwguiShaderPropertyPreset.Preset preset; - public MaterialProperty property; + public class PresetDynamicData + { + public LwguiShaderPropertyPreset.Preset preset; + public MaterialProperty property; - public PersetDynamicData(LwguiShaderPropertyPreset.Preset preset, MaterialProperty property) - { - this.preset = preset; - this.property = property; - } - } + public PresetDynamicData(LwguiShaderPropertyPreset.Preset preset, MaterialProperty property) + { + this.preset = preset; + this.property = property; + } + } - public class PropertyDynamicData - { - public MaterialProperty property; - public MaterialProperty defualtProperty; // Default values may be overridden by Preset + public class PropertyDynamicData + { + public MaterialProperty property; + public MaterialProperty defaultProperty; // Default values may be overridden by Preset - public string defaultValueDescription = string.Empty; // Description of the default values used in Tooltip - public bool hasModified = false; // Are properties modified in the material? - public bool hasChildrenModified = false; // Are Children properties modified in the material? - public bool hasRevertChanged = false; // Used to call property EndChangeCheck() - public bool isShowing = true; // ShowIf() result - public bool isAnimated = false; // Material Parameter Animation preview in Timeline is activated - } + public string defaultValueDescription = string.Empty; // Description of the default values used in Tooltip + public bool hasModified = false; // Are properties modified in the material? + public bool hasChildrenModified = false; // Are Children properties modified in the material? + public bool hasRevertChanged = false; // Used to call property EndChangeCheck() + public bool isShowing = true; // ShowIf() result + public bool isActive = true; // ActiveIf() result + public bool isAnimated = false; // Material Parameter Animation preview in Timeline is activated + } - /// - /// Contains Metadata that may be different for each Material. - /// - public class PerMaterialData - { - public Dictionary propDynamicDatas = new Dictionary(); - public MaterialProperty[] props = null; - public Material material = null; - public Material defaultMaterialWithPresetOverride = null; - public MaterialProperty[] defaultPropertiesWithPresetOverride = null; - public List activePresetDatas = new List(); - public int modifiedCount = 0; - public Dictionary cachedModifiedProperties = null; - public bool forceInit = true; + /// + /// Contains Metadata that may be different for each Material. + /// + public class PerMaterialData + { + public bool forceInit = true; + public Material material = null; + public MaterialProperty[] props = null; + public Dictionary propDynamicDatas = new Dictionary(); - public PerMaterialData(Shader shader, Material material, MaterialEditor editor, MaterialProperty[] props, PerShaderData perShaderData) - { - Init(shader, material, editor, props, perShaderData); - } + public Material defaultMaterialWithPresetOverride = null; + public MaterialProperty[] defaultPropertiesWithPresetOverride = null; + public List activePresetDatas = new List(); + public int modifiedCount = 0; + public Dictionary cachedModifiedProperties = null; - public void Init(Shader shader, Material material, MaterialEditor editor, MaterialProperty[] props, PerShaderData perShaderData) - { - forceInit = false; + // Performance Monitor + public List activeKeywords = null; + public List shaderPerfDatas = null; - // Reset Datas - this.props = props; - this.material = material; - activePresetDatas.Clear(); - propDynamicDatas.Clear(); - modifiedCount = 0; + public PerMaterialData(Shader shader, Material material, MaterialEditor editor, MaterialProperty[] props, PerShaderData perShaderData) + { + Init(shader, material, editor, props, perShaderData); + } - // Get active presets - foreach (var prop in props) - { - var propStaticData = perShaderData.propStaticDatas[prop.name]; - var activePreset = propStaticData.presetDrawer?.GetActivePreset(prop, propStaticData.propertyPresetAsset); - if (activePreset != null - // Filter invisible preset properties - && (propStaticData.showIfDatas.Count == 0 - || ShowIfDecorator.GetShowIfResultFromMaterial(propStaticData.showIfDatas, this.material))) - { - activePresetDatas.Add(new PersetDynamicData(activePreset, prop)); - } - } + // Signature of the cached default material: which presets and which base material were used to build it. + // Compared each Init() to auto-detect preset switching, material.parent changes, etc. + private List _cachedActivePresets; + private Material _cachedDefaultMaterialSource; - { - // Apply presets to default material - defaultMaterialWithPresetOverride = UnityEngine.Object.Instantiate( + private bool IsDefaultMaterialCacheValid(Material baseMaterial) + { + if (defaultMaterialWithPresetOverride == null || _cachedActivePresets == null) + return false; + if (_cachedDefaultMaterialSource != baseMaterial) + return false; + if (_cachedActivePresets.Count != activePresetDatas.Count) + return false; + for (int i = 0; i < _cachedActivePresets.Count; i++) + { + if (_cachedActivePresets[i] != activePresetDatas[i].preset) + return false; + } + return true; + } + + private void StoreDefaultMaterialCacheSignature(Material baseMaterial) + { + _cachedDefaultMaterialSource = baseMaterial; + if (_cachedActivePresets == null) + _cachedActivePresets = new List(activePresetDatas.Count); + else + _cachedActivePresets.Clear(); + for (int i = 0; i < activePresetDatas.Count; i++) + _cachedActivePresets.Add(activePresetDatas[i].preset); + } + + public void Init(Shader shader, Material material, MaterialEditor editor, MaterialProperty[] props, PerShaderData perShaderData) + { + forceInit = false; + + // Reset Datas + this.props = props; + this.material = material; + activePresetDatas.Clear(); + propDynamicDatas.Clear(); + modifiedCount = 0; + + // Get active presets + foreach (var prop in props) + { + var propStaticData = perShaderData.propStaticDatas[prop.name]; + var activePreset = propStaticData.presetDrawer?.GetActivePreset(prop, propStaticData.propertyPresetAsset); + if (activePreset != null + // Filter invisible preset properties + && (propStaticData.showIfDatas.Count == 0 + || ShowIfDecorator.GetShowIfResultFromMaterial(propStaticData.showIfDatas, this.material))) + { + activePresetDatas.Add(new PresetDynamicData(activePreset, prop)); + } + } + + { + var baseMaterial = #if UNITY_2022_1_OR_NEWER - material.parent - ? material.parent - : + material.parent + ? material.parent + : #endif - perShaderData.defaultMaterial - ); + perShaderData.defaultMaterial; - foreach (var activePresetData in activePresetDatas) - activePresetData.preset.ApplyToDefaultMaterial(defaultMaterialWithPresetOverride); + var cacheWasValid = IsDefaultMaterialCacheValid(baseMaterial); + if (!cacheWasValid) + { + defaultMaterialWithPresetOverride = UnityEngine.Object.Instantiate(baseMaterial); - defaultPropertiesWithPresetOverride = MaterialEditor.GetMaterialProperties(new[] { defaultMaterialWithPresetOverride }); - Debug.Assert(defaultPropertiesWithPresetOverride.Length == props.Length); + foreach (var activePresetData in activePresetDatas) + activePresetData.preset.ApplyToDefaultMaterial(defaultMaterialWithPresetOverride); - // Init propDynamicDatas - for (int i = 0; i < props.Length; i++) - { - var hasModified = !Helper.PropertyValueEquals(props[i], defaultPropertiesWithPresetOverride[i]); - if (hasModified) modifiedCount++; - propDynamicDatas.Add(props[i].name, new PropertyDynamicData() - { - property = props[i], - defualtProperty = defaultPropertiesWithPresetOverride[i], - hasModified = hasModified - }); - } + defaultPropertiesWithPresetOverride = MaterialEditor.GetMaterialProperties(new Object[] { defaultMaterialWithPresetOverride }); + StoreDefaultMaterialCacheSignature(baseMaterial); + } - // Collect modification - foreach (var prop in props) - { - var propStaticData = perShaderData.propStaticDatas[prop.name]; - var propDynamicData = propDynamicDatas[prop.name]; + Debug.Assert(defaultPropertiesWithPresetOverride.Length == props.Length); - // Extra Prop hasModified - foreach (var extraPropName in propStaticData.extraPropNames) - propDynamicData.hasModified |= propDynamicDatas[extraPropName].hasModified; + // Init propDynamicDatas + for (int i = 0; i < props.Length; i++) + { + var hasModified = !Helper.PropertyValueEquals(props[i], defaultPropertiesWithPresetOverride[i]); + if (hasModified) modifiedCount++; + propDynamicDatas.Add(props[i].name, new PropertyDynamicData() + { + property = props[i], + defaultProperty = defaultPropertiesWithPresetOverride[i], + hasModified = hasModified + }); + } - // Override parent hasChildrenModified - if (propDynamicData.hasModified) - { - var parentPropData = propStaticData.parent; - if (parentPropData != null) - { - propDynamicDatas[parentPropData.name].hasChildrenModified = true; - if (parentPropData.parent != null) - propDynamicDatas[parentPropData.parent.name].hasChildrenModified = true; - } - } - } - } + // Collect modification + foreach (var prop in props) + { + var propStaticData = perShaderData.propStaticDatas[prop.name]; + var propDynamicData = propDynamicDatas[prop.name]; - // Store "Show Modified Props Only" Caches - { - if (perShaderData.displayModeData.showOnlyModifiedGroups || perShaderData.displayModeData.showOnlyModifiedProperties) - { - if (cachedModifiedProperties == null) - { - cachedModifiedProperties = new Dictionary(); - foreach (var propDynamicDataKWPair in propDynamicDatas) - { - if (propDynamicDataKWPair.Value.hasModified || propDynamicDataKWPair.Value.hasChildrenModified) - cachedModifiedProperties.Add(propDynamicDataKWPair.Key, true); - } - } - } - else - cachedModifiedProperties = null; - } + // Extra Prop hasModified + foreach (var extraPropName in propStaticData.extraPropNames) + propDynamicData.hasModified |= propDynamicDatas[extraPropName].hasModified; - foreach (var prop in props) - { - var propStaticData = perShaderData.propStaticDatas[prop.name]; - var propDynamicData = propDynamicDatas[prop.name]; + // Override parent hasChildrenModified + if (propDynamicData.hasModified) + { + var parentPropData = propStaticData.parent; + if (parentPropData != null) + { + propDynamicDatas[parentPropData.name].hasChildrenModified = true; + if (parentPropData.parent != null) + propDynamicDatas[parentPropData.parent.name].hasChildrenModified = true; + } + } + } + } - // Get default value descriptions - propStaticData.baseDrawers?.ForEach(propertyDrawer => propertyDrawer.GetDefaultValueDescription(shader, prop, propDynamicData.defualtProperty, perShaderData, this)); - if (string.IsNullOrEmpty(propDynamicData.defaultValueDescription)) - propDynamicData.defaultValueDescription = RevertableHelper.GetPropertyDefaultValueText(propDynamicData.defualtProperty); + // Store "Show Modified Props Only" Caches + { + if (perShaderData.displayModeData.showOnlyModifiedGroups || perShaderData.displayModeData.showOnlyModifiedProperties) + { + if (cachedModifiedProperties == null) + { + cachedModifiedProperties = new Dictionary(); + foreach (var propDynamicDataKWPair in propDynamicDatas) + { + if (propDynamicDataKWPair.Value.hasModified || propDynamicDataKWPair.Value.hasChildrenModified) + cachedModifiedProperties.Add(propDynamicDataKWPair.Key, true); + } + } + } + else + cachedModifiedProperties = null; + } - // Get ShowIf() results - ShowIfDecorator.GetShowIfResult(propStaticData, propDynamicData, this); - } - } + foreach (var prop in props) + { + var propStaticData = perShaderData.propStaticDatas[prop.name]; + var propDynamicData = propDynamicDatas[prop.name]; - public void Update(Shader shader, Material material, MaterialEditor editor, MaterialProperty[] props, PerShaderData perShaderData) - { - if (forceInit) - { - Init(shader, material, editor, props, perShaderData); - } - else - { - foreach (var prop in props) - { - propDynamicDatas[prop.name].property = prop; - } - } - - // Check animated - var renderer = editor.GetRendererForAnimationMode(); - if (renderer != null) - { - forceInit = true; - foreach (var prop in props) - { - ReflectionHelper.MaterialAnimationUtility_OverridePropertyColor(prop, renderer, out var color); - if (color != Color.white) - propDynamicDatas[prop.name].isAnimated = true; - } - } - } + // Get default value descriptions + propStaticData.baseDrawers?.ForEach(propertyDrawer => propertyDrawer.GetDefaultValueDescription(shader, prop, propDynamicData.defaultProperty, perShaderData, this)); + if (string.IsNullOrEmpty(propDynamicData.defaultValueDescription)) + propDynamicData.defaultValueDescription = RevertableHelper.GetPropertyDefaultValueText(propDynamicData.defaultProperty); - public bool EndChangeCheck(string propName = null) - { - if (!string.IsNullOrEmpty(propName)) - { - GUI.changed |= propDynamicDatas[propName].hasRevertChanged; - propDynamicDatas[propName].hasRevertChanged = false; - } - return EditorGUI.EndChangeCheck(); - } + // Get ShowIf() results + ShowIfDecorator.GetShowIfResult(propStaticData, propDynamicData, this); + + // Get ActiveIf() results + if (propStaticData.activeIfDatas.Count > 0) + propDynamicData.isActive = ShowIfDecorator.GetShowIfResultFromMaterial(propStaticData.activeIfDatas, this.material); + } - public PropertyDynamicData GetPropDynamicData(string propName) - { - propDynamicDatas.TryGetValue(propName, out var propDynamicData); - return propDynamicData; - } - } + // Get Shader Perf Stats + if (ToolbarHelper.IsDisplayShaderPerfStatsEnabled(perShaderData.shaderUID)) + { + activeKeywords = ShaderPerfMonitor.GetMaterialAndGlobalAndUserOverrideActiveKeywords(material, perShaderData.shaderUID); + shaderPerfDatas = ShaderPerfMonitor.GetShaderVariantPerfDatas(shader, activeKeywords); + } + } + + public void InvalidateDefaultMaterialCache() + { + _cachedActivePresets = null; + } + + public void Update(Shader shader, Material material, MaterialEditor editor, MaterialProperty[] props, PerShaderData perShaderData) + { + if (forceInit) + { + Init(shader, material, editor, props, perShaderData); + } + else + { + foreach (var prop in props) + { + propDynamicDatas[prop.name].property = prop; + } + } + + // Check animated + var renderer = editor.GetRendererForAnimationMode(); + if (renderer != null) + { + forceInit = true; + foreach (var prop in props) + { + ReflectionHelper.MaterialAnimationUtility_OverridePropertyColor(prop, renderer, out var color); + if (color != Color.white) + propDynamicDatas[prop.name].isAnimated = true; + } + } + } + + public bool EndChangeCheck(string propName = null) + { + if (!string.IsNullOrEmpty(propName)) + { + GUI.changed |= propDynamicDatas[propName].hasRevertChanged; + propDynamicDatas[propName].hasRevertChanged = false; + } + return EditorGUI.EndChangeCheck(); + } + + public PropertyDynamicData GetPropDynamicData(string propName) + { + propDynamicDatas.TryGetValue(propName, out var propDynamicData); + return propDynamicData; + } + } } \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerShaderData.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerShaderData.cs index e48ad8775..3f76dd0e3 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerShaderData.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/MetaData/PerShaderData.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma // Per Shader > Per Material > Per Inspector using System; @@ -9,361 +9,369 @@ using UnityEngine; namespace LWGUI { + public enum SearchMode + { + Auto = 0, // Search by group first, and search by property when there are no results + Property = 1, // Search by property + Group = 2, // Search by group + Num = 3 + } - public enum SearchMode - { - Auto = 0, // Search by group first, and search by property when there are no results - Property = 1, // Search by property - Group = 2, // Search by group - Num = 3 - } + public class DisplayModeData + { + public bool showAllAdvancedProperties; + public bool showAllHiddenProperties; + public bool showOnlyModifiedProperties; + public bool showOnlyModifiedGroups; - public class DisplayModeData - { - public bool showAllAdvancedProperties; - public bool showAllHiddenProperties; - public bool showOnlyModifiedProperties; - public bool showOnlyModifiedGroups; + public int advancedCount; + public int hiddenCount; - public int advancedCount; - public int hiddenCount; + public bool IsDefaultDisplayMode() + { + return !(showAllAdvancedProperties || showAllHiddenProperties || showOnlyModifiedProperties || showOnlyModifiedGroups); + } + } - public bool IsDefaultDisplayMode() { return !(showAllAdvancedProperties || showAllHiddenProperties || showOnlyModifiedProperties || showOnlyModifiedGroups); } - } + /// + /// The static metadata of Material Property is only related to Shader. + /// + public partial class PropertyStaticData + { + public string name = string.Empty; + public string displayName = string.Empty; // Decoded displayName (Helpbox and Tooltip are encoded in displayName) - /// - /// The static metadata of Material Property is only related to Shader. - /// - public partial class PropertyStaticData - { - public string name = string.Empty; - public string displayName = string.Empty; // Decoded displayName (Helpbox and Tooltip are encoded in displayName) + // Structure + public string groupName = string.Empty; // [Group(groupName)] / [Sub(groupName)] / [Advanced(groupName)] + public bool isMain = false; // [Group] + public bool isAdvanced = false; // [Advanced] + public bool isAdvancedHeader = false; // the first [Advanced] in the same group + public bool isAdvancedHeaderProperty = false; + public string advancedHeaderString = string.Empty; + public PropertyStaticData parent = null; + public List children = new List(); - // Structure - public string groupName = string.Empty; // [Group(groupName)] / [Sub(groupName)] / [Advanced(groupName)] - public bool isMain = false; // [Group] - public bool isAdvanced = false; // [Advanced] - public bool isAdvancedHeader = false; // the first [Advanced] in the same group - public bool isAdvancedHeaderProperty = false; - public string advancedHeaderString = string.Empty; - public PropertyStaticData parent = null; - public List children = new List(); + // Visibility + public bool isSearchMatched = true; // Search filter result + public bool isExpanding = false; // Children are displayed only when expanded + public bool isReadOnly = false; // [ReadOnly] + public bool isHidden = false; // [Hidden] + public List showIfDatas = new List(); // [ShowIf()] + public List activeIfDatas = new List(); // [ActiveIf()] + public string conditionalDisplayKeyword = string.Empty; // [Group(groupName_conditionalDisplayKeyword)] - // Visibility - public bool isSearchMatched = true; // Search filter result - public bool isExpanding = false; // Children are displayed only when expanded - public bool isReadOnly = false; // [ReadOnly] - public bool isHidden = false; // [Hidden] - public List showIfDatas = new List(); // [ShowIf()] - public string conditionalDisplayKeyword = string.Empty; // [Group(groupName_conditionalDisplayKeyword)] + // Drawers + public IPresetDrawer presetDrawer = null; + public List baseDrawers = null; - // Drawers - public IPresetDrawer presetDrawer = null; - public List baseDrawers = null; + // Metadata + public List extraPropNames = new List(); // Other Props that have been associated + public string helpboxMessages = string.Empty; + public string tooltipMessages = string.Empty; + public LwguiShaderPropertyPreset propertyPresetAsset = null; // The Referenced Preset Asset - // Metadata - public List extraPropNames = new List(); // Other Props that have been associated - public string helpboxMessages = string.Empty; - public string tooltipMessages = string.Empty; - public LwguiShaderPropertyPreset propertyPresetAsset = null; // The Referenced Preset Asset + public void AddExtraProperty(string propName) + { + if (!extraPropNames.Contains(propName)) extraPropNames.Add(propName); + } + } - public void AddExtraProperty(string propName) - { - if (!extraPropNames.Contains(propName)) extraPropNames.Add(propName); - } - } + /// + /// All Shader static metadata can be determined after Shader is compiled and will not change. + /// + public class PerShaderData + { + public Dictionary propStaticDatas = new Dictionary(); + public Shader shader = null; + public string shaderUID = string.Empty; + public DisplayModeData displayModeData = new DisplayModeData(); + public SearchMode searchMode = SearchMode.Auto; + public string searchString = string.Empty; + // public List favoriteproperties = new List(); - /// - /// All Shader static metadata can be determined after Shader is compiled and will not change. - /// - public class PerShaderData - { - public Dictionary propStaticDatas = new Dictionary(); - public Shader shader = null; - public DisplayModeData displayModeData = new DisplayModeData(); - public SearchMode searchMode = SearchMode.Auto; - public string searchString = string.Empty; - // public List favoriteproperties = new List(); + // UnityEngine.Object may be destroyed when loading new scene, so must manually check null reference + private Material _defaultMaterial = null; - // UnityEngine.Object may be destroyed when loading new scene, so must manually check null reference - private Material _defaultMaterial = null; + public Material defaultMaterial + { + get + { + if (!_defaultMaterial && shader) _defaultMaterial = new Material(shader); + return _defaultMaterial; + } + } - public Material defaultMaterial - { - get - { - if (!_defaultMaterial && shader) _defaultMaterial = new Material(shader); - return _defaultMaterial; - } - } + public PerShaderData(Shader shader, MaterialProperty[] props) + { + this.shader = shader; + + if (AssetDatabase.Contains(shader)) + shaderUID = AssetDatabase.GetAssetPath(shader).Replace('/', '_').Replace('\\', '_'); + else + shaderUID = shader.GetHashCode().ToString(); - public PerShaderData(Shader shader, MaterialProperty[] props) - { - this.shader = shader; + // Get Property Static Data + foreach (var prop in props) + { + var propStaticData = new PropertyStaticData() { name = prop.name }; + propStaticDatas[prop.name] = propStaticData; - // Get Property Static Data - foreach (var prop in props) - { - var propStaticData = new PropertyStaticData() { name = prop.name }; - propStaticDatas[prop.name] = propStaticData; + // Get Drawers and Build Drawer StaticMetaData + bool hasDecodedStaticMetaData = false; + { + var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out var decoratorDrawers); - // Get Drawers and Build Drawer StaticMetaData - bool hasDecodedStaticMetaData = false; - { - var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out var decoratorDrawers); + if (drawer is IPresetDrawer) + propStaticData.presetDrawer = drawer as IPresetDrawer; - if (drawer is IPresetDrawer) - propStaticData.presetDrawer = drawer as IPresetDrawer; + var baseDrawer = drawer as IBaseDrawer; + if (baseDrawer != null) + { + propStaticData.baseDrawers = new List() { baseDrawer }; + baseDrawer.BuildStaticMetaData(shader, prop, props, propStaticData); + hasDecodedStaticMetaData = true; + } - var baseDrawer = drawer as IBaseDrawer; - if (baseDrawer != null) - { - propStaticData.baseDrawers = new List() { baseDrawer }; - baseDrawer.BuildStaticMetaData(shader, prop, props, propStaticData); - hasDecodedStaticMetaData = true; - } + decoratorDrawers?.ForEach(decoratorDrawer => + { + baseDrawer = decoratorDrawer as IBaseDrawer; + if (baseDrawer != null) + { + if (propStaticData.baseDrawers == null) + propStaticData.baseDrawers = new List() { baseDrawer }; + else + propStaticData.baseDrawers.Add(baseDrawer); - decoratorDrawers?.ForEach(decoratorDrawer => - { - baseDrawer = decoratorDrawer as IBaseDrawer; - if (baseDrawer != null) - { - if (propStaticData.baseDrawers == null) - propStaticData.baseDrawers = new List() { baseDrawer }; - else - propStaticData.baseDrawers.Add(baseDrawer); + baseDrawer.BuildStaticMetaData(shader, prop, props, propStaticData); + } + }); + } - baseDrawer.BuildStaticMetaData(shader, prop, props, propStaticData); - } - }); - } + if (!hasDecodedStaticMetaData) + DecodeMetaDataFromDisplayName(prop, propStaticData); + } - if (!hasDecodedStaticMetaData) - DecodeMetaDataFromDisplayName(prop, propStaticData); - } + // Check Data + foreach (var prop in props) + { + var propStaticData = propStaticDatas[prop.name]; + propStaticData.extraPropNames.RemoveAll((extraPropName => + string.IsNullOrEmpty(extraPropName) || !propStaticDatas.ContainsKey(extraPropName))); + } - // Check Data - foreach (var prop in props) - { - var propStaticData = propStaticDatas[prop.name]; - propStaticData.extraPropNames.RemoveAll((extraPropName => - string.IsNullOrEmpty(extraPropName) || !propStaticDatas.ContainsKey(extraPropName))); - } + // Build Property Structure + { + var groupToMainPropertyDic = new Dictionary(); - // Build Property Structure - { - var groupToMainPropertyDic = new Dictionary(); + // Collection Groups + foreach (var prop in props) + { + var propData = propStaticDatas[prop.name]; + if (propData.isMain + && !string.IsNullOrEmpty(propData.groupName) + && !groupToMainPropertyDic.ContainsKey(propData.groupName)) + groupToMainPropertyDic.Add(propData.groupName, prop); + } - // Collection Groups - foreach (var prop in props) - { - var propData = propStaticDatas[prop.name]; - if (propData.isMain - && !string.IsNullOrEmpty(propData.groupName) - && !groupToMainPropertyDic.ContainsKey(propData.groupName)) - groupToMainPropertyDic.Add(propData.groupName, prop); - } + // Register SubProps + foreach (var prop in props) + { + var propData = propStaticDatas[prop.name]; + if (!propData.isMain + && !string.IsNullOrEmpty(propData.groupName)) + { + foreach (var groupName in groupToMainPropertyDic.Keys) + { + if (propData.groupName.StartsWith(groupName)) + { + // Update Structure + var mainProp = groupToMainPropertyDic[groupName]; + propData.parent = propStaticDatas[mainProp.name]; + propStaticDatas[mainProp.name].children.Add(propData); - // Register SubProps - foreach (var prop in props) - { - var propData = propStaticDatas[prop.name]; - if (!propData.isMain - && !string.IsNullOrEmpty(propData.groupName)) - { - foreach (var groupName in groupToMainPropertyDic.Keys) - { - if (propData.groupName.StartsWith(groupName)) - { - // Update Structure - var mainProp = groupToMainPropertyDic[groupName]; - propData.parent = propStaticDatas[mainProp.name]; - propStaticDatas[mainProp.name].children.Add(propData); + // Split groupName and conditional display keyword + if (propData.groupName.Length > groupName.Length) + { + propData.conditionalDisplayKeyword = + propData.groupName.Substring(groupName.Length, propData.groupName.Length - groupName.Length).ToUpper(); + propData.groupName = groupName; + } + break; + } + } + } + } + } - // Split groupName and conditional display keyword - if (propData.groupName.Length > groupName.Length) - { - propData.conditionalDisplayKeyword = - propData.groupName.Substring(groupName.Length, propData.groupName.Length - groupName.Length).ToUpper(); - propData.groupName = groupName; - } - break; - } - } - } - } - } + // Build Display Mode Data + { + PropertyStaticData lastPropData = null; + PropertyStaticData lastHeaderPropData = null; + for (int i = 0; i < props.Length; i++) + { + var prop = props[i]; + var propStaticData = propStaticDatas[prop.name]; - // Build Display Mode Data - { - PropertyStaticData lastPropData = null; - PropertyStaticData lastHeaderPropData = null; - for (int i = 0; i < props.Length; i++) - { - var prop = props[i]; - var propStaticData = propStaticDatas[prop.name]; + // Counting + if (propStaticData.isHidden + || (propStaticData.parent != null + && (propStaticData.parent.isHidden + || (propStaticData.parent.parent != null && propStaticData.parent.parent.isHidden)))) + displayModeData.hiddenCount++; + if (propStaticData.isAdvanced + || (propStaticData.parent != null + && (propStaticData.parent.isAdvanced + || (propStaticData.parent.parent != null && propStaticData.parent.parent.isAdvanced)))) + displayModeData.advancedCount++; - // Counting - if (propStaticData.isHidden - || (propStaticData.parent != null - && (propStaticData.parent.isHidden - || (propStaticData.parent.parent != null && propStaticData.parent.parent.isHidden)))) - displayModeData.hiddenCount++; - if (propStaticData.isAdvanced - || (propStaticData.parent != null - && (propStaticData.parent.isAdvanced - || (propStaticData.parent.parent != null && propStaticData.parent.parent.isAdvanced)))) - displayModeData.advancedCount++; + // Build Advanced Structure + if (propStaticData.isAdvanced) + { + // If it is the first prop in a Advanced Block, set to Header + if (lastPropData == null + || !lastPropData.isAdvanced + || propStaticData.isAdvancedHeaderProperty + || (!string.IsNullOrEmpty(propStaticData.advancedHeaderString) + && propStaticData.advancedHeaderString != lastPropData.advancedHeaderString)) + { + propStaticData.isAdvancedHeader = true; + lastHeaderPropData = propStaticData; + } + // Else set to child + else + { + propStaticData.parent = lastHeaderPropData; + lastHeaderPropData.children.Add(propStaticData); + } + } - // Build Advanced Structure - if (propStaticData.isAdvanced) - { - // If it is the first prop in a Advanced Block, set to Header - if (lastPropData == null - || !lastPropData.isAdvanced - || propStaticData.isAdvancedHeaderProperty - || (!string.IsNullOrEmpty(propStaticData.advancedHeaderString) - && propStaticData.advancedHeaderString != lastPropData.advancedHeaderString)) - { - propStaticData.isAdvancedHeader = true; - lastHeaderPropData = propStaticData; - } - // Else set to child - else - { - propStaticData.parent = lastHeaderPropData; - lastHeaderPropData.children.Add(propStaticData); - } - } + lastPropData = propStaticData; + } + } + } - lastPropData = propStaticData; - } - } - } + public PropertyStaticData GetPropStaticData(string propName) + { + propStaticDatas.TryGetValue(propName, out var propStaticData); + return propStaticData; + } - public PropertyStaticData GetPropStaticData(string propName) - { - propStaticDatas.TryGetValue(propName, out var propStaticData); - return propStaticData; - } + private static readonly string _tooltipSplitter = "#"; - private static readonly string _tooltipSplitter = "#"; + private static readonly string _helpboxSplitter = "%"; - private static readonly string _helpboxSplitter = "%"; + public static void DecodeMetaDataFromDisplayName(MaterialProperty prop, PropertyStaticData propStaticData) + { + var tooltips = prop.displayName.Split(new String[] { _tooltipSplitter }, StringSplitOptions.None); + if (tooltips.Length > 1) + { + for (int i = 1; i <= tooltips.Length - 1; i++) + { + var str = tooltips[i]; + var helpboxIndex = tooltips[i].IndexOf(_helpboxSplitter, StringComparison.Ordinal); + if (helpboxIndex > 0) + str = tooltips[i].Substring(0, helpboxIndex); + propStaticData.tooltipMessages += str + "\n"; + } + } - public static void DecodeMetaDataFromDisplayName(MaterialProperty prop, PropertyStaticData propStaticData) - { - var tooltips = prop.displayName.Split(new String[] { _tooltipSplitter }, StringSplitOptions.None); - if (tooltips.Length > 1) - { - for (int i = 1; i <= tooltips.Length - 1; i++) - { - var str = tooltips[i]; - var helpboxIndex = tooltips[i].IndexOf(_helpboxSplitter, StringComparison.Ordinal); - if (helpboxIndex > 0) - str = tooltips[i].Substring(0, helpboxIndex); - propStaticData.tooltipMessages += str + "\n"; - } - } + var helpboxes = prop.displayName.Split(new String[] { _helpboxSplitter }, StringSplitOptions.None); + if (helpboxes.Length > 1) + { + for (int i = 1; i <= helpboxes.Length - 1; i++) + { + var str = helpboxes[i]; + var tooltipIndex = helpboxes[i].IndexOf(_tooltipSplitter, StringComparison.Ordinal); + if (tooltipIndex > 0) + str = tooltips[i].Substring(0, tooltipIndex); + propStaticData.helpboxMessages += str + "\n"; + } + } - var helpboxes = prop.displayName.Split(new String[] { _helpboxSplitter }, StringSplitOptions.None); - if (helpboxes.Length > 1) - { - for (int i = 1; i <= helpboxes.Length - 1; i++) - { - var str = helpboxes[i]; - var tooltipIndex = helpboxes[i].IndexOf(_tooltipSplitter, StringComparison.Ordinal); - if (tooltipIndex > 0) - str = tooltips[i].Substring(0, tooltipIndex); - propStaticData.helpboxMessages += str + "\n"; - } - } + if (propStaticData.helpboxMessages.EndsWith("\n")) + propStaticData.helpboxMessages = propStaticData.helpboxMessages.Substring(0, propStaticData.helpboxMessages.Length - 1); - if (propStaticData.helpboxMessages.EndsWith("\n")) - propStaticData.helpboxMessages = propStaticData.helpboxMessages.Substring(0, propStaticData.helpboxMessages.Length - 1); + propStaticData.displayName = prop.displayName.Split(new String[] { _tooltipSplitter, _helpboxSplitter }, StringSplitOptions.None)[0]; + } - propStaticData.displayName = prop.displayName.Split(new String[] { _tooltipSplitter, _helpboxSplitter }, StringSplitOptions.None)[0]; - } + public void UpdateSearchFilter() + { + var isSearchStringEmpty = string.IsNullOrEmpty(searchString); + var searchStringLower = searchString.ToLower(); + var searchKeywords = searchStringLower.Split(' ', ',', ';', '|', ',', ';'); // Some possible separators - public void UpdateSearchFilter() - { - var isSearchStringEmpty = string.IsNullOrEmpty(searchString); - var searchStringLower = searchString.ToLower(); - var searchKeywords = searchStringLower.Split(' ', ',', ';', '|', ',', ';'); // Some possible separators + // The First Search + foreach (var propStaticDataKWPair in propStaticDatas) + { + propStaticDataKWPair.Value.isSearchMatched = isSearchStringEmpty + ? true + : IsWholeWordMatch(propStaticDataKWPair.Value.displayName, propStaticDataKWPair.Value.name, searchKeywords); + } - // The First Search - foreach (var propStaticDataKWPair in propStaticDatas) - { - propStaticDataKWPair.Value.isSearchMatched = isSearchStringEmpty - ? true - : IsWholeWordMatch(propStaticDataKWPair.Value.displayName, propStaticDataKWPair.Value.name, searchKeywords); - } + // Further adjust visibility + if (!isSearchStringEmpty) + { + var searchModeTemp = searchMode; + // Auto: search by group first, and search by property when there are no results + if (searchModeTemp == SearchMode.Auto) + { + // if has no group + if (!propStaticDatas.Any((propStaticDataKWPair => propStaticDataKWPair.Value.isSearchMatched && propStaticDataKWPair.Value.isMain))) + searchModeTemp = SearchMode.Property; + else + searchModeTemp = SearchMode.Group; + } - // Further adjust visibility - if (!isSearchStringEmpty) - { - var searchModeTemp = searchMode; - // Auto: search by group first, and search by property when there are no results - if (searchModeTemp == SearchMode.Auto) - { - // if has no group - if (!propStaticDatas.Any((propStaticDataKWPair => propStaticDataKWPair.Value.isSearchMatched && propStaticDataKWPair.Value.isMain))) - searchModeTemp = SearchMode.Property; - else - searchModeTemp = SearchMode.Group; - } + // search by property + if (searchModeTemp == SearchMode.Property) + { + // when a SubProp is displayed, the MainProp is also displayed + foreach (var propStaticDataKWPair in propStaticDatas) + { + var propStaticData = propStaticDataKWPair.Value; + if (propStaticData.isMain + && propStaticData.children.Any((childPropStaticData => propStaticDatas[childPropStaticData.name].isSearchMatched))) + propStaticDataKWPair.Value.isSearchMatched = true; + } + } + // search by group + else if (searchModeTemp == SearchMode.Group) + { + // when search by group, all SubProps should display with MainProp + foreach (var propStaticDataKWPair in propStaticDatas) + { + var propStaticData = propStaticDataKWPair.Value; + if (propStaticData.isMain) + foreach (var childPropStaticData in propStaticData.children) + propStaticDatas[childPropStaticData.name].isSearchMatched = propStaticData.isSearchMatched; + } + } + } + } - // search by property - if (searchModeTemp == SearchMode.Property) - { - // when a SubProp is displayed, the MainProp is also displayed - foreach (var propStaticDataKWPair in propStaticDatas) - { - var propStaticData = propStaticDataKWPair.Value; - if (propStaticData.isMain - && propStaticData.children.Any((childPropStaticData => propStaticDatas[childPropStaticData.name].isSearchMatched))) - propStaticDataKWPair.Value.isSearchMatched = true; - } - } - // search by group - else if (searchModeTemp == SearchMode.Group) - { - // when search by group, all SubProps should display with MainProp - foreach (var propStaticDataKWPair in propStaticDatas) - { - var propStaticData = propStaticDataKWPair.Value; - if (propStaticData.isMain) - foreach (var childPropStaticData in propStaticData.children) - propStaticDatas[childPropStaticData.name].isSearchMatched = propStaticData.isSearchMatched; - } - } - } - } + private static bool IsWholeWordMatch(string displayName, string propertyName, string[] searchingKeywords) + { + bool contains = true; + displayName = displayName.ToLower(); + var name = propertyName.ToLower(); - private static bool IsWholeWordMatch(string displayName, string propertyName, string[] searchingKeywords) - { - bool contains = true; - displayName = displayName.ToLower(); - var name = propertyName.ToLower(); + foreach (var keyword in searchingKeywords) + { + var isMatch = false; + isMatch |= displayName.Contains(keyword); + isMatch |= name.Contains(keyword); + contains &= isMatch; + } + return contains; + } - foreach (var keyword in searchingKeywords) - { - var isMatch = false; - isMatch |= displayName.Contains(keyword); - isMatch |= name.Contains(keyword); - contains &= isMatch; - } - return contains; - } - - public void ToggleShowAllAdvancedProperties() - { - foreach (var propStaticDataKWPair in propStaticDatas) - { - if (propStaticDataKWPair.Value.isAdvancedHeader) - propStaticDataKWPair.Value.isExpanding = displayModeData.showAllAdvancedProperties; - } - } - - } + public void ToggleShowAllAdvancedProperties() + { + foreach (var propStaticDataKWPair in propStaticDatas) + { + if (propStaticDataKWPair.Value.isAdvancedHeader) + propStaticDataKWPair.Value.isExpanding = displayModeData.showAllAdvancedProperties; + } + } + } } \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor.meta new file mode 100644 index 000000000..653037bbc --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 699d09d8caac43769acdfc186d37b21b +timeCreated: 1760615698 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler.meta new file mode 100644 index 000000000..25c3bf621 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c48ecf063064446097c4da1c6ee1c085 +timeCreated: 1760615805 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc.meta new file mode 100644 index 000000000..62316335b --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f2edf52a23ac4bedb7dd9866bae7383a +timeCreated: 1760616152 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/ShaderCompilerDefaultFxc.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/ShaderCompilerDefaultFxc.cs new file mode 100644 index 000000000..37bf6c41a --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/ShaderCompilerDefaultFxc.cs @@ -0,0 +1,460 @@ +// Copyright (c) Jason Ma + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Diagnostics; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEditor.Rendering; +using UnityEngine; +using UnityEngine.Rendering; +using LWGUI.PerformanceMonitor; +using Debug = UnityEngine.Debug; + +namespace LWGUI.PerformanceMonitor.ShaderCompiler +{ + public class ShaderCompilerDefaultFxc : IShaderCompiler + { + // Per-compiler stats structure moved here so FXC owns its output data shape. + public struct ShaderPerfStats + { + public float estimatedCost; // Estimated relative performance cost based on experience, not precise results. + public int sampleCount; + public int samplerCount; + public int registerCount; + public int interpolatorChannelCount; + + public bool isValid; + } + + private static ShaderCompilerDefaultFxc _instance; + public static ShaderCompilerDefaultFxc instance => _instance ??= new ShaderCompilerDefaultFxc(); + +#if UNITY_STANDALONE_WIN + public static bool isSupportCurrentPlatform => true; +#else + public static bool isSupportCurrentPlatform => false; +#endif + + public static int priority => 0; + + public string compilerName => "Default Fxc"; + + public ShaderCompilerPlatform api { get; set; } = ShaderCompilerPlatform.D3D; + public BuildTarget target { get; set; } = BuildTarget.StandaloneWindows64; + public GraphicsTier tier { get; set; } = (GraphicsTier)(-1); + + public string GetCompiledShaderPath(ShaderPerfData shaderPerfData, string compiledShaderDirectory, string shaderTypeName) + => Path.Combine(compiledShaderDirectory, $"Fxc_{api}_{target}_{shaderTypeName}.txt"); + + public string GetCompiledDxbcPath(ShaderPerfData shaderPerfData) + => Path.Combine(shaderPerfData.compiledShaderDirectory, $"Fxc_{api}_{target}_{shaderPerfData.shaderTypeName}.dxbc"); + + public bool CompilePass(ShaderPerfData shaderPerfData, ShaderData.Pass pass, ShaderType shaderType, string[] keywords, + out string compiledShader) + { + compiledShader = string.Empty; + + if (shaderPerfData == null || pass == null || keywords == null) + return false; + + var compileInfo = pass.CompileVariant(shaderType, keywords, api, target, tier, true); + if (!compileInfo.Success) + return false; + + // Write DXBC + var dxbcPath = GetCompiledDxbcPath(shaderPerfData); + IOHelper.WriteBinaryFile(dxbcPath, compileInfo.ShaderData); + + // Disassemble With fxc.exe + return IOHelper.RunProcess(_fxcAbsPath, $"/dumpbin \"{dxbcPath}\"", out compiledShader); + } + + public object AnalyzeShaderPerformance(ShaderPerfData shaderPerfData, string compiledShader) + => ParseAsmStats(compiledShader); + + public void DrawShaderPerformanceStatsHeader(LWGUIMetaDatas metaDatas) + { + EditorGUILayout.LabelField(" ", " Cost Samples Registers"); + } + + public void DrawShaderPerformanceStatsLine(LWGUIMetaDatas metaDatas, ShaderPerfData shaderPerfData) + { + EditorGUILayout.BeginHorizontal(); + + var statsObj = shaderPerfData.stats; + if (statsObj is ShaderPerfStats { isValid: true } stats) + { + var statsStr = $"{stats.estimatedCost,7:0.0} {stats.sampleCount,7:0} {stats.registerCount,8:0}"; + EditorGUILayout.LabelField($"{shaderPerfData.passName} | {shaderPerfData.shaderTypeName}", statsStr, GUIStyles.label_monospace); + + ToolbarHelper.DrawShaderPerformanceStatsLineButtons(shaderPerfData); + } + else + { + var status = shaderPerfData.isCompiledSuccessful ? "ANALYSIS FAILED" : "COMPILATION FAILED"; + EditorGUILayout.LabelField($"{shaderPerfData.passName} | {shaderPerfData.shaderTypeName}", status); + } + + EditorGUILayout.EndHorizontal(); + } + + + private static string _cachedFxcPath; + + private static string _fxcAbsPath + { + get + { + if (string.IsNullOrEmpty(_cachedFxcPath)) + _cachedFxcPath = IOHelper.GetAbsPath(AssetDatabase.GUIDToAssetPath("994434336edc8a8469c9afcbb92c5936")); + if (string.IsNullOrEmpty(_cachedFxcPath) || !File.Exists(_cachedFxcPath)) + Debug.LogError("LWGUI: Can not find fxc.exe!"); + return _cachedFxcPath; + } + } + + // https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/shader-model-5-assembly--directx-hlsl- + private static readonly Dictionary _opcodeWeight = new() + { + // ALU + { "add", 1.0f }, + { "and", 1.0f }, + { "bfi", 1.0f }, + { "bfrev", 1.0f }, + { "countbits", 1.0f }, + { "dadd", 4.0f }, + { "ddiv", 16.0f }, + { "deq", 4.0f }, + { "deriv_rtx_coarse", 1.0f }, + { "deriv_rtx_fine", 1.0f }, + { "deriv_rty_coarse", 1.0f }, + { "deriv_rty_fine", 1.0f }, + { "dfma", 4.0f }, + { "dge", 4.0f }, + { "div", 8.0f }, + { "dlt", 4.0f }, + { "dmax", 4.0f }, + { "dmin", 4.0f }, + { "dmov", 1.0f }, + { "dmovc", 1.0f }, + { "dmul", 4.0f }, + { "dne", 4.0f }, + { "dp2", 2.0f }, + { "dp3", 3.0f }, + { "dp4", 4.0f }, + { "drcp", 8.0f }, + { "eq", 1.0f }, + { "exp", 4.0f }, + { "f16tof32", 1.0f }, + { "f32tof16", 1.0f }, + { "firstbit", 1.0f }, + { "frc", 1.0f }, + { "ftod", 2.0f }, + { "ftoi", 1.0f }, + { "ftou", 1.0f }, + { "ge", 1.0f }, + { "iadd", 1.0f }, + { "ibfe", 1.0f }, + { "ieq", 1.0f }, + { "ige", 1.0f }, + { "ilt", 1.0f }, + { "imad", 1.0f }, + { "imin", 1.0f }, + { "imul", 1.0f }, + { "ine", 1.0f }, + { "ineg", 1.0f }, + { "ishl", 1.0f }, + { "ishr", 1.0f }, + { "itof", 1.0f }, + { "log", 4.0f }, + { "lt", 1.0f }, + { "mad", 1.0f }, + { "max", 1.0f }, + { "min", 1.0f }, + { "mov", 1.0f }, + { "movc", 1.0f }, + { "mul", 1.0f }, + { "ne", 1.0f }, + { "not", 1.0f }, + { "or", 1.0f }, + { "rcp", 4.0f }, + { "round_ne", 1.0f }, + { "round_ni", 1.0f }, + { "round_pi", 1.0f }, + { "round_z", 1.0f }, + { "rsq", 4.0f }, + { "sincos", 4.0f }, + { "sqrt", 4.0f }, + { "swapc", 1.0f }, + { "uaddc", 1.0f }, + { "ubfe", 1.0f }, + { "udiv", 8.0f }, + { "uge", 1.0f }, + { "ult", 1.0f }, + { "umad", 1.0f }, + { "umax", 1.0f }, + { "umin", 1.0f }, + { "umul", 1.0f }, + { "ushr", 1.0f }, + { "usubb", 1.0f }, + { "utof", 1.0f }, + { "xor", 1.0f }, + + // Non-ALU (ignored) + { "atomic_and", 0f }, + { "atomic_cmp_store", 0f }, + { "atomic_iadd", 0f }, + { "atomic_imax", 0f }, + { "atomic_imin", 0f }, + { "atomic_or", 0f }, + { "atomic_umax", 0f }, + { "atomic_umin", 0f }, + { "atomic_xor", 0f }, + { "break", 0f }, + { "breakc", 0f }, + { "bufinfo", 0f }, + { "call", 0f }, + { "callc", 0f }, + { "case", 0f }, + { "continue", 0f }, + { "continuec", 0f }, + { "cut", 0f }, + { "cut_stream", 0f }, + { "dcl_constantbuffer", 0f }, + { "dcl_function_body", 0f }, + { "dcl_function_table", 0f }, + { "dcl_globalflags", 0f }, + { "dcl_hs_fork_phase_instance_count", 0f }, + { "dcl_hs_join_phase_instance_count", 0f }, + { "dcl_hs_max_tessfactor", 0f }, + { "dcl_immediateconstantbuffer", 0f }, + { "dcl_indexabletemp", 0f }, + { "dcl_indexrange", 0f }, + { "dcl_input", 0f }, + { "dcl_input vforkinstanceid", 0f }, + { "dcl_input vgsinstanceid", 0f }, + { "dcl_input vjoininstanceid", 0f }, + { "dcl_input voutputcontrolpointid", 0f }, + { "dcl_input vprim", 0f }, + { "dcl_input vthread", 0f }, + { "dcl_input_control_point_count", 0f }, + { "dcl_input_sv", 0f }, + { "dcl_inputprimitive", 0f }, + { "dcl_interface", 0f }, + { "dcl_interface_dynamicindexed", 0f }, + { "dcl_maxoutputvertexcount", 0f }, + { "dcl_output", 0f }, + { "dcl_output odepth", 0f }, + { "dcl_output omask", 0f }, + { "dcl_output_control_point_count", 0f }, + { "dcl_output_sgv", 0f }, + { "dcl_output_siv", 0f }, + { "dcl_outputtopology", 0f }, + { "dcl_resource", 0f }, + { "dcl_resource raw", 0f }, + { "dcl_resource structured", 0f }, + { "dcl_sampler", 0f }, + { "dcl_stream", 0f }, + { "dcl_temps", 0f }, + { "dcl_tessellator_domain", 0f }, + { "dcl_tessellator_output_primitive", 0f }, + { "dcl_tessellator_partitioning", 0f }, + { "dcl_tgsm_raw", 0f }, + { "dcl_tgsm_structured", 0f }, + { "dcl_thread_group", 0f }, + { "dcl_uav_raw", 0f }, + { "dcl_uav_structured", 0f }, + { "dcl_uav_typed", 0f }, + { "default", 0f }, + { "discard", 0f }, + { "else", 0f }, + { "emit", 0f }, + { "emit_stream", 0f }, + { "emitthencut", 0f }, + { "emitthencut_stream", 0f }, + { "endif", 0f }, + { "endloop", 0f }, + { "endswitch", 0f }, + { "fcall", 0f }, + { "gather4", 0f }, + { "gather4_c", 0f }, + { "gather4_po", 0f }, + { "gather4_po_c", 0f }, + { "hs_control_point_phase", 0f }, + { "hs_decls", 0f }, + { "hs_fork_phase", 0f }, + { "hs_join_phase", 0f }, + { "if", 0f }, + { "imm_atomic_alloc", 0f }, + { "imm_atomic_and", 0f }, + { "imm_atomic_cmp_exch", 0f }, + { "imm_atomic_consume", 0f }, + { "imm_atomic_exch", 0f }, + { "imm_atomic_iadd", 0f }, + { "imm_atomic_imax", 0f }, + { "imm_atomic_imin", 0f }, + { "imm_atomic_or", 0f }, + { "imm_atomic_umax", 0f }, + { "imm_atomic_umin", 0f }, + { "imm_atomic_xor", 0f }, + { "label", 0f }, + { "ld", 0f }, + { "ld_raw", 0f }, + { "ld_structured", 0f }, + { "ld_uav_typed", 0f }, + { "ld2dms", 0f }, + { "lod", 0f }, + { "loop", 0f }, + { "nop", 0f }, + { "resinfo", 0f }, + { "ret", 0f }, + { "retc", 0f }, + { "sample", 0f }, + { "sample_b", 0f }, + { "sample_c", 0f }, + { "sample_c_lz", 0f }, + { "sample_d", 0f }, + { "sample_l", 0f }, + { "sampleinfo", 0f }, + { "samplepos", 0f }, + { "store_raw", 0f }, + { "store_structured", 0f }, + { "store_uav_typed", 0f }, + { "switch", 0f }, + { "sync", 0f }, + }; + + private static int IndexOfWhitespace(string s) + { + for (int i = 0; i < s.Length; i++) + { + var c = s[i]; + if (char.IsWhiteSpace(c)) return i; + } + return -1; + } + + private static string NormalizeOpcode(string opcode) + { + // normalize to lower, strip optional _sat suffix used in some ops like mul_sat/mov_sat + // opcode = opcode.ToLowerInvariant(); + if (opcode.EndsWith("_sat", StringComparison.Ordinal)) + opcode = opcode.Substring(0, opcode.Length - 3); + return opcode; + } + + private static ShaderPerfStats ParseAsmStats(string asmText) + { + if (string.IsNullOrEmpty(asmText)) + { + return new ShaderPerfStats(); + } + + var totalCost = 0f; + var sampleCount = 0; + var samplers = new HashSet(StringComparer.OrdinalIgnoreCase); + var registerCount = 0; + var interpChannels = 0; + using (var reader = new StringReader(asmText)) + { + int lineIndex = -1; + while (reader.ReadLine() is { } line) + { + lineIndex++; + line = line.Trim(); + + if (lineIndex < 2) continue; + if (string.IsNullOrEmpty(line)) continue; + if (line.StartsWith("//")) continue; + + // TODO: Statistical flow control and other special instructions + + var firstSpace = IndexOfWhitespace(line); + // Skip headers like ps_#_# labels not considered + if (firstSpace <= 0) continue; + + var opcode = line.Substring(0, firstSpace).Trim(); + opcode = NormalizeOpcode(opcode); + + if (string.IsNullOrWhiteSpace(opcode)) continue; + if (!char.IsLetter(opcode[0])) continue; + + if (_opcodeWeight.TryGetValue(opcode, out var w)) + { + totalCost += w; + } + else + { + Debug.LogWarning($"LWGUI: {typeof(ShaderCompilerDefaultFxc)}: Unknown opcode: {opcode}"); + } + + // Texture sampling stats + if (opcode.StartsWith("sample", StringComparison.Ordinal) || opcode.StartsWith("gather4", StringComparison.Ordinal)) + { + sampleCount++; + } + else if (string.Equals(opcode, "ld", StringComparison.Ordinal)) + { + // count ld reading from textures t# + if (line.Contains(", t")) sampleCount++; + } + + // Sampler declarations + if (opcode == "dcl_sampler") + { + // e.g. dcl_sampler s1, mode_default + var idx = line.IndexOf('s'); + if (idx >= 0) + { + var end = idx + 1; + while (end < line.Length && char.IsDigit(line[end])) end++; + if (end > idx) + { + var sid = line.Substring(idx, end - idx); + samplers.Add(sid); + } + } + } + + // Temp registers + if (opcode == "dcl_temps") + { + // e.g. dcl_temps 27 + var numStr = line.Substring(firstSpace).Trim(); + int.TryParse(numStr, NumberStyles.Integer, CultureInfo.InvariantCulture, out registerCount); + } + + // Interpolator channels: dcl_input_ps lines only + if (opcode == "dcl_input_ps") + { + var dot = line.IndexOf('.'); + if (dot >= 0) + { + int count = 0; + for (int i = dot + 1; i < line.Length; i++) + { + var c = line[i]; + if (c == 'x' || c == 'y' || c == 'z' || c == 'w') count++; + else break; + } + interpChannels += count; + } + } + } + } + + return new ShaderPerfStats + { + estimatedCost = totalCost, + sampleCount = sampleCount, + samplerCount = samplers.Count, + registerCount = registerCount, + interpolatorChannelCount = interpChannels, + isValid = true + }; + } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/ShaderCompilerDefaultFxc.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/ShaderCompilerDefaultFxc.cs.meta new file mode 100644 index 000000000..55368df60 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/ShaderCompilerDefaultFxc.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7b5553f7fbdc45d585e9ecd2c73d8539 +timeCreated: 1760616203 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/fxc.exe b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/fxc.exe new file mode 100644 index 000000000..5e1c406ff Binary files /dev/null and b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/fxc.exe differ diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/fxc.exe.meta similarity index 61% rename from Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl.meta rename to Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/fxc.exe.meta index 9c1c4dc03..1c04a0a3a 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Fxc/fxc.exe.meta @@ -1,6 +1,6 @@ fileFormatVersion: 2 -guid: 130ac8fd23814be49854157d7be9194e -ShaderIncludeImporter: +guid: 994434336edc8a8469c9afcbb92c5936 +DefaultImporter: externalObjects: {} userData: assetBundleName: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/IShaderCompiler.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/IShaderCompiler.cs new file mode 100644 index 000000000..cbb2547df --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/IShaderCompiler.cs @@ -0,0 +1,51 @@ +// Copyright (c) Jason Ma + +using UnityEditor.Rendering; +using UnityEngine.Rendering; +using UnityEditor; + +namespace LWGUI.PerformanceMonitor.ShaderCompiler +{ + public interface IShaderCompiler + { + public static IShaderCompiler instance { get; } + + public static bool isSupportCurrentPlatform => true; + + public static int priority => 0; + + public string compilerName { get; } + + public ShaderCompilerPlatform api { get; set; } + public BuildTarget target { get; set; } + public GraphicsTier tier { get; set; } + + /// + /// The path to the Shader compilation result stored in text. + /// + public string GetCompiledShaderPath(ShaderPerfData shaderPerfData, string compiledShaderDirectory, string shaderTypeName); + + /// + /// Try to compile a pass variant. Returns true and outputs string on success. + /// + public bool CompilePass(ShaderPerfData shaderPerfData, ShaderData.Pass pass, ShaderType shaderType, string[] keywords, + out string compiledShader); + + /// + /// Analyze a compiled shader (or readable asm) and return a compiler-specific stats object. + /// The returned object is opaque to the caller and will be stored in ShaderPerfData.stats. + /// Return null on failure. + /// + public object AnalyzeShaderPerformance(ShaderPerfData shaderPerfData, string compiledShader); + + public void DrawShaderPerformanceStatsHeader(LWGUIMetaDatas metaDatas) { } + + /// + /// Draw a single line (pass) of shader performance UI inside the toolbar area. + /// Compiler-specific UI (Find/Open buttons, label contents) should be implemented here. + /// + public void DrawShaderPerformanceStatsLine(LWGUIMetaDatas metaDatas, ShaderPerfData shaderPerfData); + + public void DrawShaderPerformanceStatsFooter(LWGUIMetaDatas metaDatas) { } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/IShaderCompiler.cs.meta similarity index 83% rename from Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawer.cs.meta rename to Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/IShaderCompiler.cs.meta index 3663a9dc4..777122fe8 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawer.cs.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/IShaderCompiler.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b7661dfeec673f340b66ac769fa42d18 +guid: 8719df0f3ab95f449b01b7c46d9bf80d MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali.meta new file mode 100644 index 000000000..974c4e8ae --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bf6617caaa864ee6854c54d837967c6d +timeCreated: 1761656115 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models.meta new file mode 100644 index 000000000..84b704c83 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e21bdb269db343c6b20d39dda87981e3 +timeCreated: 1761656119 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/DynamicValue.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/DynamicValue.cs new file mode 100644 index 000000000..9fd1b660a --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/DynamicValue.cs @@ -0,0 +1,54 @@ +// Copyright (c) Jason Ma + +using System; + +namespace LWGUI.PerformanceMonitor.ShaderCompiler.Mali +{ + [Serializable] + public struct DynamicValue + { + public enum ValueType + { + Unknown, + Null, + Float, + Int, + Bool, + } + + public ValueType Type; + public int Int; + public float Float; + public bool Bool; + + public DynamicValue(object value) + { + if (value is long l) + { + value = (int) l; + } + + (Type, Int, Float, Bool) = value switch + { + int i => (ValueType.Int, i, 0, false), + float f => (ValueType.Float, 0, f, false), + bool b => (ValueType.Bool, 0, 0, b), + null => (ValueType.Null, 0, 0, false), + var _ => throw new ArgumentOutOfRangeException(nameof(value), + $"Invalid object type: {value?.GetType()}" + ), + }; + } + + public override string ToString() => + Type switch + { + ValueType.Unknown => throw new InvalidOperationException("Unknown value type"), + ValueType.Float => Float.ToString("F2"), + ValueType.Int => Int.ToString(), + ValueType.Bool => Bool.ToString(), + ValueType.Null => "N/A", + _ => throw new ArgumentOutOfRangeException(), + }; + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/DynamicValue.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/DynamicValue.cs.meta new file mode 100644 index 000000000..bd5bbe7f7 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/DynamicValue.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 082ebd2742584b6dbbfc47422310b203 +timeCreated: 1761656119 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/JsonMaliocOutput.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/JsonMaliocOutput.cs new file mode 100644 index 000000000..3466b547a --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/JsonMaliocOutput.cs @@ -0,0 +1,66 @@ +// Copyright (c) Jason Ma +// ReSharper disable InconsistentNaming + +using System; + +namespace LWGUI.PerformanceMonitor.ShaderCompiler.Mali +{ + [Serializable] + internal class JsonMaliocOutput + { + public Schema schema; + public Shader[] shaders; + + [Serializable] + public class Schema + { + public string name; + public int version; + } + + [Serializable] + public class Shader + { + // Normal output fields + public ShaderProperty[] properties; + public ShaderVariant[] variants; + + // Error output fields + public string[] errors; + public string[] warnings; + public string filename; + } + + [Serializable] + public class ShaderProperty + { + public string display_name; + public string name; + public string value; + } + + [Serializable] + public class ShaderVariant + { + public string name; + public ShaderVariantPerformance performance; + public ShaderProperty[] properties; + } + + [Serializable] + public class ShaderVariantPerformance + { + public string[] pipelines; + public ShaderVariantCycles longest_path_cycles; + public ShaderVariantCycles shortest_path_cycles; + public ShaderVariantCycles total_cycles; + } + + [Serializable] + public class ShaderVariantCycles + { + public string[] bound_pipelines; + public float[] cycle_count; + } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/JsonMaliocOutput.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/JsonMaliocOutput.cs.meta new file mode 100644 index 000000000..7a09b6ea2 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/JsonMaliocOutput.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 97b5dd9724dd4e16b4cd3fade5b6b26e +timeCreated: 1761656120 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/RuntimeMaliocShader.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/RuntimeMaliocShader.cs new file mode 100644 index 000000000..a64ed89bd --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/RuntimeMaliocShader.cs @@ -0,0 +1,59 @@ +// Copyright (c) Jason Ma + +using System; +using System.Collections.Generic; + +namespace LWGUI.PerformanceMonitor.ShaderCompiler.Mali +{ + [Serializable] + public class RuntimeMaliocShader + { + [Serializable] + public enum ShaderVariantPipelineType + { + Null, + Arithmetic, + LoadStore, + Varying, + Texture, + } + + public bool HasErrors; + public List Errors; + public List Warnings; + public List Properties; + public List Variants; + + [Serializable] + public class ShaderProperty + { + public enum Unit + { + None, + Percent, + } + + public string Name; + public DynamicValue Value; + public Unit ValueUnit; + } + + [Serializable] + public class ShaderVariant + { + public string Name; + public List Pipelines; + public ShaderPipelineCycles LongestPathCycles; + public ShaderPipelineCycles ShortestPathCycles; + public ShaderPipelineCycles TotalCycles; + public List Properties; + } + + [Serializable] + public class ShaderPipelineCycles + { + public List PipelineCycles; + public ShaderVariantPipelineType BoundPipeline; + } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/RuntimeMaliocShader.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/RuntimeMaliocShader.cs.meta new file mode 100644 index 000000000..1bf23f058 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Models/RuntimeMaliocShader.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0d803c9bc0cc4f1d9b50cb06b05aacb1 +timeCreated: 1761656119 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing.meta new file mode 100644 index 000000000..ab1a57349 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 24c5b23d58934748abe6deaa63777dd0 +timeCreated: 1761656120 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing/MaliocOutputParser.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing/MaliocOutputParser.cs new file mode 100644 index 000000000..dfa405b3e --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing/MaliocOutputParser.cs @@ -0,0 +1,139 @@ +// Copyright (c) Jason Ma + +using System; +using System.Globalization; +using System.Linq; +using UnityEngine; + +namespace LWGUI.PerformanceMonitor.ShaderCompiler.Mali +{ + public static class MaliocOutputParser + { + public static RuntimeMaliocShader Parse(string json) + { + if (json == null) + return null; + + JsonMaliocOutput jsonModel; + try + { + jsonModel = JsonUtility.FromJson(json); + } + catch (Exception e) + { + Debug.LogError($"LWGUI: Failed to parse malioc json: {e.Message}"); + return null; + } + + if (jsonModel == null || jsonModel.shaders == null || jsonModel.shaders.Length != 1) + { + Debug.LogError("LWGUI: malioc json missing shaders or unexpected format."); + return null; + } + + var shader = jsonModel.shaders[0]; + + // Check if this is an error response + bool isErrorResponse = jsonModel.schema?.name == "error"; + if (isErrorResponse || (shader.errors != null && shader.errors.Length > 0)) + { + return new RuntimeMaliocShader + { + HasErrors = true, + Errors = shader.errors?.ToList() ?? new System.Collections.Generic.List(), + Warnings = shader.warnings?.ToList() ?? new System.Collections.Generic.List(), + Properties = new System.Collections.Generic.List(), + Variants = new System.Collections.Generic.List(), + }; + } + + return new RuntimeMaliocShader + { + HasErrors = false, + Errors = new System.Collections.Generic.List(), + Warnings = shader.warnings?.ToList() ?? new System.Collections.Generic.List(), + Properties = shader.properties.Select(ConvertProperty).ToList(), + Variants = shader.variants.Select(variant => + { + var pipelines = variant.performance.pipelines.Select(ParsePipelineType).ToList(); + return new RuntimeMaliocShader.ShaderVariant + { + Name = variant.name, + Properties = variant.properties.Select(ConvertVariantProperty).ToList(), + Pipelines = pipelines, + LongestPathCycles = + ParseShaderPipelineCycles(variant.performance.longest_path_cycles), + ShortestPathCycles = + ParseShaderPipelineCycles(variant.performance.shortest_path_cycles), + TotalCycles = ParseShaderPipelineCycles(variant.performance.total_cycles), + }; + } + ).ToList(), + }; + } + + private static RuntimeMaliocShader.ShaderProperty ConvertProperty(JsonMaliocOutput.ShaderProperty property) => + new() { Name = property.display_name, Value = new DynamicValue(ParseValue(property.value)) }; + + private static RuntimeMaliocShader.ShaderProperty + ConvertVariantProperty(JsonMaliocOutput.ShaderProperty property) => + new() + { + Name = property.display_name, Value = new DynamicValue(ParseValue(property.value)), + ValueUnit = ParseValueUnit(property.name), + }; + + private static RuntimeMaliocShader.ShaderProperty.Unit ParseValueUnit(string name) => + name switch + { + "thread_occupancy" => RuntimeMaliocShader.ShaderProperty.Unit.Percent, + "fp16_arithmetic" => RuntimeMaliocShader.ShaderProperty.Unit.Percent, + var _ => RuntimeMaliocShader.ShaderProperty.Unit.None, + }; + + private static RuntimeMaliocShader.ShaderVariantPipelineType ParsePipelineType(string text) => + text switch + { + "arithmetic" => RuntimeMaliocShader.ShaderVariantPipelineType.Arithmetic, + "load_store" => RuntimeMaliocShader.ShaderVariantPipelineType.LoadStore, + "varying" => RuntimeMaliocShader.ShaderVariantPipelineType.Varying, + "texture" => RuntimeMaliocShader.ShaderVariantPipelineType.Texture, + "" => RuntimeMaliocShader.ShaderVariantPipelineType.Null, + null => RuntimeMaliocShader.ShaderVariantPipelineType.Null, + var _ => throw new ArgumentOutOfRangeException(nameof(text), text, "Invalid pipeline type."), + }; + + private static RuntimeMaliocShader.ShaderPipelineCycles ParseShaderPipelineCycles( + JsonMaliocOutput.ShaderVariantCycles cycles) => + new() + { + PipelineCycles = (cycles.cycle_count ?? Array.Empty()).Select(f => f).ToList(), + BoundPipeline = ParsePipelineType(cycles.bound_pipelines?.First()), + }; + + private static object ParseValue(string value) + { + if (string.IsNullOrEmpty(value)) + return null; + + var s = value.Trim(); + if (s.Equals("null", StringComparison.OrdinalIgnoreCase)) + return null; + + // Try int + if (int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var i)) + return i; + + // Try float + if (float.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var f)) + return f; + + // Try bool + if (bool.TryParse(s, out var b)) + return b; + + // Fallback: return string + return s; + } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing/MaliocOutputParser.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing/MaliocOutputParser.cs.meta new file mode 100644 index 000000000..cf6cb9126 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/Parsing/MaliocOutputParser.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5b9ef44e450a4f9e81fc0f0d35afc38a +timeCreated: 1761656120 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/ShaderCompilerMali.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/ShaderCompilerMali.cs new file mode 100644 index 000000000..ddefcb284 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/ShaderCompilerMali.cs @@ -0,0 +1,178 @@ +// Copyright (c) Jason Ma + +using System.IO; +using System.Linq; +using System.Text; +using UnityEditor.Rendering; +using UnityEngine.Rendering; +using UnityEngine; +using UnityEditor; +using LWGUI.PerformanceMonitor.ShaderCompiler.Mali; + +namespace LWGUI.PerformanceMonitor.ShaderCompiler +{ + public class ShaderCompilerMali : IShaderCompiler + { + private static ShaderCompilerMali _instance; + public static ShaderCompilerMali instance => _instance ??= new ShaderCompilerMali(); + + public ShaderCompilerPlatform api { get; set; } = ShaderCompilerPlatform.GLES3x; + public BuildTarget target { get; set; } = BuildTarget.Android; + public GraphicsTier tier { get; set; } = (GraphicsTier)(-1); + + public string compilerName => "Malioc"; + + private static int _isSupportCurrentPlatform = -1; + + public static bool isSupportCurrentPlatform + { + get + { + if (_isSupportCurrentPlatform == -1) + { + if (!IOHelper.RunCMD("malioc --list", out var output) || string.IsNullOrWhiteSpace(output) || !output.Contains("Compiler")) + _isSupportCurrentPlatform = 0; + else + _isSupportCurrentPlatform = 1; + } + + return _isSupportCurrentPlatform == 1; + } + } + + public static int priority => 10; + + public string GetCompiledShaderPath(ShaderPerfData shaderPerfData, string compiledShaderDirectory, string shaderTypeName) + { + string ext; + switch (shaderPerfData.shaderType) + { + // https://developer.arm.com/documentation/101863/8-8/Using-Mali-Offline-Compiler/Compiling-OpenGL-ES-shaders + case ShaderType.Vertex: ext = ".vert"; break; + case ShaderType.Fragment: ext = ".frag"; break; + case ShaderType.Geometry: ext = ".geom"; break; + default: return null; + } + + return Path.Combine(compiledShaderDirectory, $"Mali_{api}_{target}_{shaderTypeName}{ext}"); + } + + public string GetMaliJsonOutputPath(ShaderPerfData shaderPerfData) + => Path.Combine(shaderPerfData.compiledShaderDirectory, $"Mali_{api}_{target}_{shaderPerfData.shaderTypeName}.json"); + + + public bool CompilePass(ShaderPerfData shaderPerfData, ShaderData.Pass pass, ShaderType shaderType, string[] keywords, + out string compiledShader) + { + compiledShader = string.Empty; + + if (shaderPerfData == null || pass == null || keywords == null) + return false; + + var compileInfo = pass.CompileVariant(shaderType, keywords, api, target, tier, true); + if (!compileInfo.Success) + return false; + + compiledShader = Encoding.UTF8.GetString(compileInfo.ShaderData); + + // Fix Mali Compiler Errors + compiledShader = compiledShader.Replace("#version 300 es", "#version 320 es"); + compiledShader = compiledShader.Replace("#version 310 es", "#version 320 es"); + IOHelper.WriteTextFile(shaderPerfData.compiledShaderPath, compiledShader); + + return !string.IsNullOrWhiteSpace(compiledShader); + } + + + public object AnalyzeShaderPerformance(ShaderPerfData shaderPerfData, string compiledShader) + { + var jsonPath = GetMaliJsonOutputPath(shaderPerfData); + string jsonString; + + if (!File.Exists(jsonPath)) + { + // https://developer.arm.com/documentation/101863/8-8/Using-Mali-Offline-Compiler/Compiling-OpenGL-ES-shaders + IOHelper.RunCMD($"malioc --core Mali-G76 --format json \"{shaderPerfData.compiledShaderPath}\"", out jsonString); + IOHelper.WriteTextFile(jsonPath, jsonString); + } + else + { + jsonString = IOHelper.ReadTextFile(jsonPath); + } + + if (IOHelper.ExistAndNotEmpty(jsonPath)) + { + return MaliocOutputParser.Parse(jsonString); + } + + return null; + } + + public void DrawShaderPerformanceStatsHeader(LWGUIMetaDatas metaDatas) + { + EditorGUILayout.LabelField(" ", "Arithmetic Load/Store Varying Texture"); + } + + // https://developer.arm.com/documentation/101863/8-8/Using-Mali-Offline-Compiler/Performance-analysis + public void DrawShaderPerformanceStatsLine(LWGUIMetaDatas metaDatas, ShaderPerfData shaderPerfData) + { + EditorGUILayout.BeginHorizontal(); + + if (shaderPerfData.stats is RuntimeMaliocShader stats) + { + if (stats.Variants is { Count: > 0 } && stats.Variants[0].Pipelines is { Count: > 0 }) + { + var variant = stats.Variants[0]; + var cycles = Enumerable.Repeat(0.0f, variant.Pipelines.Count).ToList(); + + for (int i = 0; i < variant.Pipelines.Count; i++) + { + cycles[i] = Mathf.Max(Mathf.Max(variant.ShortestPathCycles.PipelineCycles[i], + variant.LongestPathCycles.PipelineCycles[i]), + variant.TotalCycles.PipelineCycles[i]); + } + + // https://developer.arm.com/documentation/101863/8-8/Using-Mali-Offline-Compiler/Performance-analysis/Performance-table + float arithmeticCycle = 0; + float loadStoreCycle = 0; + float varyingCycle = 0; + float textureCycle = 0; + for (int i = 0; i < variant.Pipelines.Count; i++) + { + switch (variant.Pipelines[i]) + { + case RuntimeMaliocShader.ShaderVariantPipelineType.Arithmetic: arithmeticCycle = cycles[i]; break; + case RuntimeMaliocShader.ShaderVariantPipelineType.LoadStore: loadStoreCycle = cycles[i]; break; + case RuntimeMaliocShader.ShaderVariantPipelineType.Varying: varyingCycle = cycles[i]; break; + case RuntimeMaliocShader.ShaderVariantPipelineType.Texture: textureCycle = cycles[i]; break; + } + } + + var statsStr = $"{arithmeticCycle,8:0.0} {loadStoreCycle,9:0.0} {varyingCycle,7:0.0} {textureCycle,6:0.0}"; + EditorGUILayout.LabelField($"{shaderPerfData.passName} | {shaderPerfData.shaderTypeName}", statsStr, GUIStyles.label_monospace); + + ToolbarHelper.DrawShaderPerformanceStatsLineButtons(shaderPerfData); + if (GUILayout.Button("Json", GUILayout.MaxWidth(40))) + IOHelper.OpenFile(GetMaliJsonOutputPath(shaderPerfData)); + } + else + { + EditorGUILayout.LabelField($"{shaderPerfData.passName} | {shaderPerfData.shaderTypeName}", "ANALYSIS FAILED"); + } + + if (stats.HasErrors) + { + var errorMsg = stats.Errors.Count > 0 ? stats.Errors[0] : "Unknown Error"; + Debug.LogError($"LWGUI: {shaderPerfData.passName} | {shaderPerfData.shaderTypeName} Error:\n{errorMsg}"); + } + } + else + { + var status = shaderPerfData.isCompiledSuccessful ? "ANALYSIS FAILED" : "COMPILATION FAILED"; + EditorGUILayout.LabelField($"{shaderPerfData.passName} | {shaderPerfData.shaderTypeName}", status); + } + + EditorGUILayout.EndHorizontal(); + } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/ShaderCompilerMali.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/ShaderCompilerMali.cs.meta new file mode 100644 index 000000000..5954af936 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderCompiler/Mali/ShaderCompilerMali.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 40365616bf6b4d40bb751e848dba6105 +timeCreated: 1760616221 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfData.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfData.cs new file mode 100644 index 000000000..b3c6a5426 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfData.cs @@ -0,0 +1,27 @@ +// Copyright (c) Jason Ma + +using System; +using System.Collections.Generic; +using UnityEditor.Rendering; + +namespace LWGUI.PerformanceMonitor +{ + public class ShaderPerfData + { + public int subshaderIndex = -1; + public int passIndex = -1; + public string passName = string.Empty; + public ShaderType shaderType; + public string hash = string.Empty; + public bool isCompiledSuccessful = false; + + // Path + public string shaderTypeName = string.Empty; + public string compiledShaderDirectory = string.Empty; + public string compiledShaderPath = string.Empty; + + // Opaque compiler-specific stats. + // Compiler implementations should populate this with their own stats object (or null if unavailable). + public object stats; + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfData.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfData.cs.meta new file mode 100644 index 000000000..b03507521 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6adc39ef525045bb86847fb8e69ddbaf +timeCreated: 1760615788 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfMonitor.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfMonitor.cs new file mode 100644 index 000000000..6a1424de9 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfMonitor.cs @@ -0,0 +1,253 @@ +// Copyright (c) Jason Ma + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using LWGUI.PerformanceMonitor.ShaderCompiler; +using UnityEditor; +using UnityEditor.Rendering; +using UnityEngine; +using UnityEngine.Rendering; +using Debug = UnityEngine.Debug; + +namespace LWGUI.PerformanceMonitor +{ + public static class ShaderPerfMonitor + { + #region Global Settings + + public static GraphicsTier graphicsTier = (GraphicsTier)(-1); + public static ShaderCompilerPlatform shaderCompilerPlatform = ShaderCompilerPlatform.D3D; + public static BuildTarget buildTarget = BuildTarget.StandaloneWindows64; + + #endregion + + public static List GetMaterialAndGlobalAndUserOverrideActiveKeywords(Material material, string shaderUID) + { + var output = new List(); + + foreach (var localKeyword in material.enabledKeywords) + { + if (ToolbarHelper.IsUserKeywordOverride(shaderUID, localKeyword.name)) + { + if (ToolbarHelper.IsUserKeywordEnabled(shaderUID, localKeyword.name)) + output.Add(localKeyword.name); + } + else + { + output.Add(localKeyword.name); + } + } + + foreach (var keyword in material.shader.keywordSpace.keywords) + { + if (ToolbarHelper.IsUserKeywordOverride(shaderUID, keyword.name)) + { + if (ToolbarHelper.IsUserKeywordEnabled(shaderUID, keyword.name)) + output.Add(keyword.name); + } + else + { + if (!keyword.isValid) + continue; + + // Is a global keyword? + if (keyword.isOverridable && Shader.IsKeywordEnabled(keyword.name)) + output.Add(keyword.name); + } + } + + return output.Distinct().ToList(); + } + + public static string ComputeShaderVariantHash(List keywords, BuildTarget target, ShaderCompilerPlatform platform, GraphicsTier tier) + { + var sorted = keywords?.OrderBy(k => k) ?? Enumerable.Empty(); + var key = string.Join(";", sorted) + $"|{target}|{platform}|{tier}"; + using var md5 = MD5.Create(); + var bytes = Encoding.UTF8.GetBytes(key); + var hash = md5.ComputeHash(bytes); + return string.Concat(hash.Select(b => b.ToString("x2"))); + } + + public static List GetShaderVariantPerfDatas(Shader shader, List keywords) + { + var output = new List(); + var shaderData = ShaderUtil.GetShaderData(shader); + var subshader = shaderData.ActiveSubshader; + + IShaderCompiler compiler = GetActiveCompiler(); + + for (int i = 0; i < subshader.PassCount; i++) + { + var pass = subshader.GetPass(i); + for (int j = 0; j < (int)ShaderType.Count; j++) + { + var shaderType = (ShaderType)j; + if (!pass.HasShaderStage(shaderType)) + continue; + + // Collect input data + var hash = ComputeShaderVariantHash(keywords, buildTarget, shaderCompilerPlatform, graphicsTier); + var shaderPerfData = new ShaderPerfData + { + subshaderIndex = shaderData.ActiveSubshaderIndex, + passIndex = i, + passName = IOHelper.GetValidFileName(pass.Name), + shaderType = shaderType, + hash = hash, + }; + + shaderPerfData.shaderTypeName = shaderPerfData.shaderType.ToString(); + shaderPerfData.compiledShaderDirectory = IOHelper.GetCompiledShaderVariantCacheDirectory(shader, shaderPerfData); + + if (compiler != null) + { + shaderPerfData.compiledShaderPath = compiler.GetCompiledShaderPath(shaderPerfData, shaderPerfData.compiledShaderDirectory, shaderPerfData.shaderTypeName); + + if (!string.IsNullOrEmpty(shaderPerfData.compiledShaderPath)) + { + // Compile and create cache + shaderPerfData.isCompiledSuccessful = true; + string compiledShader; + if (!File.Exists(shaderPerfData.compiledShaderPath)) + { + shaderPerfData.isCompiledSuccessful = compiler.CompilePass(shaderPerfData, pass, shaderType, keywords.ToArray(), + out compiledShader); + IOHelper.WriteTextFile(shaderPerfData.compiledShaderPath, compiledShader); + } + else + { + compiledShader = IOHelper.ReadTextFile(shaderPerfData.compiledShaderPath); + } + + shaderPerfData.isCompiledSuccessful &= IOHelper.ExistAndNotEmpty(shaderPerfData.compiledShaderPath); + + // Analyze performance + if (shaderPerfData.isCompiledSuccessful) + { + shaderPerfData.stats = compiler.AnalyzeShaderPerformance(shaderPerfData, compiledShader); + + if (shaderPerfData.stats == null) + Debug.LogError($"LWGUI: Failed to Analyze Shader: {shader.name} | Subshader: {shaderPerfData.subshaderIndex} | Pass: {shaderPerfData.passName} | Stage: {shaderType}\n" + + $"Keywords: \n{string.Join('\n', keywords)}"); + } + else + { + Debug.LogError($"LWGUI: Failed to Compile Shader: {shader.name} | Subshader: {shaderPerfData.subshaderIndex} | Pass: {shaderPerfData.passName} | Stage: {shaderType}\n" + + $"Keywords: \n{string.Join('\n', keywords)}"); + } + } + else + { + Debug.LogError("LWGUI: Unable to get the compiled Shader path!"); + break; + } + } + + output.Add(shaderPerfData); + } + } + + return output; + } + + public static void ClearShaderPerfCache(Shader shader) + { + IOHelper.ClearShaderPerfCache(shader); + } + + private static IShaderCompiler _cachedActiveCompiler; + private static readonly object _compilerLock = new object(); + + public static IShaderCompiler GetActiveCompiler() + { + if (_cachedActiveCompiler != null) + return _cachedActiveCompiler; + + lock (_compilerLock) + { + if (_cachedActiveCompiler != null) + return _cachedActiveCompiler; + + var assembly = Assembly.GetExecutingAssembly(); + var compilerTypes = assembly.GetTypes() + .Where(t => !t.IsInterface && !t.IsAbstract && typeof(IShaderCompiler).IsAssignableFrom(t)) + .ToList(); + + Type bestType = null; + int bestPriority = int.MinValue; + + foreach (var compilerType in compilerTypes) + { + try + { + var isSupportProp = compilerType.GetProperty("isSupportCurrentPlatform", + BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + if (isSupportProp == null) + continue; + + bool isSupported = (bool)isSupportProp.GetValue(null); + if (!isSupported) + continue; + + var priorityProp = compilerType.GetProperty("priority", + BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + int priority = 0; + if (priorityProp != null) + { + try { priority = (int)priorityProp.GetValue(null); } catch { priority = 0; } + } + + if (bestType == null || priority > bestPriority) + { + bestType = compilerType; + bestPriority = priority; + } + } + catch (Exception e) + { + Debug.LogError($"LWGUI: Error inspecting compiler type {compilerType.Name}: {e.Message}"); + } + } + + if (bestType != null) + { + try + { + var instanceProp = bestType.GetProperty("instance", + BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + if (instanceProp != null) + { + var instance = instanceProp.GetValue(null) as IShaderCompiler; + if (instance != null) + { + _cachedActiveCompiler = instance; + return instance; + } + } + } + catch (Exception e) + { + Debug.LogError($"LWGUI: Error getting compiler instance of type {bestType.Name}: {e.Message}"); + } + } + + Debug.LogWarning("LWGUI: No supported shader compiler found!"); + return null; + } + } + + public static void ResetActiveCompiler() + { + lock (_compilerLock) + { + _cachedActiveCompiler = null; + } + } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfMonitor.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfMonitor.cs.meta new file mode 100644 index 000000000..e6bc48901 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/PerformanceMonitor/ShaderPerfMonitor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 626fb2fbefe34f578241fed5232ed380 +timeCreated: 1760615736 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/GradientObject.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/GradientObject.cs index 5c0da2ee6..515f073c4 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/GradientObject.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/GradientObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using System; using UnityEngine; diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiRampAtlas.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiRampAtlas.cs index 935a26789..c1ce475eb 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiRampAtlas.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiRampAtlas.cs @@ -1,4 +1,5 @@ // Copyright (c) Jason Ma + using System; using System.Collections.Generic; using System.IO; @@ -7,44 +8,186 @@ using LWGUI.LwguiGradientEditor; using LWGUI.Runtime.LwguiGradient; using UnityEngine; using UnityEditor; -using UnityEngine.Serialization; namespace LWGUI { - [CreateAssetMenu(fileName = "LWGUI_RampAtlas.asset", menuName = "LWGUI/Ramp Atlas", order = 84)] - public class LwguiRampAtlas : ScriptableObject + public interface IRamp { - [Serializable] - public class Ramp + string Name { get; set; } + ColorSpace ColorSpace { get; set; } + LwguiGradient.ChannelMask ChannelMask { get; set; } + LwguiGradient.GradientTimeRange TimeRange { get; set; } + + /// + /// Ramp contains at least one Gradient. + /// You can add more custom Gradients by overriding the virtual functions in LwguiRampAtlas. + /// + LwguiGradient Gradient { get; set; } + + /// + /// Get All Gradients. + /// + LwguiGradient[] GetGradients(); + + /// + /// Fill pixels for this Ramp into the output array. + /// + /// The output pixel array to fill + /// Current index in the output array, will be updated after filling + /// Width of each row in pixels + void GetPixelsForAtlas(ref Color[] outputPixels, ref int currentIndex, int width); + + /// + /// Get preview textures for this Ramp in Ramp Selector Window. + /// Returns multiple textures if the Ramp contains multiple gradients. + /// + /// Width of the preview texture + /// Array of preview textures + Texture2D[] GetPreviewTexturesForRampSelector(int width); + + /// + /// Copy properties from another Ramp. + /// + /// The source Ramp to copy from + void CopyFrom(IRamp source); + } + + [Serializable] + public class Ramp : IRamp + { + public string name = "New Ramp"; + public ColorSpace colorSpace = ColorSpace.Gamma; + public LwguiGradient.ChannelMask channelMask = LwguiGradient.ChannelMask.All; + public LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One; + public LwguiGradient gradient = LwguiGradient.white; + + // IRamp interface implementation using explicit properties that wrap the fields + string IRamp.Name { get => name; set => name = value; } + ColorSpace IRamp.ColorSpace { get => colorSpace; set => colorSpace = value; } + LwguiGradient.ChannelMask IRamp.ChannelMask { get => channelMask; set => channelMask = value; } + LwguiGradient.GradientTimeRange IRamp.TimeRange { get => timeRange; set => timeRange = value; } + LwguiGradient IRamp.Gradient { get => gradient; set => gradient = value; } + + /// + /// The number of rows this Ramp type occupies in the Ramp Atlas Texture. + /// This is a static value bound to the type. Derived classes can hide this with 'new static'. + /// + public static int RowCount => 1; + + public virtual LwguiGradient[] GetGradients() => new[] { gradient }; + + public virtual void GetPixelsForAtlas(ref Color[] outputPixels, ref int currentIndex, int width) { - public string name = "New Ramp"; - public LwguiGradient gradient = LwguiGradient.white; - public ColorSpace colorSpace = ColorSpace.Gamma; - public LwguiGradient.ChannelMask channelMask = LwguiGradient.ChannelMask.All; - public LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One; + var gradients = GetGradients(); + for (int i = 0; i < gradients.Length; i++) + { + gradients[i]?.GetPixels(ref outputPixels, ref currentIndex, width, 1, channelMask); + } } - - public const string RampAtlasSOExtensionName = "asset"; + + public virtual Texture2D[] GetPreviewTexturesForRampSelector(int width) + { + var gradients = GetGradients(); + var textures = new Texture2D[gradients.Length]; + for (int i = 0; i < gradients.Length; i++) + { + textures[i] = gradients[i]?.GetPreviewRampTexture(width, 1, colorSpace, channelMask); + } + return textures; + } + + public virtual void CopyFrom(IRamp source) + { + if (source == null) return; + + name = source.Name; + colorSpace = source.ColorSpace; + channelMask = source.ChannelMask; + timeRange = source.TimeRange; + gradient = new LwguiGradient(source.Gradient); + + var gradients = GetGradients(); + for (int i = 1; i < gradients.Length; i++) + { + if (gradients[i] == null) + continue; + + gradients[i].DeepCopyFrom(source.Gradient); + } + } + } + + [CreateAssetMenu(fileName = "LWGUI_RampAtlas.asset", menuName = "LWGUI/Ramp Atlas", order = 84)] + public partial class LwguiRampAtlas : ScriptableObject + { + public const string RampAtlasSOExtensionName = "asset"; public const string RampAtlasTextureExtensionName = "tga"; + + public int rampAtlasWidth = 256; + public int rampAtlasHeight = 4; + public bool rampAtlasSRGB = true; - public int rampAtlasWidth = 256; - public int rampAtlasHeight = 4; - public bool rampAtlasSRGB = true; + private string _rampAtlasSOPath = string.Empty; + private string _rampAtlasTexturePath = string.Empty; + + [SerializeField] private bool _saveTextureToggle; + [SerializeField] private List _ramps = new List(); [NonSerialized] public Texture2D rampAtlasTexture = null; - - [SerializeField] private List _ramps = new List(); - public List ramps - { - get => _ramps ?? new List(); - set => _ramps = value ?? new List(); + #region Ramp Operate + + /// + /// Access the list of Ramps as IRamp interface. This property uses covariance (IReadOnlyList), + /// allowing derived classes to directly return their strongly-typed lists without type conversion. + /// Override this property in derived classes to return a custom Ramp list. + /// + public virtual IReadOnlyList Ramps => _ramps ??= new List(); + + public virtual int RowCountPerRamp => Ramp.RowCount; + + public int RampCount => Ramps.Count; + + public int TotalRowCount => RampCount * RowCountPerRamp; + + public virtual IRamp CreateRamp(IRamp srcRamp = null) + { + var newRamp = new Ramp(); + if (srcRamp != null) + newRamp.CopyFrom(srcRamp); + return newRamp; } - [SerializeField] private bool _saveTextureToggle; - private string _rampAtlasSOPath = string.Empty; - private string _rampAtlasTexturePath = string.Empty; + public virtual IRamp AddRamp(IRamp srcRamp = null) + { + _ramps ??= new List(); + var newRamp = CreateRamp(srcRamp); + _ramps.Add(newRamp as Ramp); + return newRamp; + } + + public virtual IRamp GetRamp(int index) + { + if (index < RampCount && index >= 0) + { + return Ramps[index]; + } + return null; + } + + public virtual void ClearRamps() + { + _ramps?.Clear(); + } + + public void CheckRampRowCount() + { + if (TotalRowCount > rampAtlasHeight) + Debug.LogError($"LWGUI: Ramp Atlas does NOT have enough height ({rampAtlasHeight} < {TotalRowCount}):\n{_rampAtlasSOPath}"); + } + + #endregion public void InitData() { @@ -59,12 +202,16 @@ namespace LWGUI { if (!AssetDatabase.Contains(this)) return false; - + // Try to load rampAtlasTexture = AssetDatabase.LoadAssetAtPath(_rampAtlasTexturePath); // Create - if (!rampAtlasTexture) + if (!rampAtlasTexture + || rampAtlasTexture.width != rampAtlasWidth + || rampAtlasTexture.height != rampAtlasHeight + || rampAtlasTexture.isDataSRGB != rampAtlasSRGB + ) { CreateRampAtlasTexture(); rampAtlasTexture = AssetDatabase.LoadAssetAtPath(_rampAtlasTexturePath); @@ -72,69 +219,51 @@ namespace LWGUI if (!rampAtlasTexture) { - Debug.LogError($"LWGUI: Can NOT create a Ramp Atlas Texture at path: { _rampAtlasTexturePath }"); + Debug.LogError($"LWGUI: Can NOT create a Ramp Atlas Texture at path: {_rampAtlasTexturePath}"); return false; } + CheckRampRowCount(); + return true; } - public Color[] GetPixels() + public virtual Color[] GetPixels() { - Color[] pixels = Enumerable.Repeat(Color.white, rampAtlasWidth * rampAtlasHeight).ToArray(); + var pixels = Enumerable.Repeat(Color.white, rampAtlasWidth * rampAtlasHeight).ToArray(); int currentIndex = 0; - foreach (var ramp in ramps) + foreach (var ramp in Ramps) { - ramp.gradient.GetPixels(ref pixels, ref currentIndex, rampAtlasWidth, 1, ramp.channelMask); + ramp?.GetPixelsForAtlas(ref pixels, ref currentIndex, rampAtlasWidth); } return pixels; } - public Texture2D[] GetTexture2Ds(LwguiGradient.ChannelMask channelMask = LwguiGradient.ChannelMask.All) - { - Texture2D[] textures = new Texture2D[ramps.Count]; - for (int i = 0; i < ramps.Count; i++) - { - var ramp = ramps[i]; - textures[i] = Instantiate(ramp.gradient?.GetPreviewRampTexture(rampAtlasWidth, 1, ramp.colorSpace, ramp.channelMask & channelMask)); - textures[i].name = ramp.name; - } - - return textures; - } - - public Ramp GetRamp(int index) - { - if (index < ramps.Count && index >= 0) - { - return ramps[index] ?? new Ramp(); - } - return null; - } - public void CreateRampAtlasTexture() { - var rampAtlasTexture = new Texture2D(rampAtlasWidth, rampAtlasHeight, TextureFormat.RGBA32, false, !rampAtlasSRGB); - rampAtlasTexture.SetPixels(GetPixels()); - rampAtlasTexture.wrapMode = TextureWrapMode.Clamp; - rampAtlasTexture.name = Path.GetFileName(_rampAtlasTexturePath); - rampAtlasTexture.Apply(); + var rampAtlas = new Texture2D(rampAtlasWidth, rampAtlasHeight, TextureFormat.RGBA32, false, !rampAtlasSRGB); + rampAtlas.SetPixels(GetPixels()); + rampAtlas.wrapMode = TextureWrapMode.Clamp; + rampAtlas.name = Path.GetFileName(_rampAtlasTexturePath); + rampAtlas.Apply(); - SaveTexture(rampAtlasTexture); + SaveTexture(rampAtlas, checkoutAndForceWrite:true); AssetDatabase.ImportAsset(_rampAtlasTexturePath); RampHelper.SetRampTextureImporter(_rampAtlasTexturePath, true, !rampAtlasSRGB, EditorJsonUtility.ToJson(this)); } - public void SaveTexture(Texture2D rampAtlasTexture = null, string targetRelativePath = null, bool checkoutAndForceWrite = false) + public void SaveTexture(Texture2D rampAtlas = null, string targetRelativePath = null, bool checkoutAndForceWrite = false) { targetRelativePath ??= _rampAtlasTexturePath; - rampAtlasTexture ??= this.rampAtlasTexture; - if (!rampAtlasTexture || string.IsNullOrEmpty(targetRelativePath)) + rampAtlas ??= rampAtlasTexture; + if (!rampAtlas || string.IsNullOrEmpty(targetRelativePath)) return; - var absPath = Helper.ProjectPath + targetRelativePath; + CheckRampRowCount(); + + var absPath = IOHelper.GetAbsPath(targetRelativePath); if (File.Exists(absPath)) { var existRampTexture = AssetDatabase.LoadAssetAtPath(targetRelativePath); @@ -144,7 +273,7 @@ namespace LWGUI { if (!VersionControlHelper.Checkout(targetRelativePath)) { - Debug.LogError($"LWGUI: Can NOT write the Ramp Atlas Texture to path: { absPath }"); + Debug.LogError($"LWGUI: Can NOT write the Ramp Atlas Texture to path: {absPath}"); return; } } @@ -157,10 +286,10 @@ namespace LWGUI try { - File.WriteAllBytes(absPath, rampAtlasTexture.EncodeToTGA()); + File.WriteAllBytes(absPath, rampAtlas.EncodeToTGA()); SaveTextureUserData(targetRelativePath); - - Debug.Log($"LWGUI: Saved the Ramp Atlas Texture at path: { absPath }"); + + Debug.Log($"LWGUI: Saved the Ramp Atlas Texture at path: {absPath}"); } catch (Exception e) { @@ -191,58 +320,26 @@ namespace LWGUI { if (!rampAtlasTexture) return; - + LwguiGradientWindow.RegisterSerializedObjectUndo(this); rampAtlasTexture.Reinitialize(rampAtlasWidth, rampAtlasHeight); rampAtlasTexture.SetPixels(GetPixels()); rampAtlasTexture.Apply(); } - + public void DiscardChanges() { var importer = AssetImporter.GetAtPath(_rampAtlasTexturePath); if (!importer) return; - + EditorJsonUtility.FromJsonOverwrite(importer.userData, this); InitData(); AssetDatabase.ImportAsset(_rampAtlasTexturePath, ImportAssetOptions.ForceUpdate); LoadTexture(); EditorUtility.ClearDirty(this); } - - public void ConvertColorSpace(ColorSpace targetColorSpace) - { - foreach (var ramp in ramps) - { - if (ramp.colorSpace != targetColorSpace) - { - ramp.colorSpace = targetColorSpace; - ramp.gradient.ConvertColorSpaceWithoutCopy( - targetColorSpace != ColorSpace.Gamma - ? ColorSpace.Linear - : ColorSpace.Gamma); - } - } - - rampAtlasSRGB = targetColorSpace == ColorSpace.Gamma; - RampHelper.SetRampTextureImporter(_rampAtlasTexturePath, true, !rampAtlasSRGB, EditorJsonUtility.ToJson(this)); - UpdateTexturePixels(); - SaveTexture(); - } - [ContextMenu("Convert Gamma To Linear")] - public void ConvertGammaToLinear() - { - ConvertColorSpace(ColorSpace.Linear); - } - - [ContextMenu("Convert Linear To Gamma")] - public void ConvertLinearToGamma() - { - ConvertColorSpace(ColorSpace.Gamma); - } - private void OnEnable() { InitData(); @@ -253,18 +350,21 @@ namespace LWGUI { // Skip at the end of compilation if (Event.current == null - // Skip when editing Text Field - || EditorGUIUtility.editingTextField) + // Skip when editing Text Field + || EditorGUIUtility.editingTextField) return; - + InitData(); - + if (!LoadTexture()) return; UpdateTexturePixels(); - SaveTexture(); + SaveTexture(checkoutAndForceWrite:_saveTextureToggle); + _saveTextureToggle = false; } + + #region Static public static Texture LoadRampAtlasTexture(LwguiRampAtlas rampAtlasSO) { @@ -272,11 +372,11 @@ namespace LWGUI { return null; } - + var soPath = Path.ChangeExtension(AssetDatabase.GetAssetPath(rampAtlasSO), RampAtlasTextureExtensionName); return AssetDatabase.LoadAssetAtPath(soPath); } - + public static LwguiRampAtlas LoadRampAtlasSO(Texture texture) { if (!texture || !AssetDatabase.Contains(texture)) @@ -287,17 +387,17 @@ namespace LWGUI var soPath = Path.ChangeExtension(AssetDatabase.GetAssetPath(texture), RampAtlasSOExtensionName); return AssetDatabase.LoadAssetAtPath(soPath); } - - public static LwguiRampAtlas CreateRampAtlasSO(MaterialProperty rampAtlasProp, LWGUIMetaDatas metaDatas) + + public static LwguiRampAtlas CreateRampAtlasSO(MaterialProperty rampAtlasProp, LWGUIMetaDatas metaDatas, Type rampAtlasType = null) { if (rampAtlasProp == null || metaDatas == null) return null; var shader = metaDatas.GetShader(); - + // Get default ramps RampAtlasDrawer targetRampAtlasDrawer = null; - List<(int defaultIndex, RampAtlasIndexerDrawer indexerDrawer)> defaultRampAtlasIndexerDrawers = new (); + List<(int defaultIndex, RampAtlasIndexerDrawer indexerDrawer)> defaultRampAtlasIndexerDrawers = new(); // Unity Bug: The cache of MaterialPropertyHandler must be cleared first, otherwise the default value cannot be obtained correctly. ReflectionHelper.InvalidatePropertyCache(shader); for (int i = 0; i < metaDatas.perMaterialData.defaultPropertiesWithPresetOverride.Length; i++) @@ -309,19 +409,25 @@ namespace LWGUI if (drawer is RampAtlasDrawer rampAtlasDrawer && prop.name == rampAtlasProp.name) targetRampAtlasDrawer = rampAtlasDrawer; - + if (drawer is RampAtlasIndexerDrawer rampAtlasIndexerDrawer && rampAtlasIndexerDrawer.rampAtlasPropName == rampAtlasProp.name) defaultRampAtlasIndexerDrawers.Add(((int)prop.GetNumericValue(), rampAtlasIndexerDrawer)); } - + if (targetRampAtlasDrawer == null) { - Debug.LogError($"LWGUI: Can NOT find RampAtlasDrawer { rampAtlasProp.name } in Shader { shader }"); + Debug.LogError($"LWGUI: Can NOT find RampAtlasDrawer {rampAtlasProp.name} in Shader {shader}"); + return null; + } + + // Init Ramp Atlas with custom type or default type + rampAtlasType ??= typeof(LwguiRampAtlas); + var newRampAtlasSO = ScriptableObject.CreateInstance(rampAtlasType) as LwguiRampAtlas; + if (newRampAtlasSO == null) + { + Debug.LogError($"LWGUI: Failed to create RampAtlas of type '{rampAtlasType.Name}'"); return null; } - - // Init Ramp Atlas - var newRampAtlasSO = ScriptableObject.CreateInstance(); newRampAtlasSO.name = targetRampAtlasDrawer.defaultFileName; newRampAtlasSO.rampAtlasWidth = targetRampAtlasDrawer.defaultAtlasWidth; newRampAtlasSO.rampAtlasHeight = targetRampAtlasDrawer.defaultAtlasHeight; @@ -335,36 +441,50 @@ namespace LWGUI var maxIndex = defaultRampAtlasIndexerDrawers.Max((tuple => tuple.defaultIndex)); for (int i = 0; i < maxIndex + 1; i++) { - newRampAtlasSO.ramps.Add(new LwguiRampAtlas.Ramp()); - if (newRampAtlasSO.ramps.Count >= newRampAtlasSO.rampAtlasHeight) + newRampAtlasSO.AddRamp(); + if (newRampAtlasSO.TotalRowCount > newRampAtlasSO.rampAtlasHeight) newRampAtlasSO.rampAtlasHeight *= 2; } - + // Set Ramps Default Value for (int i = 0; i < defaultRampAtlasIndexerDrawers.Count; i++) { var defaultRampAtlasIndexerDrawer = defaultRampAtlasIndexerDrawers[i]; - var ramp = newRampAtlasSO.ramps[defaultRampAtlasIndexerDrawer.defaultIndex]; + var ramp = newRampAtlasSO.GetRamp(defaultRampAtlasIndexerDrawer.defaultIndex); var drawer = defaultRampAtlasIndexerDrawer.indexerDrawer; - ramp.name = drawer.defaultRampName; - ramp.colorSpace = drawer.colorSpace; - ramp.channelMask = drawer.viewChannelMask; - ramp.timeRange = drawer.timeRange; + ramp.Name = drawer.defaultRampName; + ramp.ColorSpace = drawer.colorSpace; + ramp.ChannelMask = drawer.viewChannelMask; + ramp.TimeRange = drawer.timeRange; } } return SaveRampAtlasSOToAsset(newRampAtlasSO, targetRampAtlasDrawer.rootPath, targetRampAtlasDrawer.defaultFileName); } - public static LwguiRampAtlas CloneRampAtlasSO(LwguiRampAtlas rampAtlasSO) + public static LwguiRampAtlas CloneRampAtlasSO(LwguiRampAtlas rampAtlasSO, Type targetType = null) { if (!rampAtlasSO) return null; - var newRampAtlasSO = Instantiate(rampAtlasSO); var rootPath = Path.GetDirectoryName(rampAtlasSO._rampAtlasSOPath); var defaultFileName = Path.GetFileName(rampAtlasSO._rampAtlasSOPath); + LwguiRampAtlas newRampAtlasSO; + + // If target type is specified and different from source type, use ConvertToType + if (targetType != null && targetType != rampAtlasSO.GetType()) + { + // Use ConvertToType for type conversion + newRampAtlasSO = ConvertToType(rampAtlasSO, targetType, false); + return newRampAtlasSO; + } + else + { + // Same type, use Instantiate for direct clone + newRampAtlasSO = Instantiate(rampAtlasSO); + } + if (SaveRampAtlasSOToAsset(newRampAtlasSO, rootPath, defaultFileName)) { newRampAtlasSO.InitData(); @@ -374,7 +494,7 @@ namespace LWGUI return null; } - + public static LwguiRampAtlas SaveRampAtlasSOToAsset(LwguiRampAtlas rampAtlasSO, string rootPath, string defaultFileName) { if (!rampAtlasSO) @@ -387,15 +507,15 @@ namespace LWGUI // TODO: Warning: // PropertiesGUI() is being called recursively. If you want to render the default gui for shader properties then call PropertiesDefaultGUI() instead var absPath = EditorUtility.SaveFilePanel("Create a Ramp Atlas SO", rootPath, defaultFileName, "asset"); - - if (absPath.StartsWith(Helper.ProjectPath)) + + if (absPath.StartsWith(IOHelper.ProjectPath)) { - createdFileRelativePath = absPath.Replace(Helper.ProjectPath, string.Empty); + createdFileRelativePath = IOHelper.GetRelativePath(absPath); break; } else if (absPath != string.Empty) { - var retry = EditorUtility.DisplayDialog("Invalid Path", "Please select the subdirectory of '" + Helper.ProjectPath + "'", "Retry", "Cancel"); + var retry = EditorUtility.DisplayDialog("Invalid Path", $"Please select the subdirectory of '{IOHelper.ProjectPath}'", "Retry", "Cancel"); if (!retry) break; } else @@ -403,7 +523,7 @@ namespace LWGUI break; } } - + if (!string.IsNullOrEmpty(createdFileRelativePath)) { AssetDatabase.CreateAsset(rampAtlasSO, createdFileRelativePath); @@ -411,8 +531,126 @@ namespace LWGUI rampAtlasSO.LoadTexture(); return rampAtlasSO; } - + return null; } + #endregion + + #region Context Menu + + public void ConvertColorSpace(ColorSpace targetColorSpace) + { + foreach (var ramp in Ramps) + { + if (ramp.ColorSpace != targetColorSpace) + { + ramp.ColorSpace = targetColorSpace; + foreach (var gradient in ramp.GetGradients()) + { + gradient?.ConvertColorSpaceWithoutCopy( + targetColorSpace != ColorSpace.Gamma + ? ColorSpace.Linear + : ColorSpace.Gamma); + } + } + } + + rampAtlasSRGB = targetColorSpace == ColorSpace.Gamma; + RampHelper.SetRampTextureImporter(_rampAtlasTexturePath, true, !rampAtlasSRGB, EditorJsonUtility.ToJson(this)); + UpdateTexturePixels(); + SaveTexture(checkoutAndForceWrite:true); + } + + [ContextMenu("Convert Gamma To Linear")] + public void ConvertGammaToLinear() + { + ConvertColorSpace(ColorSpace.Linear); + } + + [ContextMenu("Convert Linear To Gamma")] + public void ConvertLinearToGamma() + { + ConvertColorSpace(ColorSpace.Gamma); + } + + #endregion + + + #region Conversion Utilities + + /// + /// Convert an existing LwguiRampAtlas asset to a custom derived type. + /// The new asset will be created at the same location with a suffix. + /// For custom Ramp types with additional Gradients, the extra Gradients will be copied from the default Gradient. + /// + public static LwguiRampAtlas ConvertToType(LwguiRampAtlas source, Type targetType, bool saveToAsset = true, string suffix = "_Converted") + { + if (source == null) + { + Debug.LogError("LWGUI: Source RampAtlas is null"); + return null; + } + + if (targetType == null || !typeof(LwguiRampAtlas).IsAssignableFrom(targetType)) + { + Debug.LogError($"LWGUI: Target type must be derived from LwguiRampAtlas"); + return null; + } + + // Create new instance of target type + var newAtlas = ScriptableObject.CreateInstance(targetType) as LwguiRampAtlas; + if (newAtlas == null) + { + Debug.LogError($"LWGUI: Failed to create instance of type '{targetType.Name}'"); + return null; + } + + // Copy basic properties + newAtlas.rampAtlasWidth = source.rampAtlasWidth; + newAtlas.rampAtlasHeight = source.rampAtlasHeight; + newAtlas.rampAtlasSRGB = source.rampAtlasSRGB; + + // Convert each Ramp using CopyFrom interface + foreach (var sourceRamp in source.Ramps) + { + if (sourceRamp == null) continue; + + var newRamp = newAtlas.AddRamp(); + newRamp?.CopyFrom(sourceRamp); + } + + // Adjust height if needed + while (newAtlas.TotalRowCount > newAtlas.rampAtlasHeight) + { + newAtlas.rampAtlasHeight *= 2; + } + + if (!saveToAsset) + return newAtlas; + + // Save as new asset + var sourcePath = AssetDatabase.GetAssetPath(source); + if (string.IsNullOrEmpty(sourcePath)) + { + Debug.LogWarning("LWGUI: Source RampAtlas is not a saved asset"); + return newAtlas; + } + + var directory = Path.GetDirectoryName(sourcePath); + var fileName = Path.GetFileNameWithoutExtension(sourcePath); + var newPath = Path.Combine(directory, fileName + suffix + "." + RampAtlasSOExtensionName); + newPath = AssetDatabase.GenerateUniqueAssetPath(newPath); + + var result = SaveRampAtlasSOToAsset(newAtlas, directory, Path.GetFileNameWithoutExtension(newPath)); + + if (result != null) + Debug.Log($"LWGUI: Successfully converted RampAtlas to '{targetType.Name}' at: {newPath}"); + else + Debug.LogError($"LWGUI: Conversion of RampAtlas to '{targetType.Name}' failed at: {newPath}"); + + return result; + } + + #endregion } -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiShaderPropertyPreset.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiShaderPropertyPreset.cs index 6276e7a74..74d7d4b21 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiShaderPropertyPreset.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ScriptableObject/LwguiShaderPropertyPreset.cs @@ -283,18 +283,25 @@ namespace LWGUI if (presets == null) return null; - if (index < presets.Count) - { + if (index < presets.Count && index >= 0) return presets[index]; - } - else - { - Debug.LogError($"LWGUI: Index ({ index }) is out of range when accessing PresetFile: { name }"); - return null; - } + + Debug.LogError($"LWGUI: Index ({ index }) is out of range when accessing PresetFile: { name }"); + return null; } - public Preset GetPreset(float index) => GetPreset((int)index); + public Preset TryGetPreset(int index) + { + if (presets == null) + return null; + + if (index < presets.Count && index >= 0) + return presets[index]; + + return null; + } + + public Preset TryGetPreset(float floatIndex) => TryGetPreset(Mathf.CeilToInt(floatIndex)); private void OnValidate() { diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawer.cs deleted file mode 100644 index 16ab8dcfa..000000000 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawer.cs +++ /dev/null @@ -1,2496 +0,0 @@ -// Copyright (c) Jason Ma - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using LWGUI.LwguiGradientEditor; -using LWGUI.Runtime; -using LWGUI.Runtime.LwguiGradient; -using LWGUI.Timeline; -using UnityEditor; -using UnityEngine; -using UnityEngine.Rendering; -using Object = UnityEngine.Object; - -namespace LWGUI -{ - #region Interfaces - public interface IBaseDrawer - { - void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) {} - - void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) {} - - void GetCustomContextMenus(GenericMenu menu, Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) {} - } - - public interface IPresetDrawer - { - LwguiShaderPropertyPreset.Preset GetActivePreset(MaterialProperty inProp, LwguiShaderPropertyPreset lwguiShaderPropertyPreset); - } - #endregion - - #region Metadata - public partial class PropertyStaticData - { - // Image - public Texture2D image; - - // Button - public List buttonDisplayNames = new(); - public List buttonCommands = new(); - public List buttonDisplayNameWidths = new(); - - // You can add more data that is determined during the initialization of the Drawer as a cache here, - // thereby avoiding the need to calculate it every frame in OnGUI(). - // >>>>>>>>>>>>>>>>>>>>>>>> Add new data here <<<<<<<<<<<<<<<<<<<<<<< - } - #endregion - - #region Basic Drawers - /// - /// Create a Folding Group - /// - /// group: group name (Default: Property Name) - /// keyword: keyword used for toggle, "_" = ignore, none or "__" = Property Name + "_ON", always Upper (Default: none) - /// default Folding State: "on" or "off" (Default: off) - /// default Toggle Displayed: "on" or "off" (Default: on) - /// preset File Name: "Shader Property Preset" asset name, see Preset() for detail (Default: none) - /// Target Property Type: Float, express Toggle value - /// - public class MainDrawer : MaterialPropertyDrawer, IBaseDrawer, IPresetDrawer - { - protected LWGUIMetaDatas metaDatas; - - private static readonly float _height = 28f; - - private bool _isFolding; - private string _group; - private string _keyword; - private bool _defaultFoldingState; - private bool _defaultToggleDisplayed; - private string _presetFileName; - - public MainDrawer() : this(String.Empty) { } - - public MainDrawer(string group) : this(group, String.Empty) { } - - public MainDrawer(string group, string keyword) : this(group, keyword, "off") { } - - public MainDrawer(string group, string keyword, string defaultFoldingState) : this(group, keyword, defaultFoldingState, "on") { } - - public MainDrawer(string group, string keyword, string defaultFoldingState, string defaultToggleDisplayed) : this(group, keyword, defaultFoldingState, defaultToggleDisplayed, String.Empty) { } - - public MainDrawer(string group, string keyword, string defaultFoldingState, string defaultToggleDisplayed, string presetFileName) - { - this._group = group; - this._keyword = keyword; - this._defaultFoldingState = Helper.StringToBool(defaultFoldingState); - this._defaultToggleDisplayed = Helper.StringToBool(defaultToggleDisplayed); - this._presetFileName = presetFileName; - } - - public virtual void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.groupName = _group; - inoutPropertyStaticData.isMain = true; - inoutPropertyStaticData.isExpanding = _defaultFoldingState; - PerShaderData.DecodeMetaDataFromDisplayName(inProp, inoutPropertyStaticData); - PresetDrawer.SetPresetAssetToStaticData(inoutPropertyStaticData, _presetFileName); - } - - public virtual void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) - { - inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = inDefaultProp.floatValue > 0 ? "On" : "Off"; - } - - public LwguiShaderPropertyPreset.Preset GetActivePreset(MaterialProperty inProp, LwguiShaderPropertyPreset lwguiShaderPropertyPreset) => - PresetDrawer.GetActivePresetFromFloatProperty(inProp, lwguiShaderPropertyPreset); - - public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - metaDatas = Helper.GetLWGUIMetadatas(editor); - - var showMixedValue = EditorGUI.showMixedValue; - EditorGUI.showMixedValue = prop.hasMixedValue; - EditorGUI.BeginChangeCheck(); - - bool toggleResult = Helper.DrawFoldout(position, ref metaDatas.GetPropStaticData(prop).isExpanding, !Helper.Approximately(prop.floatValue, 0), _defaultToggleDisplayed, label); - - if (Helper.EndChangeCheck(metaDatas, prop)) - { - prop.floatValue = toggleResult ? 1.0f : 0.0f; - var keyword = Helper.GetKeywordName(_keyword, prop.name); - Helper.SetShaderKeywordEnabled(editor.targets, keyword, toggleResult); - PresetHelper.GetPresetAsset(_presetFileName)?.GetPreset(prop.floatValue)?.ApplyToEditingMaterial(editor, metaDatas.perMaterialData); - TimelineHelper.SetKeywordToggleToTimeline(prop, editor, keyword); - } - EditorGUI.showMixedValue = showMixedValue; - } - - // Call in custom shader gui - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - return _height; - } - - // Call when create/edit/undo materials, used to set keywords and presets - public override void Apply(MaterialProperty prop) - { - base.Apply(prop); - if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) - { - Helper.SetShaderKeywordEnabled(prop.targets, Helper.GetKeywordName(_keyword, prop.name), prop.floatValue > 0f); - PresetDrawer.ApplyPreset(_presetFileName, prop); - } - } - } - - /// - /// Draw a property with default style in the folding group - /// - /// group: parent group name (Default: none) - /// Target Property Type: Any - /// - public class SubDrawer : MaterialPropertyDrawer, IBaseDrawer - { - public string group = String.Empty; - public LWGUIMetaDatas metaDatas; - - public SubDrawer() { } - - public SubDrawer(string group) - { - this.group = group; - } - - protected virtual bool IsMatchPropType(MaterialProperty property) { return true; } - - protected virtual float GetVisibleHeight(MaterialProperty prop) - { - var height = MaterialEditor.GetDefaultPropertyHeight(prop); - return prop.GetPropertyType() == ShaderPropertyType.Vector ? EditorGUIUtility.singleLineHeight : height; - } - - public virtual void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.groupName = group; - PerShaderData.DecodeMetaDataFromDisplayName(inProp, inoutPropertyStaticData); - } - - public virtual void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) { } - - public virtual void GetCustomContextMenus(GenericMenu menu, Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) { } - - public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - metaDatas = Helper.GetLWGUIMetadatas(editor); - - if (IsMatchPropType(prop)) - { - DrawProp(position, prop, label, editor); - } - else - { - Debug.LogWarning("LWGUI: Property:'" + prop.name + "' Type:'" + prop.GetPropertyType() + "' mismatch!"); - editor.DefaultShaderProperty(position, prop, label.text); - } - } - - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - return GetVisibleHeight(prop); - } - - // Draws a custom style property - public virtual void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - RevertableHelper.FixGUIWidthMismatch(prop.GetPropertyType(), editor); - editor.DefaultShaderPropertyInternal(position, prop, label); - } - } - #endregion - - #region Extra Drawers - - #region Numeric - /// - /// Similar to builtin Toggle() - /// - /// group: parent group name (Default: none) - /// keyword: keyword used for toggle, "_" = ignore, none or "__" = Property Name + "_ON", always Upper (Default: none) - /// preset File Name: "Shader Property Preset" asset name, see Preset() for detail (Default: none) - /// Target Property Type: Float - /// - public class SubToggleDrawer : SubDrawer, IPresetDrawer - { - private string _keyWord = String.Empty; - private string _presetFileName = String.Empty; - - public SubToggleDrawer() { } - - public SubToggleDrawer(string group) : this(group, String.Empty, String.Empty) { } - - public SubToggleDrawer(string group, string keyWord) : this(group, keyWord, String.Empty) { } - - public SubToggleDrawer(string group, string keyWord, string presetFileName) - { - this.group = group; - this._keyWord = keyWord; - this._presetFileName = presetFileName; - } - - protected override bool IsMatchPropType(MaterialProperty property) - { - return property.GetPropertyType() is ShaderPropertyType.Float; - } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); - PresetDrawer.SetPresetAssetToStaticData(inoutPropertyStaticData, _presetFileName); - } - - public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) - { - inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = inDefaultProp.floatValue > 0 ? "On" : "Off"; - } - - public LwguiShaderPropertyPreset.Preset GetActivePreset(MaterialProperty inProp, LwguiShaderPropertyPreset lwguiShaderPropertyPreset) => - PresetDrawer.GetActivePresetFromFloatProperty(inProp, lwguiShaderPropertyPreset); - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - var value = EditorGUI.Toggle(position, label, !Helper.Approximately(prop.floatValue, 0)); - if (Helper.EndChangeCheck(metaDatas, prop)) - { - prop.floatValue = value ? 1.0f : 0.0f; - var keyword = Helper.GetKeywordName(_keyWord, prop.name); - Helper.SetShaderKeywordEnabled(editor.targets, keyword, value); - PresetHelper.GetPresetAsset(_presetFileName)?.GetPreset(prop.floatValue)?.ApplyToEditingMaterial(editor, metaDatas.perMaterialData); - TimelineHelper.SetKeywordToggleToTimeline(prop, editor, keyword); - } - EditorGUI.showMixedValue = false; - } - - public override void Apply(MaterialProperty prop) - { - base.Apply(prop); - if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) - { - Helper.SetShaderKeywordEnabled(prop.targets, Helper.GetKeywordName(_keyWord, prop.name), prop.floatValue > 0f); - PresetDrawer.ApplyPreset(_presetFileName, prop); - } - } - } - - /// - /// Similar to builtin PowerSlider() - /// - /// group: parent group name (Default: none) - /// power: power of slider (Default: 1) - /// Target Property Type: Range - /// - public class SubPowerSliderDrawer : SubDrawer - { - private float _power = 1; - - public SubPowerSliderDrawer(float power) : this("_", power) { } - - public SubPowerSliderDrawer(string group, float power) - { - this.group = group; - this._power = Mathf.Clamp(power, 0, float.MaxValue); - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Range; } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - RevertableHelper.FixGUIWidthMismatch(prop.GetPropertyType(), editor); - EditorGUI.showMixedValue = prop.hasMixedValue; - var rect = position; - ReflectionHelper.DoPowerRangeProperty(rect, prop, label, _power); - EditorGUI.showMixedValue = false; - } - } - - /// - /// Similar to builtin IntRange() - /// - /// group: parent group name (Default: none) - /// Target Property Type: Range - /// - public class SubIntRangeDrawer : SubDrawer - { - public SubIntRangeDrawer(string group) - { - this.group = group; - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Range; } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - RevertableHelper.FixGUIWidthMismatch(prop.GetPropertyType(), editor); - - if (prop.GetPropertyType() != ShaderPropertyType.Range) - { - EditorGUI.LabelField(position, "IntRange used on a non-range property: " + prop.name, EditorStyles.helpBox); - } - else - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - float labelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 0.0f; - int num = EditorGUI.IntSlider(position, label, (int)prop.floatValue, (int)prop.rangeLimits.x, (int)prop.rangeLimits.y); - EditorGUI.showMixedValue = false; - EditorGUIUtility.labelWidth = labelWidth; - if (Helper.EndChangeCheck(metaDatas, prop)) - { - prop.floatValue = num; - } - } - } - } - - /// - /// Draw a min max slider - /// - /// group: parent group name (Default: none) - /// minPropName: Output Min Property Name - /// maxPropName: Output Max Property Name - /// Target Property Type: Range, range limits express the MinMaxSlider value range - /// Output Min/Max Property Type: Range, it's value is limited by it's range - /// - public class MinMaxSliderDrawer : SubDrawer - { - private string _minPropName; - private string _maxPropName; - - public MinMaxSliderDrawer(string minPropName, string maxPropName) : this("_", minPropName, maxPropName) { } - - public MinMaxSliderDrawer(string group, string minPropName, string maxPropName) - { - this.group = group; - this._minPropName = minPropName; - this._maxPropName = maxPropName; - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Range; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); - inoutPropertyStaticData.AddExtraProperty(_minPropName); - inoutPropertyStaticData.AddExtraProperty(_maxPropName); - } - - public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) - { - if (string.IsNullOrEmpty(_minPropName) - || string.IsNullOrEmpty(_maxPropName) - || !inoutPerMaterialData.propDynamicDatas.ContainsKey(_minPropName) - || !inoutPerMaterialData.propDynamicDatas.ContainsKey(_maxPropName) - ) - { - Debug.LogError("LWGUI: " + inProp.name + " has no available min/max properties!"); - return; - } - - inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = - inoutPerMaterialData.propDynamicDatas[_minPropName].defualtProperty.floatValue - + " - " - + inoutPerMaterialData.propDynamicDatas[_maxPropName].defualtProperty.floatValue; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - // read min max - MaterialProperty minProp = metaDatas.GetProperty(_minPropName); - MaterialProperty maxProp = metaDatas.GetProperty(_maxPropName); - if (minProp == null || maxProp == null) - { - Debug.LogError("LWGUI: MinMaxSliderDrawer: minProp: " + (minProp == null ? "null" : minProp.name) + " or maxProp: " + (maxProp == null ? "null" : maxProp.name) + " not found!"); - return; - } - float minf = minProp.floatValue; - float maxf = maxProp.floatValue; - - // define draw area - Rect controlRect = position; // this is the full length rect area - var w = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 0; - Rect inputRect = MaterialEditor.GetRectAfterLabelWidth(controlRect); // this is the remaining rect area after label's area - - // draw label - EditorGUI.PrefixLabel(controlRect, label); - - // draw min max slider - var indentLevel = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - Rect[] splittedRect = Helper.SplitRect(inputRect, 3); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = minProp.hasMixedValue; - var newMinf = EditorGUI.FloatField(splittedRect[0], minf); - if (Helper.EndChangeCheck(metaDatas, minProp)) - { - minf = Mathf.Clamp(newMinf, minProp.rangeLimits.x, minProp.rangeLimits.y); - minProp.floatValue = minf; - } - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = maxProp.hasMixedValue; - var newMaxf = EditorGUI.FloatField(splittedRect[2], maxf); - if (Helper.EndChangeCheck(metaDatas, maxProp)) - { - maxf = Mathf.Clamp(newMaxf, maxProp.rangeLimits.x, maxProp.rangeLimits.y); - maxProp.floatValue = maxf; - } - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - if (splittedRect[1].width > 50f) - EditorGUI.MinMaxSlider(splittedRect[1], ref minf, ref maxf, prop.rangeLimits.x, prop.rangeLimits.y); - EditorGUI.showMixedValue = false; - - // write back min max if changed - if (EditorGUI.EndChangeCheck()) - { - minProp.floatValue = Mathf.Clamp(minf, minProp.rangeLimits.x, minProp.rangeLimits.y); - maxProp.floatValue = Mathf.Clamp(maxf, maxProp.rangeLimits.x, maxProp.rangeLimits.y); - } - - EditorGUI.indentLevel = indentLevel; - EditorGUIUtility.labelWidth = w; - } - } - - /// - /// Similar to builtin Enum() / KeywordEnum() - /// - /// group: parent group name (Default: none) - /// n(s): display name - /// k(s): keyword - /// v(s): value - /// Target Property Type: Float, express current keyword index - /// - public class KWEnumDrawer : SubDrawer - { - private GUIContent[] _names; - private string[] _keyWords; - private float[] _values; - - - #region - - public KWEnumDrawer(string n1, string k1) - : this("_", new string[1] { n1 }, new string[1] { k1 }) { } - - public KWEnumDrawer(string n1, string k1, string n2, string k2) - : this("_", new string[2] { n1, n2 }, new string[2] { k1, k2 }) { } - - public KWEnumDrawer(string n1, string k1, string n2, string k2, string n3, string k3) - : this("_", new string[3] { n1, n2, n3 }, new string[3] { k1, k2, k3 }) { } - - public KWEnumDrawer(string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4) - : this("_", new string[4] { n1, n2, n3, n4 }, new string[4] { k1, k2, k3, k4 }) { } - - public KWEnumDrawer(string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4, string n5, string k5) - : this("_", new string[5] { n1, n2, n3, n4, n5 }, new string[5] { k1, k2, k3, k4, k5 }) { } - - public KWEnumDrawer(string group, string n1, string k1) - : this(group, new string[1] { n1 }, new string[1] { k1 }) { } - - public KWEnumDrawer(string group, string n1, string k1, string n2, string k2) - : this(group, new string[2] { n1, n2 }, new string[2] { k1, k2 }) { } - - public KWEnumDrawer(string group, string n1, string k1, string n2, string k2, string n3, string k3) - : this(group, new string[3] { n1, n2, n3 }, new string[3] { k1, k2, k3 }) { } - - public KWEnumDrawer(string group, string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4) - : this(group, new string[4] { n1, n2, n3, n4 }, new string[4] { k1, k2, k3, k4 }) { } - - public KWEnumDrawer(string group, string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4, string n5, string k5) - : this(group, new string[5] { n1, n2, n3, n4, n5 }, new string[5] { k1, k2, k3, k4, k5 }) { } - - #endregion - - - public KWEnumDrawer(string group, string[] names, string[] keyWords = null, float[] values = null) - { - Init(group, names, keyWords, values); - } - - protected void Init(string group, string[] names, string[] keyWords, float[] values) - { - this.group = group; - - this._names = new GUIContent[names.Length]; - for (int index = 0; index < names.Length; ++index) - this._names[index] = new GUIContent(names[index]); - - if (keyWords == null) - { - keyWords = new string[names.Length]; - for (int i = 0; i < names.Length; i++) - keyWords[i] = String.Empty; - } - this._keyWords = keyWords; - - if (values == null) - { - values = new float[names.Length]; - for (int index = 0; index < names.Length; ++index) - values[index] = index; - } - this._values = values; - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() is ShaderPropertyType.Float; } - - protected virtual string GetKeywordName(string propName, string name) { return (name).Replace(' ', '_').ToUpperInvariant(); } - - public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) - { - var index = Array.IndexOf(_values, (int)inDefaultProp.floatValue); - if (index < _names.Length && index >= 0) - inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = _names[index].text; - } - - private string[] GetKeywords(MaterialProperty property) - { - string[] keyWords = new string[_keyWords.Length]; - for (int i = 0; i < keyWords.Length; i++) - keyWords[i] = GetKeywordName(property.name, _keyWords[i]); - return keyWords; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - - var rect = position; - - string[] keyWords = GetKeywords(prop); - int index = Array.IndexOf(_values, prop.floatValue); - if (index < 0) - { - Debug.LogError("LWGUI: Property: " + prop.name + " has unknown Enum Value: '" + prop.floatValue + "' !\n"); - return; - } - - Helper.AdaptiveFieldWidth(EditorStyles.popup, _names[index]); - int newIndex = EditorGUI.Popup(rect, label, index, _names); - EditorGUI.showMixedValue = false; - if (Helper.EndChangeCheck(metaDatas, prop)) - { - prop.floatValue = _values[newIndex]; - Helper.SelectShaderKeyword(editor.targets, keyWords, newIndex); - } - } - - public override void Apply(MaterialProperty prop) - { - base.Apply(prop); - if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) - { - Helper.SelectShaderKeyword(prop.targets, GetKeywords(prop), (int)prop.floatValue); - } - } - } - - public class SubEnumDrawer : KWEnumDrawer - { - // UnityEditor.MaterialEnumDrawer(string enumName) - // enumName: like "UnityEngine.Rendering.BlendMode" - public SubEnumDrawer(string group, string enumName) : base(group, enumName) - { - var array = ReflectionHelper.GetAllTypes(); - try - { - Type enumType = array.FirstOrDefault(x => x.IsSubclassOf(typeof(Enum)) && (x.Name == enumName || x.FullName == enumName)); - string[] names = Enum.GetNames(enumType); - Array valuesArray = Enum.GetValues(enumType); - var values = new float[valuesArray.Length]; - for (int index = 0; index < valuesArray.Length; ++index) - values[index] = (int)valuesArray.GetValue(index); - Init(group, names, null, values); - } - catch (Exception ex) - { - Debug.LogWarningFormat("LWGUI: Failed to create SubEnum, enum {0} not found, {1}.", enumName, ex); - throw; - } - } - - public SubEnumDrawer(string group, string n1, float v1, string n2, float v2) - : base(group, new[] { n1, n2 }, null, new[] { v1, v2 }) { } - - public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3) - : base(group, new[] { n1, n2, n3 }, null, new[] { v1, v2, v3 }) { } - - public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4) - : base(group, new[] { n1, n2, n3, n4 }, null, new[] { v1, v2, v3, v4 }) { } - - public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5) - : base(group, new[] { n1, n2, n3, n4, n5 }, null, new[] { v1, v2, v3, v4, v5 }) { } - - public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6) - : base(group, new[] { n1, n2, n3, n4, n5, n6 }, null, new[] { v1, v2, v3, v4, v5, v6 }) { } - - public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7) - : base(group, new[] { n1, n2, n3, n4, n5, n6, n7 }, null, new[] { v1, v2, v3, v4, v5, v6, v7 }) { } - - protected override string GetKeywordName(string propName, string name) { return "_"; } - - public override void Apply(MaterialProperty prop) { } - } - - public class SubKeywordEnumDrawer : KWEnumDrawer - { - public SubKeywordEnumDrawer(string group, string kw1, string kw2) - : base(group, new[] { kw1, kw2 }, new[] { kw1, kw2 }) { } - - public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3) - : base(group, new[] { kw1, kw2, kw3 }, new[] { kw1, kw2, kw3 }) { } - - public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4) - : base(group, new[] { kw1, kw2, kw3, kw4 }, new[] { kw1, kw2, kw3, kw4 }) { } - - public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5) - : base(group, new[] { kw1, kw2, kw3, kw4, kw5 }, new[] { kw1, kw2, kw3, kw4, kw5 }) { } - - public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6) - : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6 }) { } - - public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7) - : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7 }) { } - - public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7, string kw8) - : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8 }) { } - - public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7, string kw8, string kw9) - : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8, kw9 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8, kw9 }) { } - - protected override string GetKeywordName(string propName, string name) { return (propName + "_" + name).Replace(' ', '_').ToUpperInvariant(); } - } - - /// - /// Popping a menu, you can select the Shader Property Preset, the Preset values will replaces the default values - /// - /// group: parent group name (Default: none) - /// presetFileName: "Shader Property Preset" asset name, you can create new Preset by - /// "Right Click > Create > LWGUI > Shader Property Preset" in Project window, - /// *any Preset in the entire project cannot have the same name* - /// Target Property Type: Float, express current keyword index - /// - public class PresetDrawer : SubDrawer, IPresetDrawer - { - public string presetFileName; - - public PresetDrawer(string presetFileName) : this("_", presetFileName) { } - - public PresetDrawer(string group, string presetFileName) - { - this.group = group; - this.presetFileName = presetFileName; - } - - public static void SetPresetAssetToStaticData(PropertyStaticData inoutPropertyStaticData, string presetFileName) - { - inoutPropertyStaticData.propertyPresetAsset = PresetHelper.GetPresetAsset(presetFileName); - } - - public static LwguiShaderPropertyPreset.Preset GetActivePresetFromFloatProperty(MaterialProperty inProp, LwguiShaderPropertyPreset lwguiShaderPropertyPreset) - { - LwguiShaderPropertyPreset.Preset preset = null; - var index = (int)inProp.floatValue; - if (lwguiShaderPropertyPreset && index >= 0 && index < lwguiShaderPropertyPreset.GetPresetCount()) - { - preset = lwguiShaderPropertyPreset.GetPreset(index); - } - return preset; - } - - public static void ApplyPreset(string presetFileName, MaterialProperty prop) - { - var presetFile = PresetHelper.GetPresetAsset(presetFileName); - if (presetFile != null - && prop.floatValue < presetFile.GetPresetCount() - && ShowIfDecorator.GetShowIfResultToFilterDrawerApplying(prop) - ) - { - presetFile.GetPreset(prop.floatValue)?.ApplyKeywordsAndPassesToMaterials(prop.targets); - } - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Float; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); - SetPresetAssetToStaticData(inoutPropertyStaticData, presetFileName); - } - - public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) - { - var index = (int)inDefaultProp.floatValue; - var propertyPreset = inPerShaderData.propStaticDatas[inProp.name].propertyPresetAsset; - - if (propertyPreset && index < propertyPreset.GetPresetCount() && index >= 0) - inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = propertyPreset.GetPreset(index).presetName; - } - - public LwguiShaderPropertyPreset.Preset GetActivePreset(MaterialProperty inProp, LwguiShaderPropertyPreset lwguiShaderPropertyPreset) => - GetActivePresetFromFloatProperty(inProp, lwguiShaderPropertyPreset); - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - - var rect = position; - - int index = (int)Mathf.Max(0, prop.floatValue); - var presetFile = PresetHelper.GetPresetAsset(presetFileName); - if (presetFile == null || presetFile.GetPresetCount() == 0) - { - Helper.DrawShaderPropertyWithErrorLabel(rect, prop, label, editor, $"Invalid Preset File: {presetFileName}"); - return; - } - - if (index < presetFile.GetPresetCount()) - { - var presetNames = presetFile.GetPresets().Select((inPreset) => new GUIContent(inPreset.presetName)).ToArray(); - if (EditorGUI.showMixedValue) - index = -1; - else - Helper.AdaptiveFieldWidth(EditorStyles.popup, presetNames[index]); - int newIndex = EditorGUI.Popup(rect, label, index, presetNames); - if (Helper.EndChangeCheck(metaDatas, prop)) - { - prop.floatValue = newIndex; - presetFile.GetPreset(newIndex).ApplyToEditingMaterial(editor, metaDatas.perMaterialData); - } - EditorGUI.showMixedValue = false; - } - else - { - Helper.DrawShaderPropertyWithErrorLabel(position, prop, label, editor, $"Out of Index Range"); - Debug.LogError($"LWGUI: { prop.name } out of Preset index range!"); - } - - } - - public override void Apply(MaterialProperty prop) - { - base.Apply(prop); - if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) - { - ApplyPreset(presetFileName, prop); - } - } - } - - /// - /// Draw the Int value as a Bit Mask. - /// Note: - /// - Currently only 8 bits are supported. - /// - /// Warning 1: If used to set Stencil, it will conflict with SRP Batcher! - /// (Reproduced in Unity 2022) - /// SRP Batcher does not correctly handle multiple materials with different Stencil Ref values, - /// mistakenly merging them into a single Batch and randomly selecting one material's Stencil Ref value for the entire Batch. - /// In theory, if different materials have different Stencil Ref values, they should not be merged into a single Batch due to differing Render States. - /// Solution: - /// - Force disable SRP Batcher by setting the Material Property Block - /// - Place materials with the same Stencil Ref value in a separate Render Queue to ensure the Batch's Render State is correct - /// - /// Warning 2: Once in use, do not change the Target Property Type! - /// The underlying type of Int Property is Float Property, and in Materials, Int and Integer are stored separately. - /// Once a Material is saved, the Property Type is determined. - /// If you change the Property Type at this point (such as switching between Int/Integer), some strange bugs may occur. - /// If you must change the Property Type, it is recommended to modify the Property Name as well or delete the saved Property in the material. - /// - /// group: parent group name (Default: none) - /// bitDescription 7-0: Description of each Bit. (Default: none) - /// Target Property Type: Int/Integer - /// - public class BitMaskDrawer : SubDrawer - { - public int bitCount = 8; - - public float maxHeight = EditorGUIUtility.singleLineHeight; - - public List buttonLables = new (); - - public List buttonWidths = new(); - - public List buttonStyles = new(); - - public float totalButtonWidth; - - private static readonly int _hint = "BitMask".GetHashCode(); - - private static readonly float _minButtonWidth = 25; - - private static readonly float _buttonPadding = 1.0f; - - public BitMaskDrawer() : this(string.Empty, null) { } - - public BitMaskDrawer(string group) : this(group, null) { } - - public BitMaskDrawer(string group, string bitDescription7, string bitDescription6, string bitDescription5, string bitDescription4, string bitDescription3, string bitDescription2, string bitDescription1, string bitDescription0) - : this(group, new List() { bitDescription0, bitDescription1, bitDescription2, bitDescription3, bitDescription4, bitDescription5, bitDescription6, bitDescription7 }) { } - - public BitMaskDrawer(string group, List bitDescriptions) - { - this.group = group; - - bitCount = Mathf.Clamp(bitCount, 1, 16); - - for (int i = 0; i < bitCount; i++) - { - var description = bitDescriptions != null && bitDescriptions.Count > i ? bitDescriptions[i] : string.Empty; - buttonLables.Add(new GUIContent( - string.IsNullOrEmpty(description) ? i.ToString() : i + "\n" + description)); - buttonWidths.Add(Mathf.Max(_minButtonWidth, EditorStyles.miniButton.CalcSize(buttonLables[i]).x)); - - if (!string.IsNullOrEmpty(description)) - maxHeight = EditorGUIUtility.singleLineHeight * 2; - } - - for (int i = 0; i < bitCount; i++) - { - if (i == 0) - buttonStyles.Add(new GUIStyle(EditorStyles.miniButtonRight)); - else if (i == bitCount - 1) - buttonStyles.Add(new GUIStyle(EditorStyles.miniButtonLeft)); - else - buttonStyles.Add(new GUIStyle(EditorStyles.miniButton)); - - buttonStyles[i].fixedHeight = maxHeight; - } - - totalButtonWidth = buttonWidths.Sum(); - } - - protected override bool IsMatchPropType(MaterialProperty property) - => property.GetPropertyType() is ShaderPropertyType.Float or ShaderPropertyType.Int; - - protected override float GetVisibleHeight(MaterialProperty prop) { return maxHeight; } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - label.tooltip += $"\nCurrent Value: { prop.GetNumericValue() }"; - - int controlId = GUIUtility.GetControlID(_hint, FocusType.Keyboard, position); - var fieldRect = EditorGUI.PrefixLabel(position, controlId, label); - - if (position.width < totalButtonWidth) - return; - - fieldRect.xMin = fieldRect.xMax; - - for (int i = 0; i < bitCount; i++) - { - fieldRect.xMin = fieldRect.xMax - buttonWidths[i]; - var buttonLable = buttonLables[i]; - var active = RuntimeHelper.IsBitEnabled((int)prop.GetNumericValue(), i); - var style = buttonStyles[i]; - var buttonRect = fieldRect; - - if (i > 0 && i < bitCount - 1) - { - buttonRect.xMin -= _buttonPadding; - buttonRect.xMax += _buttonPadding * 2; - } - - if (style.richText = prop.hasMixedValue) - { - // https://docs.unity3d.com/2021.3/Documentation/Manual/StyledText.html - buttonLable = new GUIContent($"{ buttonLable.text }"); - } - - if (Helper.ToggleButton(buttonRect, buttonLable, active, style, _buttonPadding * 1.5f)) - { - prop.SetNumericValue(RuntimeHelper.SetBitEnabled((int)prop.GetNumericValue(), i, !active)); - } - - fieldRect.xMax = fieldRect.xMin; - } - } - } - - /// - /// Visually similar to Ramp(), but RampAtlasIndexer() must be used together with RampAtlas(). - /// The actual stored value is the index of the current Ramp in the Ramp Atlas SO, used for sampling the Ramp Atlas Texture in the Shader. - /// - /// group: parent group name. - /// rampAtlasPropName: RampAtlas() property name. - /// defaultRampName: default ramp name. (Default: Ramp) - /// colorSpace: default ramp color space. (sRGB/Linear) (Default: sRGB) - /// viewChannelMask: editable channels. (Default: RGBA) - /// timeRange: the abscissa display range (1/24/2400), is used to optimize the editing experience when the abscissa is time of day. (Default: 1) - /// Target Property Type: Float - /// - public class RampAtlasIndexerDrawer : RampDrawer - { - public string rampAtlasPropName = string.Empty; - public string defaultRampName = "Ramp"; - - private LwguiRampAtlas _rampAtlasSO; - public LwguiRampAtlas rampAtlasSO - { - get - { - if (!_rampAtlasSO) - { - var rampAtlasProp = metaDatas.GetProperty(rampAtlasPropName); - if (rampAtlasProp != null && rampAtlasProp.GetPropertyType() == ShaderPropertyType.Texture) - { - _rampAtlasSO = LwguiRampAtlas.LoadRampAtlasSO(rampAtlasProp.textureValue); - } - } - return _rampAtlasSO; - } - - set => _rampAtlasSO = value; - } - - private LwguiRampAtlas.Ramp _currentRamp; - private bool _rampAtlasSOHasMixedValue; - - public RampAtlasIndexerDrawer(string group, string rampAtlasPropName) : this(group, rampAtlasPropName, "Ramp") {} - - public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName) : this(group, rampAtlasPropName, defaultRampName, "sRGB") {} - - public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName, string colorSpace) : this(group, rampAtlasPropName, defaultRampName, colorSpace, "RGBA") {} - - public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName, string colorSpace, string viewChannelMask) : this(group, rampAtlasPropName, defaultRampName, colorSpace, viewChannelMask, 1) {} - - public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName, string colorSpace, string viewChannelMask, float timeRange) - { - this.group = group; - this.rampAtlasPropName = rampAtlasPropName; - this.defaultRampName = defaultRampName; - this.colorSpace = colorSpace.ToLower() == "linear" ? ColorSpace.Linear : ColorSpace.Gamma; - this.viewChannelMask = LwguiGradient.ChannelMask.None; - { - viewChannelMask = viewChannelMask.ToLower(); - for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) - { - if (viewChannelMask.Contains(LwguiGradient.channelNames[c])) - this.viewChannelMask |= LwguiGradient.ChannelIndexToMask(c); - } - } - this.timeRange = LwguiGradient.GradientTimeRange.One; - { - if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFour) - this.timeRange = LwguiGradient.GradientTimeRange.TwentyFour; - else if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFourHundred) - this.timeRange = LwguiGradient.GradientTimeRange.TwentyFourHundred; - } - } - - protected override bool IsMatchPropType(MaterialProperty property) => property.GetPropertyType() is ShaderPropertyType.Float or ShaderPropertyType.Int; - - protected override void OnRampPropUpdate(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - if (doRegisterUndo) - OnGradientEditorChange(null); - } - - protected override void OnGradientEditorChange(LwguiGradient gradient) - { - LwguiGradientWindow.RegisterSerializedObjectUndo(rampAtlasSO); - } - - protected override void OnEditRampMap(MaterialProperty prop, LwguiGradient gradient) - { - rampAtlasSO?.UpdateTexturePixels(); - OnGradientEditorChange(null); - } - - protected override void OnSaveRampMap(MaterialProperty prop, LwguiGradient gradient) - { - rampAtlasSO?.SaveTexture(checkoutAndForceWrite:true); - rampAtlasSO?.SaveRampAtlasSO(); - } - - protected override LwguiGradient GetLwguiGradient(MaterialProperty prop, out bool isDirty) - { - isDirty = false; - if (rampAtlasSO && (int)prop.GetNumericValue() < rampAtlasSO.ramps.Count) - { - _currentRamp = rampAtlasSO.GetRamp((int)prop.GetNumericValue()); - if (_currentRamp == null) - return null; - - isDirty = EditorUtility.IsDirty(rampAtlasSO); - colorSpace = _currentRamp.colorSpace; - viewChannelMask = _currentRamp.channelMask; - timeRange = _currentRamp.timeRange; - return _currentRamp.gradient; - } - else - return null; - } - - protected override void CreateNewRampMap(MaterialProperty prop, MaterialEditor editor) - { - // Create a Ramp - if (rampAtlasSO) - { - var newIndex = rampAtlasSO.ramps.Count; - - rampAtlasSO.ramps.Add(new LwguiRampAtlas.Ramp() - { - name = defaultRampName, - gradient = LwguiGradient.white, - colorSpace = colorSpace, - channelMask = viewChannelMask, - timeRange = timeRange - }); - - prop.SetNumericValue(newIndex); - if (newIndex >= rampAtlasSO.rampAtlasHeight) - rampAtlasSO.rampAtlasHeight *= 2; - rampAtlasSO.UpdateTexturePixels(); - } - // Create a Ramp Atlas SO - else - { - var rampAtlasProp = metaDatas.GetProperty(rampAtlasPropName); - var newRampAtlasSO = LwguiRampAtlas.CreateRampAtlasSO(rampAtlasProp, metaDatas); - if (newRampAtlasSO) - { - rampAtlasSO = newRampAtlasSO; - rampAtlasProp.textureValue = rampAtlasSO?.rampAtlasTexture; - } - } - } - - protected override void SwitchRampMap(MaterialProperty prop, Texture2D newRampMap, int index) - { - prop.SetNumericValue(index); - OnSwitchRampMap(prop, newRampMap, index); - LWGUI.OnValidate(metaDatas); - } - - protected override LwguiGradient DiscardRampMap(MaterialProperty prop, LwguiGradient gradient) - { - rampAtlasSO?.DiscardChanges(); - _currentRamp = rampAtlasSO?.GetRamp((int)prop.GetNumericValue()); - return _currentRamp?.gradient; - } - - protected override void DrawRampSelector(Rect selectButtonRect, MaterialProperty prop, LwguiGradient gradient) - { - if (!_rampAtlasSOHasMixedValue) - RampHelper.RampIndexSelectorOverride(selectButtonRect, prop, rampAtlasSO, SwitchRampMap); - } - - protected override void DrawRampObjectField(Rect rampFieldRect, MaterialProperty prop, LwguiGradient gradient) - { - if (rampAtlasSO && !_rampAtlasSOHasMixedValue) - EditorGUI.ObjectField(rampFieldRect, gradient?.GetPreviewRampTexture(), typeof(Texture2D), false); - else - { - EditorGUI.BeginChangeCheck(); - var newRampAtlasSO = EditorGUI.ObjectField(rampFieldRect, rampAtlasSO, typeof(LwguiRampAtlas), false) as LwguiRampAtlas; - if (EditorGUI.EndChangeCheck()) - { - rampAtlasSO = newRampAtlasSO; - metaDatas.GetProperty(rampAtlasPropName).textureValue = rampAtlasSO?.rampAtlasTexture; - } - } - } - - protected override void DrawPreviewTextureOverride(Rect previewRect, MaterialProperty prop, LwguiGradient gradient) - { - if (gradient != null && !EditorGUI.showMixedValue) - LwguiGradientEditorHelper.DrawGradientWithSeparateAlphaChannel(previewRect, gradient, colorSpace, viewChannelMask); - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - var rampAtlasProp = metaDatas.GetProperty(rampAtlasPropName); - if (rampAtlasProp == null || rampAtlasProp.GetPropertyType() != ShaderPropertyType.Texture) - { - Helper.DrawShaderPropertyWithErrorLabel(position, prop, label, editor, "Invalid rampAtlasPropName"); - Debug.LogError($"LWGUI: Property { prop.name } has invalid rampAtlasPropName: { rampAtlasPropName }"); - return; - } - - // Add Info to label - var currentIndex = (int)prop.GetNumericValue(); - label.tooltip += $"\nCurrent Value: {currentIndex}"; - if (rampAtlasSO) - { - var isOutOfRange = currentIndex >= rampAtlasSO.ramps.Count; - var info = isOutOfRange ? "OUT OF RANGE!" : rampAtlasSO.ramps[currentIndex].name; - label.text += $" ({ currentIndex }: { info } - { rampAtlasSO.ramps.Count })"; - } - else - label.text += $" ({ currentIndex } - NULL)"; - - // Handle Mixed Value - _rampAtlasSOHasMixedValue = rampAtlasProp.hasMixedValue; - var showMixedValue = EditorGUI.showMixedValue; - EditorGUI.showMixedValue = prop.hasMixedValue || _rampAtlasSOHasMixedValue; - - - base.DrawProp(position, prop, label, editor); - - - // Clear - _rampAtlasSO = null; - _currentRamp = null; - EditorGUI.showMixedValue = showMixedValue; - } - } - - #endregion - - #region Texture - /// - /// Draw a Texture property in single line with a extra property - /// - /// group: parent group name (Default: none) - /// extraPropName: extra property name (Default: none) - /// Target Property Type: Texture - /// Extra Property Type: Color, Vector - /// Target Property Type: Texture2D - /// - public class TexDrawer : SubDrawer - { - private string _extraPropName = String.Empty; - private ChannelDrawer _channelDrawer = new ChannelDrawer(); - - public TexDrawer() { } - - public TexDrawer(string group) : this(group, String.Empty) { } - - public TexDrawer(string group, string extraPropName) - { - this.group = group; - this._extraPropName = extraPropName; - } - - protected override float GetVisibleHeight(MaterialProperty prop) { return EditorGUIUtility.singleLineHeight; } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Texture; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); - inoutPropertyStaticData.AddExtraProperty(_extraPropName); - } - - public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) - { - var defaultExtraProp = inoutPerMaterialData.GetPropDynamicData(_extraPropName)?.defualtProperty; - if (defaultExtraProp != null) - { - var text = string.Empty; - if (defaultExtraProp.GetPropertyType() == ShaderPropertyType.Vector) - text = ChannelDrawer.GetChannelName(defaultExtraProp); - else - text = RevertableHelper.GetPropertyDefaultValueText(defaultExtraProp); - - inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = - RevertableHelper.GetPropertyDefaultValueText(inDefaultProp) + ", " + text; - } - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - EditorGUI.showMixedValue = prop.hasMixedValue; - var rect = position; - - MaterialProperty extraProp = metaDatas.GetProperty(_extraPropName); - if (extraProp != null - // && ( - // extraProp.type == MaterialProperty.PropType.Color - // || extraProp.type == MaterialProperty.PropType.Vector - // ) - ) - { - var i = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - - var extraRect = MaterialEditor.GetRightAlignedFieldRect(rect); - extraRect.height = rect.height; - - if (extraProp.GetPropertyType() == ShaderPropertyType.Vector) - _channelDrawer.OnGUI(extraRect, extraProp, GUIContent.none, editor); - else - editor.ShaderProperty(extraRect, extraProp, GUIContent.none); - - EditorGUI.indentLevel = i; - } - - editor.TexturePropertyMiniThumbnail(rect, prop, label.text, label.tooltip); - - EditorGUI.showMixedValue = false; - } - } - - /// - /// Draw an unreal style Ramp Map Editor (Default Ramp Map Resolution: 256 * 2) - /// NEW: The new LwguiGradient type has both the Gradient and Curve editors, and can be used in C# scripts and runtime, and is intended to replace UnityEngine.Gradient - /// - /// group: parent group name (Default: none) - /// defaultFileName: default Ramp Map file name when create a new one (Default: RampMap) - /// rootPath: the path where ramp is stored, replace '/' with '.' (for example: Assets.Art.Ramps). when selecting ramp, it will also be filtered according to the path (Default: Assets) - /// colorSpace: switch sRGB / Linear in ramp texture import setting (Default: sRGB) - /// defaultWidth: default Ramp Width. (Default: 256) - /// viewChannelMask: editable channels. (Default: RGBA) - /// timeRange: the abscissa display range (1/24/2400), is used to optimize the editing experience when the abscissa is time of day. (Default: 1) - /// Target Property Type: Texture2D - /// - public class RampDrawer : SubDrawer - { - public static readonly string DefaultRootPath = "Assets"; - - public string rootPath = "Assets"; - public string saveFilePanelTitle = "Create New Ramp Texture"; - public string defaultFileName = "RampMap"; - public string fileExtension = "png"; - public int defaultWidth = 256; - public int defaultHeight = 2; - public ColorSpace colorSpace = ColorSpace.Gamma; - public LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All; - public LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One; - public bool doRegisterUndo; - - private static readonly GUIContent _iconMixImage = EditorGUIUtility.IconContent("darkviewbackground"); - - private static readonly float _rampPreviewHeight = EditorGUIUtility.singleLineHeight; - private static readonly float _rampButtonsHeight = EditorGUIUtility.singleLineHeight; - - protected override float GetVisibleHeight(MaterialProperty prop) { return _rampPreviewHeight + _rampButtonsHeight; } - - public RampDrawer() : this(String.Empty) { } - - public RampDrawer(string group) : this(group, "RampMap") { } - - public RampDrawer(string group, string defaultFileName) : this(group, defaultFileName, DefaultRootPath, 256) { } - - public RampDrawer(string group, string defaultFileName, float defaultWidth) : this(group, defaultFileName, DefaultRootPath, defaultWidth) { } - - public RampDrawer(string group, string defaultFileName, string rootPath, float defaultWidth) : this(group, defaultFileName, rootPath, "sRGB", defaultWidth) { } - - public RampDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, "RGBA") { } - - public RampDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, string viewChannelMask) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, viewChannelMask, 1) { } - - public RampDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, string viewChannelMask, float timeRange) - { - if (!rootPath.StartsWith(DefaultRootPath)) - { - Debug.LogError("LWGUI: Ramp Root Path: '" + rootPath + "' must start with 'Assets'!"); - rootPath = DefaultRootPath; - } - this.group = group; - this.defaultFileName = defaultFileName; - this.rootPath = rootPath.Replace('.', '/'); - this.colorSpace = colorSpace.ToLower() == "linear" ? ColorSpace.Linear : ColorSpace.Gamma; - this.defaultWidth = (int)Mathf.Max(2, defaultWidth); - this.viewChannelMask = LwguiGradient.ChannelMask.None; - { - viewChannelMask = viewChannelMask.ToLower(); - for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) - { - if (viewChannelMask.Contains(LwguiGradient.channelNames[c])) - this.viewChannelMask |= LwguiGradient.ChannelIndexToMask(c); - } - - if (this.viewChannelMask == (LwguiGradient.ChannelMask.RGB | LwguiGradient.ChannelMask.Alpha)) - this.viewChannelMask = LwguiGradient.ChannelMask.All; - } - this.timeRange = LwguiGradient.GradientTimeRange.One; - { - if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFour) - this.timeRange = LwguiGradient.GradientTimeRange.TwentyFour; - else if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFourHundred) - this.timeRange = LwguiGradient.GradientTimeRange.TwentyFourHundred; - } - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Texture; } - - protected virtual void OnRampPropUpdate(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } - - protected virtual void OnCreateNewRampMap(MaterialProperty prop) { } - - protected virtual void OnGradientEditorChange(LwguiGradient gradient) { } - - protected virtual void OnEditRampMap(MaterialProperty prop, LwguiGradient gradient) { } - - protected virtual void OnSaveRampMap(MaterialProperty prop, LwguiGradient gradient) { } - - protected virtual void OnDiscardRampMap(MaterialProperty prop, LwguiGradient gradient) { } - - protected virtual void OnSwitchRampMap(MaterialProperty prop, Texture2D newRampMap, int index) { } - - protected virtual LwguiGradient GetLwguiGradient(MaterialProperty prop, out bool isDirty) - { - return RampHelper.GetGradientFromTexture(prop.textureValue, out isDirty, false, doRegisterUndo); - } - - protected virtual void EditWhenNoRampMap(MaterialProperty prop, MaterialEditor editor) - { - LwguiGradientWindow.CloseWindow(); - CreateNewRampMap(prop, editor); - OnCreateNewRampMap(prop); - LWGUI.OnValidate(metaDatas); - } - - protected virtual void CreateNewRampMap(MaterialProperty prop, MaterialEditor editor) - { - string createdFileRelativePath = string.Empty; - while (true) - { - if (!Directory.Exists(Helper.ProjectPath + rootPath)) - Directory.CreateDirectory(Helper.ProjectPath + rootPath); - - // TODO: Warning: - // PropertiesGUI() is being called recursively. If you want to render the default gui for shader properties then call PropertiesDefaultGUI() instead - var absPath = EditorUtility.SaveFilePanel(saveFilePanelTitle, rootPath, defaultFileName, fileExtension); - - if (absPath.StartsWith(Helper.ProjectPath + rootPath)) - { - createdFileRelativePath = absPath.Replace(Helper.ProjectPath, string.Empty); - break; - } - else if (absPath != string.Empty) - { - var retry = EditorUtility.DisplayDialog("Invalid Path", "Please select the subdirectory of '" + Helper.ProjectPath + rootPath + "'", "Retry", "Cancel"); - if (!retry) break; - } - else - { - break; - } - } - - if (!string.IsNullOrEmpty(createdFileRelativePath)) - { - RampHelper.CreateAndSaveNewGradientTexture(defaultWidth, defaultHeight, createdFileRelativePath, colorSpace == ColorSpace.Linear); - prop.textureValue = AssetDatabase.LoadAssetAtPath(createdFileRelativePath); - } - } - - protected virtual void ChangeRampMap(MaterialProperty prop, LwguiGradient gradient) - { - RampHelper.SetGradientToTexture(prop.textureValue, gradient, false); - } - - protected virtual void SaveRampMap(MaterialProperty prop, LwguiGradient gradient) - { - RampHelper.SetGradientToTexture(prop.textureValue, gradient, true); - } - - protected virtual void SwitchRampMap(MaterialProperty prop, Texture2D newRampMap, int index) - { - prop.textureValue = newRampMap; - OnSwitchRampMap(prop, newRampMap, index); - LWGUI.OnValidate(metaDatas); - } - - protected virtual LwguiGradient DiscardRampMap(MaterialProperty prop, LwguiGradient gradient) - { - // Tex > Gradient - gradient = RampHelper.GetGradientFromTexture(prop.textureValue, out _, true); - // GradientObject > Tex - RampHelper.SetGradientToTexture(prop.textureValue, gradient, true); - return gradient; - } - - protected virtual void DrawRampSelector(Rect selectButtonRect, MaterialProperty prop, LwguiGradient gradient) - { - RampHelper.RampMapSelectorOverride(selectButtonRect, prop, rootPath, SwitchRampMap); - } - - // Manual replace ramp map - protected virtual void DrawRampObjectField(Rect rampFieldRect, MaterialProperty prop, LwguiGradient gradient) - { - EditorGUI.BeginChangeCheck(); - var newManualSelectedTexture = (Texture2D)EditorGUI.ObjectField(rampFieldRect, prop.textureValue, typeof(Texture2D), false); - if (Helper.EndChangeCheck(metaDatas, prop)) - { - if (newManualSelectedTexture && !AssetDatabase.GetAssetPath(newManualSelectedTexture).StartsWith(rootPath)) - EditorUtility.DisplayDialog("Invalid Path", "Please select the subdirectory of '" + rootPath + "'", "OK"); - else - SwitchRampMap(prop, newManualSelectedTexture, 0); - } - } - - protected virtual void DrawPreviewTextureOverride(Rect previewRect, MaterialProperty prop, LwguiGradient gradient) - { - if (!prop.hasMixedValue && gradient != null) - { - LwguiGradientEditorHelper.DrawGradientWithSeparateAlphaChannel(previewRect, gradient, colorSpace, viewChannelMask); - } - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - var labelWidth = EditorGUIUtility.labelWidth; - var indentLevel = EditorGUI.indentLevel; - - OnRampPropUpdate(position, prop, label, editor); - - var gradient = GetLwguiGradient(prop, out var isDirty); - - // Draw Label - var labelRect = new Rect(position); - { - labelRect.height = _rampPreviewHeight; - EditorGUI.PrefixLabel(labelRect, label); - } - - // Ramp buttons Rect - var buttonRect = new Rect(position); - { - EditorGUIUtility.labelWidth = 0; - EditorGUI.indentLevel = 0; - buttonRect.yMin = buttonRect.yMax - _rampPreviewHeight; - buttonRect = MaterialEditor.GetRectAfterLabelWidth(buttonRect); - if (buttonRect.width < 50f) return; - } - - // Draw Ramp Editor - RampHelper.RampEditor(buttonRect, ref gradient, colorSpace, viewChannelMask, timeRange, isDirty, - out bool hasGradientChanges, - out bool doEditWhenNoGradient, - out doRegisterUndo, - out bool doCreate, - out bool doSaveGradient, - out bool doDiscardGradient, - OnGradientEditorChange); - - // Edit When No Gradient - if (doEditWhenNoGradient) - { - EditWhenNoRampMap(prop, editor); - } - - // Create - if (doCreate) - { - LwguiGradientWindow.CloseWindow(); - CreateNewRampMap(prop, editor); - OnCreateNewRampMap(prop); - LWGUI.OnValidate(metaDatas); - } - - // Change - if (hasGradientChanges && gradient != null) - { - ChangeRampMap(prop, gradient); - OnEditRampMap(prop, gradient); - } - - // Save - if (doSaveGradient && gradient != null) - { - SaveRampMap(prop, gradient); - OnSaveRampMap(prop, gradient); - } - - // Discard - if (doDiscardGradient) - { - LwguiGradientWindow.CloseWindow(); - gradient = DiscardRampMap(prop, gradient); - OnDiscardRampMap(prop, gradient); - } - - // Texture Object Field, handle switch texture event - var rampFieldRect = MaterialEditor.GetRectAfterLabelWidth(labelRect); - var previewRect = new Rect(rampFieldRect.x + 0.5f, rampFieldRect.y + 0.5f, rampFieldRect.width - 18, rampFieldRect.height - 0.5f); - { - var selectButtonRect = new Rect(previewRect.xMax, rampFieldRect.y, rampFieldRect.width - previewRect.width, rampFieldRect.height); - DrawRampSelector(selectButtonRect, prop, gradient); - - DrawRampObjectField(rampFieldRect, prop, gradient); - } - - // Preview texture override (larger preview, hides texture name) - DrawPreviewTextureOverride(previewRect, prop, gradient); - - EditorGUIUtility.labelWidth = labelWidth; - EditorGUI.indentLevel = indentLevel; - } - } - - /// - /// Draw a "Ramp Atlas Scriptable Object" selector and texture preview. - /// The Ramp Atlas SO is responsible for storing multiple ramps and generating the corresponding Ramp Atlas Texture. - /// Use it together with RampAtlasIndexer() to sample specific ramps in Shader using Index, similar to UE's Curve Atlas. - /// Note: Currently, the material only saves Texture reference and Int value, - /// if you manually modify the Ramp Atlas, the references will not update automatically! - /// - /// group: parent group name (Default: none) - /// defaultFileName: the default file name when creating a Ramp Atlas SO (Default: RampAtlas) - /// rootPath: the default directory when creating a Ramp Atlas SO, replace '/' with '.' (for example: Assets.Art.RampAtlas). (Default: Assets) - /// colorSpace: the Color Space of Ramp Atlas Texture. (sRGB/Linear) (Default: sRGB) - /// defaultWidth: default Ramp Atlas Texture width (Default: 256) - /// showAtlasPreview: Draw the preview of Ramp Atlas below (True/False) (Default: True) - /// Target Property Type: Texture2D - /// - public class RampAtlasDrawer : SubDrawer - { - public string rootPath = "Assets"; - public string defaultFileName = "RampAtlas"; - public bool defaultAtlasSRGB = true; - public int defaultAtlasWidth = 256; - public int defaultAtlasHeight = 2; - public bool showAtlasPreview = true; - - protected LwguiRampAtlas _rampAtlasSO; - - public RampAtlasDrawer() : this(string.Empty) { } - - public RampAtlasDrawer(string group) : this(group, "RampAtlas") { } - - public RampAtlasDrawer(string group, string defaultFileName) : this(group, defaultFileName, "Assets") { } - - public RampAtlasDrawer(string group, string defaultFileName, string rootPath) : this(group, defaultFileName, rootPath, "sRGB") { } - - public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace) : this(group, defaultFileName, rootPath, colorSpace, 256) { } - - public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, 4) { } - - public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, float defaultHeight) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, defaultHeight, "true") { } - - public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, float defaultHeight, string showAtlasPreview) - { - if (!rootPath.StartsWith(this.rootPath)) - { - Debug.LogError("LWGUI: Ramp Atlas Root Path: '" + rootPath + "' must start with 'Assets'!"); - rootPath = this.rootPath; - } - this.group = group; - this.defaultFileName = defaultFileName; - this.rootPath = rootPath.Replace('.', '/'); - this.defaultAtlasSRGB = colorSpace.ToLower() == "srgb"; - this.defaultAtlasWidth = (int)Mathf.Max(2, defaultWidth); - this.defaultAtlasHeight = (int)Mathf.Max(2, defaultHeight); - this.showAtlasPreview = Helper.StringToBool(showAtlasPreview); - } - - protected override bool IsMatchPropType(MaterialProperty property) => property.GetPropertyType() == ShaderPropertyType.Texture; - - protected override float GetVisibleHeight(MaterialProperty prop) => - EditorGUIUtility.singleLineHeight + - (prop.textureValue && showAtlasPreview ? MaterialEditor.GetDefaultPropertyHeight(prop) + 2.0f : 0); - - public override void GetCustomContextMenus(GenericMenu menu, Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) - { - menu.AddSeparator(""); - menu.AddItem(new GUIContent("Create Ramp Atlas"), false, () => - { - _rampAtlasSO = LwguiRampAtlas.CreateRampAtlasSO(prop, metaDatas); - if (_rampAtlasSO) - { - prop.textureValue = _rampAtlasSO.rampAtlasTexture; - LWGUI.OnValidate(metaDatas); - } - }); - - if (_rampAtlasSO) - { - menu.AddItem(new GUIContent("Clone Ramp Atlas"), false, () => - { - var newRampAtlasSO = LwguiRampAtlas.CloneRampAtlasSO(_rampAtlasSO); - if (newRampAtlasSO) - { - _rampAtlasSO = newRampAtlasSO; - prop.textureValue = _rampAtlasSO.rampAtlasTexture; - LWGUI.OnValidate(metaDatas); - } - }); - } - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - EditorGUI.PrefixLabel(position, label); - - var labelWidth = EditorGUIUtility.labelWidth; - var indentLevel = EditorGUI.indentLevel; - EditorGUIUtility.labelWidth = 0; - EditorGUI.indentLevel = 0; - - var fieldRect = MaterialEditor.GetRectAfterLabelWidth(position); - var rampAtlasSORect = new Rect(fieldRect.x, fieldRect.y, fieldRect.width, EditorGUIUtility.singleLineHeight); - var rampAtlasTextureRect = new Rect(fieldRect.x, rampAtlasSORect.yMax + 2.0f, fieldRect.width, MaterialEditor.GetDefaultPropertyHeight(prop)); - - _rampAtlasSO = LwguiRampAtlas.LoadRampAtlasSO(prop.textureValue); - - // Disable ObjectField's Context Menu - var e = Event.current; - if (e?.type == EventType.MouseDown && Event.current.button == 1 - && (rampAtlasSORect.Contains(e.mousePosition))) - { - e.Use(); - } - - EditorGUI.BeginChangeCheck(); - _rampAtlasSO = (LwguiRampAtlas)EditorGUI.ObjectField(rampAtlasSORect, GUIContent.none, _rampAtlasSO, typeof(LwguiRampAtlas), false); - if (EditorGUI.EndChangeCheck()) - { - prop.textureValue = LwguiRampAtlas.LoadRampAtlasTexture(_rampAtlasSO); - - if (_rampAtlasSO && !prop.textureValue) - { - Debug.LogError($"LWGUI: Can NOT load the Ramp Atlas Texture from: { _rampAtlasSO.name }"); - } - } - - if (showAtlasPreview && prop.textureValue && !prop.hasMixedValue) - { - var filter = prop.textureValue.filterMode; - prop.textureValue.filterMode = FilterMode.Point; - EditorGUI.DrawPreviewTexture(rampAtlasTextureRect, prop.textureValue); - prop.textureValue.filterMode = filter; - } - } - } - - /// - /// Draw an image preview. - /// display name: The path of the image file relative to the Unity project, such as: "Assets/test.png", "Doc/test.png", "../test.png" - /// - /// group: parent group name (Default: none) - /// Target Property Type: Any - /// - public class ImageDrawer : SubDrawer - { - public ImageDrawer() { } - - public ImageDrawer(string group) - { - this.group = group; - } - - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - var imagePath = Application.dataPath.Substring(0, Application.dataPath.Length - 6) + inProp.displayName; - if (File.Exists(imagePath)) - { - var fileData = File.ReadAllBytes(imagePath); - Texture2D texture = new Texture2D(2, 2); - - // LoadImage will auto-resize the texture dimensions - if (texture.LoadImage(fileData)) - { - inoutPropertyStaticData.image = texture; - } - else - { - Debug.LogError($"LWGUI: Failed to load image data into texture: { imagePath }"); - } - } - else - { - Debug.LogError($"LWGUI: Image path not found: { imagePath }"); - } - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - var image = metaDatas.GetPropStaticData(prop).image; - if (image) - { - var scaledheight = Mathf.Max(0, image.height / (image.width / Helper.GetCurrentPropertyLayoutWidth())); - var rect = EditorGUILayout.GetControlRect(true, scaledheight); - rect = RevertableHelper.IndentRect(EditorGUI.IndentedRect(rect)); - EditorGUI.DrawPreviewTexture(rect, image); - - if (GUI.enabled) - prop.textureValue = null; - } - } - } - #endregion - - #region Vector - /// - /// Display up to 4 colors in a single line - /// - /// group: parent group name (Default: none) - /// color2-4: extra color property name - /// Target Property Type: Color - /// - public class ColorDrawer : SubDrawer - { - private string[] _colorStrings = new string[3]; - - public ColorDrawer(string group, string color2) : this(group, color2, String.Empty, String.Empty) { } - - public ColorDrawer(string group, string color2, string color3) : this(group, color2, color3, String.Empty) { } - - public ColorDrawer(string group, string color2, string color3, string color4) - { - this.group = group; - this._colorStrings[0] = color2; - this._colorStrings[1] = color3; - this._colorStrings[2] = color4; - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Color; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); - foreach (var colorPropName in _colorStrings) - { - inoutPropertyStaticData.AddExtraProperty(colorPropName); - } - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - var cProps = new Stack(); - for (int i = 0; i < 4; i++) - { - if (i == 0) - { - cProps.Push(prop); - continue; - } - - var p = metaDatas.GetProperty(_colorStrings[i - 1]); - if (p != null && IsMatchPropType(p)) - cProps.Push(p); - } - - var count = cProps.Count; - var colorArray = cProps.ToArray(); - - EditorGUI.PrefixLabel(position, label); - - for (int i = 0; i < count; i++) - { - EditorGUI.BeginChangeCheck(); - var cProp = colorArray[i]; - EditorGUI.showMixedValue = cProp.hasMixedValue; - var r = new Rect(position); - var interval = 13 * i * (-0.25f + EditorGUI.indentLevel * 1.25f); - var w = EditorGUIUtility.fieldWidth * (0.8f + EditorGUI.indentLevel * 0.2f); - r.xMin += r.width - w * (i + 1) + interval; - r.xMax -= w * i - interval; - - var src = cProp.colorValue; - var isHdr = (colorArray[i].GetPropertyFlags() & ShaderPropertyFlags.HDR) != ShaderPropertyFlags.None; - var dst = EditorGUI.ColorField(r, GUIContent.none, src, true, true, isHdr); - if (Helper.EndChangeCheck(metaDatas, cProp)) - { - cProp.colorValue = dst; - } - } - - EditorGUI.showMixedValue = false; - } - } - - /// - /// Draw a R/G/B/A drop menu: - /// R = (1, 0, 0, 0) - /// G = (0, 1, 0, 0) - /// B = (0, 0, 1, 0) - /// A = (0, 0, 0, 1) - /// RGB Average = (1f / 3f, 1f / 3f, 1f / 3f, 0) - /// RGB Luminance = (0.2126f, 0.7152f, 0.0722f, 0) - /// None = (0, 0, 0, 0) - /// - /// group: parent group name (Default: none) - /// Target Property Type: Vector, used to dot() with Texture Sample Value - /// - public class ChannelDrawer : SubDrawer - { - private static GUIContent[] _names = new[] - { - new GUIContent("R"), - new GUIContent("G"), - new GUIContent("B"), - new GUIContent("A"), - new GUIContent("RGB Average"), - new GUIContent("RGB Luminance"), - new GUIContent("None") - }; - private static int[] _intValues = new int[] { 0, 1, 2, 3, 4, 5, 6 }; - private static Vector4[] _vector4Values = new[] - { - new Vector4(1, 0, 0, 0), - new Vector4(0, 1, 0, 0), - new Vector4(0, 0, 1, 0), - new Vector4(0, 0, 0, 1), - new Vector4(1f / 3f, 1f / 3f, 1f / 3f, 0), - new Vector4(0.2126f, 0.7152f, 0.0722f, 0), - new Vector4(0, 0, 0, 0) - }; - - public ChannelDrawer() { } - - public ChannelDrawer(string group) - { - this.group = group; - } - - protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Vector; } - - private static int GetChannelIndex(MaterialProperty prop) - { - int index = -1; - for (int i = 0; i < _vector4Values.Length; i++) - { - if (prop.vectorValue == _vector4Values[i]) - index = i; - } - if (index == -1) - { - Debug.LogError("LWGUI: Channel Property: " + prop.name + " invalid vector found, reset to A"); - prop.vectorValue = _vector4Values[3]; - index = 3; - } - return index; - } - - public static string GetChannelName(MaterialProperty prop) - { - return _names[GetChannelIndex(prop)].text; - } - - public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) - { - inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = GetChannelName(inDefaultProp); - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - EditorGUI.BeginChangeCheck(); - - EditorGUI.showMixedValue = prop.hasMixedValue; - var index = GetChannelIndex(prop); - int num = EditorGUI.IntPopup(position, label, index, _names, _intValues); - EditorGUI.showMixedValue = false; - if (Helper.EndChangeCheck(metaDatas, prop)) - { - prop.vectorValue = _vector4Values[num]; - } - } - } - #endregion - - #region Other - /// - /// Draw one or more Buttons within the same row, using the Display Name to control the appearance and behavior of the buttons - /// - /// Declaring a set of Button Name and Button Command in Display Name generates a Button, separated by '@': - /// ButtonName0@ButtonCommand0@ButtonName1@ButtonCommand1 - /// - /// Button Name can be any other string, the format of Button Command is: - /// TYPE:Argument - /// - /// The following TYPEs are currently supported: - /// - URL: Open the URL, Argument is the URL - /// - C#: Call the public static C# function, Argument is NameSpace.Class.Method(arg0, arg1, ...), - /// for target function signatures, see: LWGUI.ButtonDrawer.TestMethod(). - /// - /// The full example: - /// [Button(_)] _button0 ("URL Button@URL:https://github.com/JasonMa0012/LWGUI@C#:LWGUI.ButtonDrawer.TestMethod(1234, abcd)", Float) = 0 - /// - /// group: parent group name (Default: none) - /// Target Property Type: Any - /// - public class ButtonDrawer : SubDrawer - { - private const string _urlPrefix = "URL:"; - private const string _csPrefix = "C#:"; - private const string _separator = "@"; - - public ButtonDrawer() { } - - public ButtonDrawer(string group) - { - this.group = group; - } - - protected override float GetVisibleHeight(MaterialProperty prop) => 24; - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.groupName = group; - - // Display Name: ButtonName@URL:XXX@ButtonName@CS:NameSpace.Class.Method(arg0, arg1, ...)@... - var buttonNameAndCommands = inProp.displayName.Split(_separator); - if (buttonNameAndCommands != null && buttonNameAndCommands.Length > 0 && buttonNameAndCommands.Length % 2 == 0) - { - for (int i = 0; i < buttonNameAndCommands.Length; i++) - { - if (i % 2 == 0) - { - inoutPropertyStaticData.buttonDisplayNames.Add(buttonNameAndCommands[i]); - inoutPropertyStaticData.buttonDisplayNameWidths.Add(EditorStyles.label.CalcSize(new GUIContent(buttonNameAndCommands[i])).x); - } - else - { - inoutPropertyStaticData.buttonCommands.Add(buttonNameAndCommands[i]); - } - } - } - else - { - Debug.LogError($"LWGUI: ButtonDrawer with invalid Display Name Commands: { buttonNameAndCommands } ! prop: { inProp.name }"); - } - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - var buttonDisplayNames = metaDatas.GetPropStaticData(prop).buttonDisplayNames; - var buttonDisplayNameWidths = metaDatas.GetPropStaticData(prop).buttonDisplayNameWidths; - var buttonCommands = metaDatas.GetPropStaticData(prop).buttonCommands; - if (buttonDisplayNames == null || buttonCommands == null || buttonDisplayNames.Count == 0 || buttonCommands.Count == 0 - || buttonDisplayNames.Count != buttonCommands.Count) - { - return; - } - - var enbaled = GUI.enabled; - GUI.enabled = true; - - position = EditorGUI.IndentedRect(position); - var rect = new Rect(position.x, position.y, 0, position.height); - var spaceWidth = (position.width - buttonDisplayNameWidths.Sum()) / buttonDisplayNames.Count; - - for (int i = 0; i < buttonDisplayNames.Count; i++) - { - var displayName = buttonDisplayNames[i]; - var displayNameRelativeWidth = buttonDisplayNameWidths[i]; - var command = buttonCommands[i]; - rect.xMax = rect.xMin + displayNameRelativeWidth + spaceWidth; - - if (GUI.Button(rect, new GUIContent(displayName, command))) - { - if (command.StartsWith(_urlPrefix)) - { - Application.OpenURL(command.Substring(_urlPrefix.Length, command.Length - _urlPrefix.Length)); - } - else if (command.StartsWith(_csPrefix)) - { - var csCommand = command.Substring(_csPrefix.Length, command.Length - _csPrefix.Length); - - // Get method name and args - string className = null, methodName = null; - string[] args = null; - { - var lastPointIndex = csCommand.LastIndexOf('.'); - if (lastPointIndex != -1) - { - className = csCommand.Substring(0, lastPointIndex); - var leftBracketIndex = csCommand.IndexOf('('); - if (leftBracketIndex != -1) - { - methodName = csCommand.Substring(lastPointIndex + 1, leftBracketIndex - lastPointIndex - 1); - args = csCommand.Substring(leftBracketIndex + 1, csCommand.Length - leftBracketIndex - 2) - ?.Split(',').Select(s => s.TrimStart()).ToArray(); - } - } - } - - // Find and call method - if (!string.IsNullOrEmpty(className) && !string.IsNullOrEmpty(methodName) && args != null) - { - Type type = ReflectionHelper.GetAllTypes().FirstOrDefault((type1 => type1.Name == className || type1.FullName == className)); - if (type != null) - { - var methodInfo = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public); - if (methodInfo != null) - { - methodInfo.Invoke(null, new object[]{ prop, editor, metaDatas, args }); - } - else - { - Debug.LogError($"LWGUI: Method {methodName} not found in {className}"); - } - } - else - { - Debug.LogError($"LWGUI: Class {className} not found"); - } - } - else - { - Debug.LogError($"LWGUI: Invalid C# command: {csCommand}"); - } - } - else - { - Debug.LogError($"LWGUI: Unknown command type: {command}"); - } - } - - rect.xMin = rect.xMax; - } - - GUI.enabled = enbaled; - } - - public static void TestMethod(MaterialProperty prop, MaterialEditor editor, LWGUIMetaDatas metaDatas, string[] args) - { - Debug.Log($"LWGUI: ButtonDrawer.TestMethod({prop}, {editor}, {metaDatas}, {args})"); - - foreach (var arg in args) - { - Debug.Log(arg); - } - } - } - #endregion - - #endregion - - #region Extra Decorators - - #region Appearance - /// - /// Similar to Header() - /// - /// group: parent group name (Default: none) - /// header: string to display, "SpaceLine" or "_" = none (Default: none) - /// height: line height (Default: 22) - /// - public class TitleDecorator : SubDrawer - { - private string _header; - private float _height; - - public static readonly float DefaultHeight = EditorGUIUtility.singleLineHeight + 6f; - - protected override float GetVisibleHeight(MaterialProperty prop) { return _height; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) { } - - public TitleDecorator(string header) : this("_", header, DefaultHeight) { } - - public TitleDecorator(string header, float height) : this("_", header, height) { } - - public TitleDecorator(string group, string header) : this(group, header, DefaultHeight) { } - - public TitleDecorator(string group, string header, float height) - { - this.group = group; - this._header = header == "SpaceLine" || header == "_" ? String.Empty : header; - this._height = height; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - position = EditorGUI.IndentedRect(position); - GUIStyle style = new GUIStyle(EditorStyles.boldLabel); - style.alignment = TextAnchor.LowerLeft; - style.border.bottom = 2; - GUI.Label(position, _header, style); - } - } - - /// - /// Similar to Title() - /// - /// group: parent group name (Default: none) - /// header: string to display, "SpaceLine" or "_" = none (Default: none) - /// height: line height (Default: 22) - /// - public class SubTitleDecorator : TitleDecorator - { - public SubTitleDecorator(string group, string header) : base(group, header, DefaultHeight) { } - - public SubTitleDecorator(string group, string header, float height) : base(group, header, height) { } - } - - /// - /// Tooltip, describes the details of the property. (Default: property.name and property default value) - /// You can also use "#Text" in DisplayName to add Tooltip that supports Multi-Language. - /// - /// tooltip: a single-line string to display, support up to 4 ','. (Default: Newline) - /// - public class TooltipDecorator : SubDrawer - { - private string _tooltip; - - - #region - - public TooltipDecorator() : this(string.Empty) { } - - public TooltipDecorator(string tooltip) { this._tooltip = tooltip; } - - public TooltipDecorator(string s1, string s2) : this(s1 + ", " + s2) { } - - public TooltipDecorator(string s1, string s2, string s3) : this(s1 + ", " + s2 + ", " + s3) { } - - public TooltipDecorator(string s1, string s2, string s3, string s4) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4) { } - - public TooltipDecorator(string s1, string s2, string s3, string s4, string s5) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4 + ", " + s5) { } - - #endregion - - - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.tooltipMessages += _tooltip + "\n"; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } - } - - /// - /// Display a Helpbox on the property - /// You can also use "%Text" in DisplayName to add Helpbox that supports Multi-Language. - /// - /// message: a single-line string to display, support up to 4 ','. (Default: Newline) - /// - public class HelpboxDecorator : TooltipDecorator - { - private string _message; - - - #region - - public HelpboxDecorator() : this(string.Empty) { } - - public HelpboxDecorator(string message) { this._message = message; } - - public HelpboxDecorator(string s1, string s2) : this(s1 + ", " + s2) { } - - public HelpboxDecorator(string s1, string s2, string s3) : this(s1 + ", " + s2 + ", " + s3) { } - - public HelpboxDecorator(string s1, string s2, string s3, string s4) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4) { } - - public HelpboxDecorator(string s1, string s2, string s3, string s4, string s5) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4 + ", " + s5) { } - - #endregion - - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.helpboxMessages += _message + "\n"; - } - } - - /// - /// Set the property to read-only. - /// - public class ReadOnlyDecorator : SubDrawer - { - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.isReadOnly = true; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } - } - #endregion - - #region Logic - /// - /// Cooperate with Toggle to switch certain Passes. - /// - /// lightModeName(s): Light Mode in Shader Pass (https://docs.unity3d.com/2017.4/Documentation/Manual/SL-PassTags.html) - /// - public class PassSwitchDecorator : SubDrawer - { - private string[] _lightModeNames; - - - #region - - public PassSwitchDecorator(string lightModeName1) - : this(new[] { lightModeName1 }) { } - - public PassSwitchDecorator(string lightModeName1, string lightModeName2) - : this(new[] { lightModeName1, lightModeName2 }) { } - - public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3) - : this(new[] { lightModeName1, lightModeName2, lightModeName3 }) { } - - public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3, string lightModeName4) - : this(new[] { lightModeName1, lightModeName2, lightModeName3, lightModeName4 }) { } - - public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3, string lightModeName4, string lightModeName5) - : this(new[] { lightModeName1, lightModeName2, lightModeName3, lightModeName4, lightModeName5 }) { } - - public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3, string lightModeName4, string lightModeName5, string lightModeName6) - : this(new[] { lightModeName1, lightModeName2, lightModeName3, lightModeName4, lightModeName5, lightModeName6 }) { } - - public PassSwitchDecorator(string[] lightModeNames) { _lightModeNames = lightModeNames.Select((s => s.ToUpper())).ToArray(); } - - #endregion - - - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - protected override bool IsMatchPropType(MaterialProperty property) - { - return property.GetPropertyType() == ShaderPropertyType.Float - || property.GetPropertyType() == ShaderPropertyType.Int; - } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) { } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) - Helper.SetShaderPassEnabled(prop.targets, _lightModeNames, prop.floatValue > 0); - } - - public override void Apply(MaterialProperty prop) - { - base.Apply(prop); - if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) - { - if (ShowIfDecorator.GetShowIfResultToFilterDrawerApplying(prop)) - Helper.SetShaderPassEnabled(prop.targets, _lightModeNames, prop.floatValue > 0); - } - } - } - #endregion - - #region Structure - /// - /// Collapse the current Property into an Advanced Block. - /// Specify the Header String to create a new Advanced Block. - /// All Properties using Advanced() will be collapsed into the nearest Advanced Block. - /// - /// headerString: The title of the Advanced Block. Default: "Advanced" - /// - public class AdvancedDecorator : SubDrawer - { - private string headerString; - - public AdvancedDecorator() : this(string.Empty) { } - - public AdvancedDecorator(string headerString) - { - this.headerString = headerString; - } - - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.isAdvanced = true; - inoutPropertyStaticData.advancedHeaderString = headerString; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } - } - - /// - /// Create an Advanced Block using the current Property as the Header. - /// - public class AdvancedHeaderPropertyDecorator : SubDrawer - { - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.isAdvanced = true; - inoutPropertyStaticData.isAdvancedHeader = true; - inoutPropertyStaticData.isAdvancedHeaderProperty = true; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } - } - #endregion - - #region Condition Display - /// - /// Similar to HideInInspector(), the difference is that Hidden() can be unhidden through the Display Mode button. - /// - public class HiddenDecorator : SubDrawer - { - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.isHidden = true; - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } - } - - /// - /// Control the show or hide of a single or a group of properties based on multiple conditions. - /// - /// logicalOperator: And | Or (Default: And). - /// propName: Target Property Name used for comparison. - /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). - /// value: Target Property Value used for comparison. - /// - public class ShowIfDecorator : SubDrawer - { - public enum LogicalOperator - { - And, - Or - } - - public class ShowIfData - { - public LogicalOperator logicalOperator = LogicalOperator.And; - public string targetPropertyName = string.Empty; - public CompareFunction compareFunction = CompareFunction.Equal; - public float value = 0; - } - - public ShowIfData showIfData = new(); - - private readonly Dictionary _compareFunctionLUT = new() - { - { "Less", "Less" }, - { "L", "Less" }, - { "Equal", "Equal" }, - { "E", "Equal" }, - { "LessEqual", "LessEqual" }, - { "LEqual", "LessEqual" }, - { "LE", "LessEqual" }, - { "Greater", "Greater" }, - { "G", "Greater" }, - { "NotEqual", "NotEqual" }, - { "NEqual", "NotEqual" }, - { "NE", "NotEqual" }, - { "GreaterEqual", "GreaterEqual" }, - { "GEqual", "GreaterEqual" }, - { "GE", "GreaterEqual" }, - }; - - public ShowIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } - - public ShowIfDecorator(string logicalOperator, string propName, string compareFunction, float value) - { - showIfData.logicalOperator = logicalOperator.ToLower() == "or" ? LogicalOperator.Or : LogicalOperator.And; - showIfData.targetPropertyName = propName; - if (!_compareFunctionLUT.ContainsKey(compareFunction) || !Enum.IsDefined(typeof(CompareFunction), _compareFunctionLUT[compareFunction])) - Debug.LogError("LWGUI: Invalid compareFunction: '" - + compareFunction - + "', Must be one of the following: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE)."); - else - showIfData.compareFunction = (CompareFunction)Enum.Parse(typeof(CompareFunction), _compareFunctionLUT[compareFunction]); - showIfData.value = value; - } - - private static void Compare(ShowIfData showIfData, float targetValue, ref bool result) - { - bool compareResult; - - switch (showIfData.compareFunction) - { - case CompareFunction.Less: - compareResult = targetValue < showIfData.value; - break; - case CompareFunction.LessEqual: - compareResult = targetValue <= showIfData.value; - break; - case CompareFunction.Greater: - compareResult = targetValue > showIfData.value; - break; - case CompareFunction.NotEqual: - compareResult = targetValue != showIfData.value; - break; - case CompareFunction.GreaterEqual: - compareResult = targetValue >= showIfData.value; - break; - default: - compareResult = targetValue == showIfData.value; - break; - } - - switch (showIfData.logicalOperator) - { - case LogicalOperator.And: - result &= compareResult; - break; - case LogicalOperator.Or: - result |= compareResult; - break; - } - } - - public static bool GetShowIfResultToFilterDrawerApplying(MaterialProperty prop) - { - var material = prop.targets[0] as Material; - var showIfDatas = new List(); - { - var drawer = ReflectionHelper.GetPropertyDrawer(material.shader, prop, out var decoratorDrawers); - if (decoratorDrawers != null && decoratorDrawers.Count > 0) - { - foreach (ShowIfDecorator showIfDecorator in decoratorDrawers.Where(drawer => drawer is ShowIfDecorator)) - { - showIfDatas.Add(showIfDecorator.showIfData); - } - } - else - { - return true; - } - } - - return GetShowIfResultFromMaterial(showIfDatas, material); - } - - public static bool GetShowIfResultFromMaterial(List showIfDatas, Material material) - { - bool result = true; - foreach (var showIfData in showIfDatas) - { - var targetValue = material.GetFloat(showIfData.targetPropertyName); - Compare(showIfData, targetValue, ref result); - } - - return result; - } - - public static void GetShowIfResult(PropertyStaticData propStaticData, PropertyDynamicData propDynamicData, PerMaterialData perMaterialData) - { - foreach (var showIfData in propStaticData.showIfDatas) - { - var targetValue = perMaterialData.propDynamicDatas[showIfData.targetPropertyName].property.floatValue; - Compare(showIfData, targetValue, ref propDynamicData.isShowing); - } - } - - protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } - - public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) - { - inoutPropertyStaticData.showIfDatas.Add(showIfData); - } - - public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } - } - #endregion - - #endregion - -} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers.meta new file mode 100644 index 000000000..8ed7dedce --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 799ea78c6ec34670ac45e915a967b2cc +timeCreated: 1769096897 \ No newline at end of file diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers.meta similarity index 77% rename from Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL.meta rename to Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers.meta index 5b2f6baa8..b46d45dc8 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 721b8d7aa96ce3243ad6e988775df5ee +guid: 0087db252163ae340b69ec11fcd1e28a folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/MainDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/MainDrawer.cs new file mode 100644 index 000000000..f98241ec7 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/MainDrawer.cs @@ -0,0 +1,109 @@ +// Copyright (c) Jason Ma + +using System; +using LWGUI.Timeline; +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Create a Folding Group + /// + /// group: group name (Default: Property Name) + /// keyword: keyword used for toggle, "_" = ignore, none or "__" = Property Name + "_ON", always Upper (Default: none) + /// default Folding State: "on" or "off" (Default: off) + /// default Toggle Displayed: "on" or "off" (Default: on) + /// preset File Name: "Shader Property Preset" asset name, see Preset() for detail (Default: none) + /// Target Property Type: Float, express Toggle value + /// + public class MainDrawer : MaterialPropertyDrawer, IBaseDrawer, IPresetDrawer + { + protected LWGUIMetaDatas metaDatas; + + private static readonly float _height = 28f; + + private bool _isFolding; + private string _group; + private string _keyword; + private bool _defaultFoldingState; + private bool _defaultToggleDisplayed; + private string _presetFileName; + + public MainDrawer() : this(String.Empty) { } + + public MainDrawer(string group) : this(group, String.Empty) { } + + public MainDrawer(string group, string keyword) : this(group, keyword, "off") { } + + public MainDrawer(string group, string keyword, string defaultFoldingState) : this(group, keyword, defaultFoldingState, "on") { } + + public MainDrawer(string group, string keyword, string defaultFoldingState, string defaultToggleDisplayed) : this(group, keyword, defaultFoldingState, defaultToggleDisplayed, String.Empty) { } + + public MainDrawer(string group, string keyword, string defaultFoldingState, string defaultToggleDisplayed, string presetFileName) + { + this._group = group; + this._keyword = keyword; + this._defaultFoldingState = Helper.StringToBool(defaultFoldingState); + this._defaultToggleDisplayed = Helper.StringToBool(defaultToggleDisplayed); + this._presetFileName = presetFileName; + } + + public virtual void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.groupName = _group; + inoutPropertyStaticData.isMain = true; + inoutPropertyStaticData.isExpanding = _defaultFoldingState; + PerShaderData.DecodeMetaDataFromDisplayName(inProp, inoutPropertyStaticData); + PresetDrawer.SetPresetAssetToStaticData(inoutPropertyStaticData, _presetFileName); + } + + public virtual void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) + { + inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = inDefaultProp.floatValue > 0 ? "On" : "Off"; + } + + public string GetPresetFileName() => _presetFileName; + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + metaDatas = Helper.GetLWGUIMetadatas(editor); + + var showMixedValue = EditorGUI.showMixedValue; + EditorGUI.showMixedValue = prop.hasMixedValue; + EditorGUI.BeginChangeCheck(); + + bool toggleResult = Helper.DrawFoldout(position, ref metaDatas.GetPropStaticData(prop).isExpanding, !Helper.Approximately(prop.floatValue, 0), _defaultToggleDisplayed, label); + + if (Helper.EndChangeCheck(metaDatas, prop)) + { + prop.floatValue = toggleResult ? 1.0f : 0.0f; + var keyword = Helper.GetKeywordName(_keyword, prop.name); + Helper.SetShaderKeywordEnabled(editor.targets, keyword, toggleResult); + PresetHelper.GetPresetAsset(_presetFileName)?.TryGetPreset(prop.floatValue)?.ApplyToEditingMaterial(editor, metaDatas.perMaterialData); + TimelineHelper.SetKeywordToggleToTimeline(prop, editor, keyword); + } + EditorGUI.showMixedValue = showMixedValue; + } + + // Call in custom shader gui + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + return _height; + } + + // Call when create/edit/undo materials. + // Used to set material settings such as Keywords that need to be kept synchronized with the value forever. + // DO NOT modify other properties here!!! Otherwise, manually modified values will be overwritten. + public override void Apply(MaterialProperty prop) + { + base.Apply(prop); + if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) + { + Helper.SetShaderKeywordEnabled(prop.targets, Helper.GetKeywordName(_keyword, prop.name), prop.floatValue > 0f); + PresetDrawer.ApplyPresetWithoutPropertyChanges(_presetFileName, prop); + } + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/MainDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/MainDrawer.cs.meta new file mode 100644 index 000000000..ad87a3334 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/MainDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 80bd09bde334c2c439f7374bb2ba821c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/SubDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/SubDrawer.cs new file mode 100644 index 000000000..469c6c5e1 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/SubDrawer.cs @@ -0,0 +1,74 @@ +// Copyright (c) Jason Ma + +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Draw a property with default style in the folding group + /// + /// group: parent group name (Default: none) + /// Target Property Type: Any + /// + public class SubDrawer : MaterialPropertyDrawer, IBaseDrawer + { + public string group = String.Empty; + public LWGUIMetaDatas metaDatas; + + public SubDrawer() { } + + public SubDrawer(string group) + { + this.group = group; + } + + protected virtual bool IsMatchPropType(MaterialProperty property) { return true; } + + protected virtual float GetVisibleHeight(MaterialProperty prop) + { + var height = MaterialEditor.GetDefaultPropertyHeight(prop); + return prop.GetPropertyType() == ShaderPropertyType.Vector ? EditorGUIUtility.singleLineHeight : height; + } + + public virtual void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.groupName = group; + PerShaderData.DecodeMetaDataFromDisplayName(inProp, inoutPropertyStaticData); + } + + public virtual void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) { } + + public virtual void GetCustomContextMenus(GenericMenu menu, Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) { } + + public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + metaDatas = Helper.GetLWGUIMetadatas(editor); + + if (IsMatchPropType(prop)) + { + DrawProp(position, prop, label, editor); + } + else + { + Debug.LogWarning("LWGUI: Property:'" + prop.name + "' Type:'" + prop.GetPropertyType() + "' mismatch!"); + editor.DefaultShaderProperty(position, prop, label.text); + } + } + + public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) + { + return GetVisibleHeight(prop); + } + + // Draws a custom style property + public virtual void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + RevertableHelper.FixGUIWidthMismatch(prop.GetPropertyType(), editor); + editor.DefaultShaderPropertyInternal(position, prop, label); + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/SubDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/SubDrawer.cs.meta new file mode 100644 index 000000000..96e964f07 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/BasicDrawers/SubDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1018092e809fcf448a004c21f19c56cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators.meta similarity index 57% rename from Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl.meta rename to Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators.meta index fb43f5c3d..bd16ddb3c 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators.meta @@ -1,6 +1,7 @@ fileFormatVersion: 2 -guid: 734309d3fd8d31246bde14f3278d4ee3 -ShaderIncludeImporter: +guid: d88e9b9124470694db30ecb3c7da26c2 +folderAsset: yes +DefaultImporter: externalObjects: {} userData: assetBundleName: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance.meta new file mode 100644 index 000000000..f98deeb39 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5e5aaa8816648ca4eaed701110c637d4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/HelpboxDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/HelpboxDecorator.cs new file mode 100644 index 000000000..8754d68fd --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/HelpboxDecorator.cs @@ -0,0 +1,41 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Display a Helpbox on the property + /// You can also use "%Text" in DisplayName to add Helpbox that supports Multi-Language. + /// + /// message: a single-line string to display, support up to 4 ','. (Default: Newline) + /// + public class HelpboxDecorator : TooltipDecorator + { + private string _message; + + + #region + + public HelpboxDecorator() : this(string.Empty) { } + + public HelpboxDecorator(string message) { this._message = message; } + + public HelpboxDecorator(string s1, string s2) : this(s1 + ", " + s2) { } + + public HelpboxDecorator(string s1, string s2, string s3) : this(s1 + ", " + s2 + ", " + s3) { } + + public HelpboxDecorator(string s1, string s2, string s3, string s4) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4) { } + + public HelpboxDecorator(string s1, string s2, string s3, string s4, string s5) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4 + ", " + s5) { } + + #endregion + + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.helpboxMessages += _message + "\n"; + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/HelpboxDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/HelpboxDecorator.cs.meta new file mode 100644 index 000000000..87a9275a3 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/HelpboxDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c60e1921fd5b285489b55fa3650c40a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/ReadOnlyDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/ReadOnlyDecorator.cs new file mode 100644 index 000000000..89b96726a --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/ReadOnlyDecorator.cs @@ -0,0 +1,22 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Set the property to read-only. + /// + public class ReadOnlyDecorator : SubDrawer + { + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.isReadOnly = true; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/ReadOnlyDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/ReadOnlyDecorator.cs.meta new file mode 100644 index 000000000..eda9247fa --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/ReadOnlyDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e86854765f20f184185f804b18f4bd1c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/SubTitleDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/SubTitleDecorator.cs new file mode 100644 index 000000000..d02b781ce --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/SubTitleDecorator.cs @@ -0,0 +1,18 @@ +// Copyright (c) Jason Ma + +namespace LWGUI +{ + /// + /// Similar to Title() + /// + /// group: parent group name (Default: none) + /// header: string to display, "SpaceLine" or "_" = none (Default: none) + /// height: line height (Default: 22) + /// + public class SubTitleDecorator : TitleDecorator + { + public SubTitleDecorator(string group, string header) : base(group, header, DefaultHeight) { } + + public SubTitleDecorator(string group, string header, float height) : base(group, header, height) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/SubTitleDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/SubTitleDecorator.cs.meta new file mode 100644 index 000000000..22be5ae1c --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/SubTitleDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59dc6bb7a17b4da4c9ea5d75aed10b7e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TitleDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TitleDecorator.cs new file mode 100644 index 000000000..5b0787e21 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TitleDecorator.cs @@ -0,0 +1,46 @@ +// Copyright (c) Jason Ma + +using System; +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Similar to Header() + /// + /// group: parent group name (Default: none) + /// header: string to display, "SpaceLine" or "_" = none (Default: none) + /// height: line height (Default: 22) + /// + public class TitleDecorator : SubDrawer + { + private string _header; + private float _height; + + public static readonly float DefaultHeight = EditorGUIUtility.singleLineHeight + 6f; + + protected override float GetVisibleHeight(MaterialProperty prop) { return _height; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) { } + + public TitleDecorator(string header) : this("_", header, DefaultHeight) { } + + public TitleDecorator(string header, float height) : this("_", header, height) { } + + public TitleDecorator(string group, string header) : this(group, header, DefaultHeight) { } + + public TitleDecorator(string group, string header, float height) + { + this.group = group; + this._header = header == "SpaceLine" || header == "_" ? String.Empty : header; + this._height = height; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + position = EditorGUI.IndentedRect(position); + GUI.Label(position, _header, GUIStyles.title); + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TitleDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TitleDecorator.cs.meta new file mode 100644 index 000000000..3896b2702 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TitleDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 09b3118ef6d65ec49bdd423f20f09f09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TooltipDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TooltipDecorator.cs new file mode 100644 index 000000000..357913429 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TooltipDecorator.cs @@ -0,0 +1,45 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Tooltip, describes the details of the property. (Default: property.name and property default value) + /// You can also use "#Text" in DisplayName to add Tooltip that supports Multi-Language. + /// + /// tooltip: a single-line string to display, support up to 4 ','. (Default: Newline) + /// + public class TooltipDecorator : SubDrawer + { + private string _tooltip; + + + #region + + public TooltipDecorator() : this(string.Empty) { } + + public TooltipDecorator(string tooltip) { this._tooltip = tooltip; } + + public TooltipDecorator(string s1, string s2) : this(s1 + ", " + s2) { } + + public TooltipDecorator(string s1, string s2, string s3) : this(s1 + ", " + s2 + ", " + s3) { } + + public TooltipDecorator(string s1, string s2, string s3, string s4) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4) { } + + public TooltipDecorator(string s1, string s2, string s3, string s4, string s5) : this(s1 + ", " + s2 + ", " + s3 + ", " + s4 + ", " + s5) { } + + #endregion + + + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.tooltipMessages += _tooltip + "\n"; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TooltipDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TooltipDecorator.cs.meta new file mode 100644 index 000000000..59e8c3c0d --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Appearance/TooltipDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5934a4eb43f5b3b48b5396a2cb653f76 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay.meta new file mode 100644 index 000000000..18d4978cd --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 921ffaf8b8533bf42983cf1189a4ad45 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs new file mode 100644 index 000000000..196230a7c --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs @@ -0,0 +1,39 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Control whether the property can be edited based on multiple conditions. + /// + /// logicalOperator: And | Or (Default: And). + /// propName: Target Property Name used for comparison. + /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). + /// value: Target Property Value used for comparison. + /// + public class ActiveIfDecorator : SubDrawer + { + public ShowIfDecorator.ShowIfData activeIfData = new(); + + public ActiveIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } + + public ActiveIfDecorator(string logicalOperator, string propName, string compareFunction, float value) + { + activeIfData.logicalOperator = logicalOperator.ToLower() == "or" ? ShowIfDecorator.LogicalOperator.Or : ShowIfDecorator.LogicalOperator.And; + activeIfData.targetPropertyName = propName; + activeIfData.compareFunction = ShowIfDecorator.ParseCompareFunction(compareFunction); + activeIfData.value = value; + } + + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.activeIfDatas.Add(activeIfData); + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs.meta new file mode 100644 index 000000000..311321233 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ActiveIfDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 224088b56f7a2814ba7520292da26cf8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/HiddenDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/HiddenDecorator.cs new file mode 100644 index 000000000..507985f03 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/HiddenDecorator.cs @@ -0,0 +1,22 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Similar to HideInInspector(), the difference is that Hidden() can be unhidden through the Display Mode button. + /// + public class HiddenDecorator : SubDrawer + { + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.isHidden = true; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/HiddenDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/HiddenDecorator.cs.meta new file mode 100644 index 000000000..ff8920b5a --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/HiddenDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b730963b9bced7f418f78f2502b39607 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs new file mode 100644 index 000000000..c198e3834 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs @@ -0,0 +1,170 @@ +// Copyright (c) Jason Ma + +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Control the show or hide of a single or a group of properties based on multiple conditions. + /// + /// logicalOperator: And | Or (Default: And). + /// propName: Target Property Name used for comparison. + /// compareFunction: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE). + /// value: Target Property Value used for comparison. + /// + public class ShowIfDecorator : SubDrawer + { + public enum LogicalOperator + { + And, + Or + } + + public class ShowIfData + { + public LogicalOperator logicalOperator = LogicalOperator.And; + public string targetPropertyName = string.Empty; + public CompareFunction compareFunction = CompareFunction.Equal; + public float value = 0; + } + + public ShowIfData showIfData = new(); + + private static readonly Dictionary _compareFunctionLUT = new() + { + { "Less", "Less" }, + { "L", "Less" }, + { "Equal", "Equal" }, + { "E", "Equal" }, + { "LessEqual", "LessEqual" }, + { "LEqual", "LessEqual" }, + { "LE", "LessEqual" }, + { "Greater", "Greater" }, + { "G", "Greater" }, + { "NotEqual", "NotEqual" }, + { "NEqual", "NotEqual" }, + { "NE", "NotEqual" }, + { "GreaterEqual", "GreaterEqual" }, + { "GEqual", "GreaterEqual" }, + { "GE", "GreaterEqual" }, + }; + + public static CompareFunction ParseCompareFunction(string compareFunction) + { + if (!_compareFunctionLUT.TryGetValue(compareFunction, out var compareFunctionName) + || !Enum.IsDefined(typeof(CompareFunction), compareFunctionName)) + { + Debug.LogError("LWGUI: Invalid compareFunction: '" + + compareFunction + + "', Must be one of the following: Less (L) | Equal (E) | LessEqual (LEqual / LE) | Greater (G) | NotEqual (NEqual / NE) | GreaterEqual (GEqual / GE)."); + return CompareFunction.Equal; + } + + return (CompareFunction)Enum.Parse(typeof(CompareFunction), compareFunctionName); + } + + public ShowIfDecorator(string propName, string comparisonMethod, float value) : this("And", propName, comparisonMethod, value) { } + + public ShowIfDecorator(string logicalOperator, string propName, string compareFunction, float value) + { + showIfData.logicalOperator = logicalOperator.ToLower() == "or" ? LogicalOperator.Or : LogicalOperator.And; + showIfData.targetPropertyName = propName; + showIfData.compareFunction = ParseCompareFunction(compareFunction); + showIfData.value = value; + } + + private static void Compare(ShowIfData showIfData, float targetValue, ref bool result) + { + bool compareResult; + + switch (showIfData.compareFunction) + { + case CompareFunction.Less: + compareResult = targetValue < showIfData.value; + break; + case CompareFunction.LessEqual: + compareResult = targetValue <= showIfData.value; + break; + case CompareFunction.Greater: + compareResult = targetValue > showIfData.value; + break; + case CompareFunction.NotEqual: + compareResult = targetValue != showIfData.value; + break; + case CompareFunction.GreaterEqual: + compareResult = targetValue >= showIfData.value; + break; + default: + compareResult = targetValue == showIfData.value; + break; + } + + switch (showIfData.logicalOperator) + { + case LogicalOperator.And: + result &= compareResult; + break; + case LogicalOperator.Or: + result |= compareResult; + break; + } + } + + public static bool GetShowIfResultToFilterDrawerApplying(MaterialProperty prop) + { + var material = prop.targets[0] as Material; + var showIfDatas = new List(); + { + var drawer = ReflectionHelper.GetPropertyDrawer(material.shader, prop, out var decoratorDrawers); + if (decoratorDrawers != null && decoratorDrawers.Count > 0) + { + foreach (ShowIfDecorator showIfDecorator in decoratorDrawers.Where(drawer => drawer is ShowIfDecorator)) + { + showIfDatas.Add(showIfDecorator.showIfData); + } + } + else + { + return true; + } + } + + return GetShowIfResultFromMaterial(showIfDatas, material); + } + + public static bool GetShowIfResultFromMaterial(List showIfDatas, Material material) + { + bool result = true; + foreach (var showIfData in showIfDatas) + { + var targetValue = material.GetFloat(showIfData.targetPropertyName); + Compare(showIfData, targetValue, ref result); + } + + return result; + } + + public static void GetShowIfResult(PropertyStaticData propStaticData, PropertyDynamicData propDynamicData, PerMaterialData perMaterialData) + { + foreach (var showIfData in propStaticData.showIfDatas) + { + var targetValue = perMaterialData.propDynamicDatas[showIfData.targetPropertyName].property.floatValue; + Compare(showIfData, targetValue, ref propDynamicData.isShowing); + } + } + + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.showIfDatas.Add(showIfData); + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs.meta new file mode 100644 index 000000000..5823279be --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/ConditionDisplay/ShowIfDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f391774ca908ee42abfa5b95dea3b8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic.meta new file mode 100644 index 000000000..d863a4f6e --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 39a1eac873eb3a04a8bd4ad4805745b9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic/PassSwitchDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic/PassSwitchDecorator.cs new file mode 100644 index 000000000..c6c840310 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic/PassSwitchDecorator.cs @@ -0,0 +1,71 @@ +// Copyright (c) Jason Ma + +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Cooperate with Toggle to switch certain Passes. + /// + /// lightModeName(s): Light Mode in Shader Pass (https://docs.unity3d.com/2017.4/Documentation/Manual/SL-PassTags.html) + /// + public class PassSwitchDecorator : SubDrawer + { + private string[] _lightModeNames; + + + #region + + public PassSwitchDecorator(string lightModeName1) + : this(new[] { lightModeName1 }) { } + + public PassSwitchDecorator(string lightModeName1, string lightModeName2) + : this(new[] { lightModeName1, lightModeName2 }) { } + + public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3) + : this(new[] { lightModeName1, lightModeName2, lightModeName3 }) { } + + public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3, string lightModeName4) + : this(new[] { lightModeName1, lightModeName2, lightModeName3, lightModeName4 }) { } + + public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3, string lightModeName4, string lightModeName5) + : this(new[] { lightModeName1, lightModeName2, lightModeName3, lightModeName4, lightModeName5 }) { } + + public PassSwitchDecorator(string lightModeName1, string lightModeName2, string lightModeName3, string lightModeName4, string lightModeName5, string lightModeName6) + : this(new[] { lightModeName1, lightModeName2, lightModeName3, lightModeName4, lightModeName5, lightModeName6 }) { } + + public PassSwitchDecorator(string[] lightModeNames) { _lightModeNames = lightModeNames.Select((s => s.ToUpper())).ToArray(); } + + #endregion + + + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + protected override bool IsMatchPropType(MaterialProperty property) + { + return property.GetPropertyType() == ShaderPropertyType.Float + || property.GetPropertyType() == ShaderPropertyType.Int; + } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) { } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) + Helper.SetShaderPassEnabled(prop.targets, _lightModeNames, prop.floatValue > 0); + } + + public override void Apply(MaterialProperty prop) + { + base.Apply(prop); + if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) + { + if (ShowIfDecorator.GetShowIfResultToFilterDrawerApplying(prop)) + Helper.SetShaderPassEnabled(prop.targets, _lightModeNames, prop.floatValue > 0); + } + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic/PassSwitchDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic/PassSwitchDecorator.cs.meta new file mode 100644 index 000000000..8385d694c --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Logic/PassSwitchDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ce1e6b3dcc10bf4d904506b5427dd62 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure.meta new file mode 100644 index 000000000..2e68edc50 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3d4d8d42a6cdcf4280e9f094d31280c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedDecorator.cs new file mode 100644 index 000000000..f7c2b4e5e --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedDecorator.cs @@ -0,0 +1,36 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Collapse the current Property into an Advanced Block. + /// Specify the Header String to create a new Advanced Block. + /// All Properties using Advanced() will be collapsed into the nearest Advanced Block. + /// + /// headerString: The title of the Advanced Block. Default: "Advanced" + /// + public class AdvancedDecorator : SubDrawer + { + private string headerString; + + public AdvancedDecorator() : this(string.Empty) { } + + public AdvancedDecorator(string headerString) + { + this.headerString = headerString; + } + + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.isAdvanced = true; + inoutPropertyStaticData.advancedHeaderString = headerString; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedDecorator.cs.meta new file mode 100644 index 000000000..e65752895 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f94593a3791d98342bcf7e2ce8a434ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedHeaderPropertyDecorator.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedHeaderPropertyDecorator.cs new file mode 100644 index 000000000..8b6f90763 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedHeaderPropertyDecorator.cs @@ -0,0 +1,24 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Create an Advanced Block using the current Property as the Header. + /// + public class AdvancedHeaderPropertyDecorator : SubDrawer + { + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.isAdvanced = true; + inoutPropertyStaticData.isAdvancedHeader = true; + inoutPropertyStaticData.isAdvancedHeaderProperty = true; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedHeaderPropertyDecorator.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedHeaderPropertyDecorator.cs.meta new file mode 100644 index 000000000..ad6bfb4f7 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDecorators/Structure/AdvancedHeaderPropertyDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eda92ad2828dbbf4b8ad1ceec6a203bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers.meta new file mode 100644 index 000000000..6b588e7ff --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f91db697c82843841ac35226be10a332 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric.meta new file mode 100644 index 000000000..8b911694f --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b9ac04b03bfd1b6458e0821d6c79a3f8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/BitMaskDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/BitMaskDrawer.cs new file mode 100644 index 000000000..1322ad9ca --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/BitMaskDrawer.cs @@ -0,0 +1,143 @@ +// Copyright (c) Jason Ma + +using System.Collections.Generic; +using System.Linq; +using LWGUI.Runtime; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Draw the Int value as a Bit Mask. + /// Note: + /// - Currently only 8 bits are supported. + /// + /// Warning 1: If used to set Stencil, it will conflict with SRP Batcher! + /// (Reproduced in Unity 2022) + /// SRP Batcher does not correctly handle multiple materials with different Stencil Ref values, + /// mistakenly merging them into a single Batch and randomly selecting one material's Stencil Ref value for the entire Batch. + /// In theory, if different materials have different Stencil Ref values, they should not be merged into a single Batch due to differing Render States. + /// Solution: + /// - Force disable SRP Batcher by setting the Material Property Block + /// - Place materials with the same Stencil Ref value in a separate Render Queue to ensure the Batch's Render State is correct + /// + /// Warning 2: Once in use, do not change the Target Property Type! + /// The underlying type of Int Property is Float Property, and in Materials, Int and Integer are stored separately. + /// Once a Material is saved, the Property Type is determined. + /// If you change the Property Type at this point (such as switching between Int/Integer), some strange bugs may occur. + /// If you must change the Property Type, it is recommended to modify the Property Name as well or delete the saved Property in the material. + /// + /// group: parent group name (Default: none) + /// bitDescription 7-0: Description of each Bit. (Default: none) + /// Target Property Type: Int/Integer + /// + public class BitMaskDrawer : SubDrawer + { + public int bitCount = 8; + + public float maxHeight = EditorGUIUtility.singleLineHeight; + + public List buttonLables = new (); + + public List buttonWidths = new(); + + public List buttonStyles = new(); + + public float totalButtonWidth; + + private static readonly int _hint = "BitMask".GetHashCode(); + + private static readonly float _minButtonWidth = 25; + + private static readonly float _buttonPadding = 1.0f; + + public BitMaskDrawer() : this(string.Empty, null) { } + + public BitMaskDrawer(string group) : this(group, null) { } + + public BitMaskDrawer(string group, string bitDescription7, string bitDescription6, string bitDescription5, string bitDescription4, string bitDescription3, string bitDescription2, string bitDescription1, string bitDescription0) + : this(group, new List() { bitDescription0, bitDescription1, bitDescription2, bitDescription3, bitDescription4, bitDescription5, bitDescription6, bitDescription7 }) { } + + public BitMaskDrawer(string group, List bitDescriptions) + { + this.group = group; + + bitCount = Mathf.Clamp(bitCount, 1, 16); + + for (int i = 0; i < bitCount; i++) + { + var description = bitDescriptions != null && bitDescriptions.Count > i ? bitDescriptions[i] : string.Empty; + buttonLables.Add(new GUIContent( + string.IsNullOrEmpty(description) ? i.ToString() : i + "\n" + description)); + buttonWidths.Add(Mathf.Max(_minButtonWidth, EditorStyles.miniButton.CalcSize(buttonLables[i]).x)); + + if (!string.IsNullOrEmpty(description)) + maxHeight = EditorGUIUtility.singleLineHeight * 2; + } + + for (int i = 0; i < bitCount; i++) + { + if (i == 0) + buttonStyles.Add(new GUIStyle(EditorStyles.miniButtonRight)); + else if (i == bitCount - 1) + buttonStyles.Add(new GUIStyle(EditorStyles.miniButtonLeft)); + else + buttonStyles.Add(new GUIStyle(EditorStyles.miniButton)); + + buttonStyles[i].fixedHeight = maxHeight; + } + + totalButtonWidth = buttonWidths.Sum(); + } + + protected override bool IsMatchPropType(MaterialProperty property) + => property.GetPropertyType() is ShaderPropertyType.Float or ShaderPropertyType.Int; + + protected override float GetVisibleHeight(MaterialProperty prop) { return maxHeight; } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + label.tooltip += $"\nCurrent Value: { prop.GetNumericValue() }"; + + int controlId = GUIUtility.GetControlID(_hint, FocusType.Keyboard, position); + var fieldRect = EditorGUI.PrefixLabel(position, controlId, label); + + if (position.width < totalButtonWidth) + return; + + fieldRect.xMin = fieldRect.xMax; + + for (int i = 0; i < bitCount; i++) + { + fieldRect.xMin = fieldRect.xMax - buttonWidths[i]; + var buttonLable = buttonLables[i]; + var active = RuntimeHelper.IsBitEnabled((int)prop.GetNumericValue(), i); + var style = buttonStyles[i]; + var buttonRect = fieldRect; + + if (i > 0 && i < bitCount - 1) + { + buttonRect.xMin -= _buttonPadding; + buttonRect.xMax += _buttonPadding * 2; + } + + if (prop.hasMixedValue) + { + style.richText = true; + // https://docs.unity3d.com/2021.3/Documentation/Manual/StyledText.html + buttonLable = new GUIContent($"{ buttonLable.text }"); + } + + if (Helper.ToggleButton(buttonRect, buttonLable, active, style, _buttonPadding * 1.5f)) + { + prop.SetNumericValue(RuntimeHelper.SetBitEnabled((int)prop.GetNumericValue(), i, !active)); + } + + fieldRect.xMax = fieldRect.xMin; + } + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/BitMaskDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/BitMaskDrawer.cs.meta new file mode 100644 index 000000000..37d3a3d10 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/BitMaskDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69a1cc36b3afcad49bab404c303589f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/KWEnumDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/KWEnumDrawer.cs new file mode 100644 index 000000000..70f921059 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/KWEnumDrawer.cs @@ -0,0 +1,145 @@ +// Copyright (c) Jason Ma + +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Similar to builtin Enum() / KeywordEnum() + /// + /// group: parent group name (Default: none) + /// n(s): display name + /// k(s): keyword + /// v(s): value + /// Target Property Type: Float, express current keyword index + /// + public class KWEnumDrawer : SubDrawer + { + private GUIContent[] _names; + private string[] _keyWords; + private float[] _values; + + + #region + + public KWEnumDrawer(string n1, string k1) + : this("_", new string[1] { n1 }, new string[1] { k1 }) { } + + public KWEnumDrawer(string n1, string k1, string n2, string k2) + : this("_", new string[2] { n1, n2 }, new string[2] { k1, k2 }) { } + + public KWEnumDrawer(string n1, string k1, string n2, string k2, string n3, string k3) + : this("_", new string[3] { n1, n2, n3 }, new string[3] { k1, k2, k3 }) { } + + public KWEnumDrawer(string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4) + : this("_", new string[4] { n1, n2, n3, n4 }, new string[4] { k1, k2, k3, k4 }) { } + + public KWEnumDrawer(string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4, string n5, string k5) + : this("_", new string[5] { n1, n2, n3, n4, n5 }, new string[5] { k1, k2, k3, k4, k5 }) { } + + public KWEnumDrawer(string group, string n1, string k1) + : this(group, new string[1] { n1 }, new string[1] { k1 }) { } + + public KWEnumDrawer(string group, string n1, string k1, string n2, string k2) + : this(group, new string[2] { n1, n2 }, new string[2] { k1, k2 }) { } + + public KWEnumDrawer(string group, string n1, string k1, string n2, string k2, string n3, string k3) + : this(group, new string[3] { n1, n2, n3 }, new string[3] { k1, k2, k3 }) { } + + public KWEnumDrawer(string group, string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4) + : this(group, new string[4] { n1, n2, n3, n4 }, new string[4] { k1, k2, k3, k4 }) { } + + public KWEnumDrawer(string group, string n1, string k1, string n2, string k2, string n3, string k3, string n4, string k4, string n5, string k5) + : this(group, new string[5] { n1, n2, n3, n4, n5 }, new string[5] { k1, k2, k3, k4, k5 }) { } + + #endregion + + + public KWEnumDrawer(string group, string[] names, string[] keyWords = null, float[] values = null) + { + Init(group, names, keyWords, values); + } + + protected void Init(string group, string[] names, string[] keyWords, float[] values) + { + this.group = group; + + this._names = new GUIContent[names.Length]; + for (int index = 0; index < names.Length; ++index) + this._names[index] = new GUIContent(names[index]); + + if (keyWords == null) + { + keyWords = new string[names.Length]; + for (int i = 0; i < names.Length; i++) + keyWords[i] = String.Empty; + } + this._keyWords = keyWords; + + if (values == null) + { + values = new float[names.Length]; + for (int index = 0; index < names.Length; ++index) + values[index] = index; + } + this._values = values; + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() is ShaderPropertyType.Float; } + + protected virtual string GetKeywordName(string propName, string name) { return (name).Replace(' ', '_').ToUpperInvariant(); } + + public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) + { + var index = Array.IndexOf(_values, (int)inDefaultProp.floatValue); + if (index < _names.Length && index >= 0) + inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = _names[index].text; + } + + private string[] GetKeywords(MaterialProperty property) + { + string[] keyWords = new string[_keyWords.Length]; + for (int i = 0; i < keyWords.Length; i++) + keyWords[i] = GetKeywordName(property.name, _keyWords[i]); + return keyWords; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + + var rect = position; + + string[] keyWords = GetKeywords(prop); + int index = Array.IndexOf(_values, prop.floatValue); + if (index < 0) + { + Debug.LogError("LWGUI: Property: " + prop.name + " has unknown Enum Value: '" + prop.floatValue + "' !\n"); + return; + } + + Helper.AdaptiveFieldWidth(EditorStyles.popup, _names[index]); + int newIndex = EditorGUI.Popup(rect, label, index, _names); + EditorGUI.showMixedValue = false; + if (Helper.EndChangeCheck(metaDatas, prop)) + { + prop.floatValue = _values[newIndex]; + Helper.SelectShaderKeyword(editor.targets, keyWords, newIndex); + } + } + + public override void Apply(MaterialProperty prop) + { + base.Apply(prop); + if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) + { + Helper.SelectShaderKeyword(prop.targets, GetKeywords(prop), (int)prop.floatValue); + } + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/KWEnumDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/KWEnumDrawer.cs.meta new file mode 100644 index 000000000..41bc5ec98 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/KWEnumDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6efec1ff74c201940bfb8b2ed76cc759 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/MinMaxSliderDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/MinMaxSliderDrawer.cs new file mode 100644 index 000000000..4b5369b6d --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/MinMaxSliderDrawer.cs @@ -0,0 +1,122 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Draw a min max slider + /// + /// group: parent group name (Default: none) + /// minPropName: Output Min Property Name + /// maxPropName: Output Max Property Name + /// Target Property Type: Range, range limits express the MinMaxSlider value range + /// Output Min/Max Property Type: Range, it's value is limited by it's range + /// + public class MinMaxSliderDrawer : SubDrawer + { + private string _minPropName; + private string _maxPropName; + + public MinMaxSliderDrawer(string minPropName, string maxPropName) : this("_", minPropName, maxPropName) { } + + public MinMaxSliderDrawer(string group, string minPropName, string maxPropName) + { + this.group = group; + this._minPropName = minPropName; + this._maxPropName = maxPropName; + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Range; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); + inoutPropertyStaticData.AddExtraProperty(_minPropName); + inoutPropertyStaticData.AddExtraProperty(_maxPropName); + } + + public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) + { + if (string.IsNullOrEmpty(_minPropName) + || string.IsNullOrEmpty(_maxPropName) + || !inoutPerMaterialData.propDynamicDatas.ContainsKey(_minPropName) + || !inoutPerMaterialData.propDynamicDatas.ContainsKey(_maxPropName) + ) + { + Debug.LogError("LWGUI: " + inProp.name + " has no available min/max properties!"); + return; + } + + inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = + inoutPerMaterialData.propDynamicDatas[_minPropName].defaultProperty.floatValue + + " - " + + inoutPerMaterialData.propDynamicDatas[_maxPropName].defaultProperty.floatValue; + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + // read min max + MaterialProperty minProp = metaDatas.GetProperty(_minPropName); + MaterialProperty maxProp = metaDatas.GetProperty(_maxPropName); + if (minProp == null || maxProp == null) + { + Debug.LogError("LWGUI: MinMaxSliderDrawer: minProp: " + (minProp == null ? "null" : minProp.name) + " or maxProp: " + (maxProp == null ? "null" : maxProp.name) + " not found!"); + return; + } + float minf = minProp.floatValue; + float maxf = maxProp.floatValue; + + // define draw area + Rect controlRect = position; // this is the full length rect area + var w = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 0; + Rect inputRect = MaterialEditor.GetRectAfterLabelWidth(controlRect); // this is the remaining rect area after label's area + + // draw label + EditorGUI.PrefixLabel(controlRect, label); + + // draw min max slider + var indentLevel = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + Rect[] splittedRect = Helper.SplitRect(inputRect, 3); + + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = minProp.hasMixedValue; + var newMinf = EditorGUI.FloatField(splittedRect[0], minf); + if (Helper.EndChangeCheck(metaDatas, minProp)) + { + minf = Mathf.Clamp(newMinf, minProp.rangeLimits.x, minProp.rangeLimits.y); + minProp.floatValue = minf; + } + + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = maxProp.hasMixedValue; + var newMaxf = EditorGUI.FloatField(splittedRect[2], maxf); + if (Helper.EndChangeCheck(metaDatas, maxProp)) + { + maxf = Mathf.Clamp(newMaxf, maxProp.rangeLimits.x, maxProp.rangeLimits.y); + maxProp.floatValue = maxf; + } + + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + if (splittedRect[1].width > 50f) + EditorGUI.MinMaxSlider(splittedRect[1], ref minf, ref maxf, prop.rangeLimits.x, prop.rangeLimits.y); + EditorGUI.showMixedValue = false; + + // write back min max if changed + if (EditorGUI.EndChangeCheck()) + { + minProp.floatValue = Mathf.Clamp(minf, minProp.rangeLimits.x, minProp.rangeLimits.y); + maxProp.floatValue = Mathf.Clamp(maxf, maxProp.rangeLimits.x, maxProp.rangeLimits.y); + } + + EditorGUI.indentLevel = indentLevel; + EditorGUIUtility.labelWidth = w; + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/MinMaxSliderDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/MinMaxSliderDrawer.cs.meta new file mode 100644 index 000000000..b3c19fa35 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/MinMaxSliderDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07b7eef69a55e7a438e862d05f0a4e82 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/PresetDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/PresetDrawer.cs new file mode 100644 index 000000000..3197e6433 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/PresetDrawer.cs @@ -0,0 +1,111 @@ +// Copyright (c) Jason Ma + +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Popping a menu, you can select the Shader Property Preset, the Preset values will replaces the default values + /// + /// group: parent group name (Default: none) + /// presetFileName: "Shader Property Preset" asset name, you can create new Preset by + /// "Right Click > Create > LWGUI > Shader Property Preset" in Project window, + /// *any Preset in the entire project cannot have the same name* + /// Target Property Type: Float, express current keyword index + /// + public class PresetDrawer : SubDrawer, IPresetDrawer + { + public string presetFileName; + + public PresetDrawer(string presetFileName) : this("_", presetFileName) { } + + public PresetDrawer(string group, string presetFileName) + { + this.group = group; + this.presetFileName = presetFileName; + } + + public static void SetPresetAssetToStaticData(PropertyStaticData inoutPropertyStaticData, string presetFileName) + { + inoutPropertyStaticData.propertyPresetAsset = PresetHelper.GetPresetAsset(presetFileName); + } + + // Apply Keywords and Passes in presets without modifying other property values + // Used to call in MaterialPropertyDrawer.Apply() + public static void ApplyPresetWithoutPropertyChanges(string presetFileName, MaterialProperty prop) + { + var presetFile = PresetHelper.GetPresetAsset(presetFileName); + if (presetFile && ShowIfDecorator.GetShowIfResultToFilterDrawerApplying(prop)) + { + presetFile.TryGetPreset(prop.floatValue)?.ApplyKeywordsAndPassesToMaterials(prop.targets); + } + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Float; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); + SetPresetAssetToStaticData(inoutPropertyStaticData, presetFileName); + } + + public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) + { + var propertyPreset = inPerShaderData.propStaticDatas[inProp.name].propertyPresetAsset; + if (propertyPreset) + inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = propertyPreset.TryGetPreset(inDefaultProp.floatValue)?.presetName; + } + + public string GetPresetFileName() => presetFileName; + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + + var rect = position; + + int index = (int)Mathf.Max(0, prop.floatValue); + var presetFile = PresetHelper.GetPresetAsset(presetFileName); + if (!presetFile || presetFile.GetPresetCount() == 0) + { + Helper.DrawShaderPropertyWithErrorLabel(rect, prop, label, editor, $"Invalid Preset File: {presetFileName}"); + return; + } + + if (index < presetFile.GetPresetCount()) + { + var presetNames = presetFile.GetPresets().Select((inPreset) => new GUIContent(inPreset.presetName)).ToArray(); + if (EditorGUI.showMixedValue) + index = -1; + else + Helper.AdaptiveFieldWidth(EditorStyles.popup, presetNames[index]); + int newIndex = EditorGUI.Popup(rect, label, index, presetNames); + if (Helper.EndChangeCheck(metaDatas, prop)) + { + prop.floatValue = newIndex; + presetFile.TryGetPreset(newIndex)?.ApplyToEditingMaterial(editor, metaDatas.perMaterialData); + } + EditorGUI.showMixedValue = false; + } + else + { + Helper.DrawShaderPropertyWithErrorLabel(position, prop, label, editor, $"Out of Index Range"); + Debug.LogError($"LWGUI: { prop.name } out of Preset index range!"); + } + } + + public override void Apply(MaterialProperty prop) + { + base.Apply(prop); + if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) + { + ApplyPresetWithoutPropertyChanges(presetFileName, prop); + } + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/PresetDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/PresetDrawer.cs.meta new file mode 100644 index 000000000..e09641706 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/PresetDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ce051a8eefac7c4698c3d242f5984ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubEnumDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubEnumDrawer.cs new file mode 100644 index 000000000..199390801 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubEnumDrawer.cs @@ -0,0 +1,57 @@ +// Copyright (c) Jason Ma + +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + public class SubEnumDrawer : KWEnumDrawer + { + // UnityEditor.MaterialEnumDrawer(string enumName) + // enumName: like "UnityEngine.Rendering.BlendMode" + public SubEnumDrawer(string group, string enumName) : base(group, enumName) + { + var array = ReflectionHelper.GetAllTypes(); + try + { + Type enumType = array.FirstOrDefault(x => x.IsSubclassOf(typeof(Enum)) && (x.Name == enumName || x.FullName == enumName)); + string[] names = Enum.GetNames(enumType); + Array valuesArray = Enum.GetValues(enumType); + var values = new float[valuesArray.Length]; + for (int index = 0; index < valuesArray.Length; ++index) + values[index] = (int)valuesArray.GetValue(index); + Init(group, names, null, values); + } + catch (Exception ex) + { + Debug.LogWarningFormat("LWGUI: Failed to create SubEnum, enum {0} not found, {1}.", enumName, ex); + throw; + } + } + + public SubEnumDrawer(string group, string n1, float v1, string n2, float v2) + : base(group, new[] { n1, n2 }, null, new[] { v1, v2 }) { } + + public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3) + : base(group, new[] { n1, n2, n3 }, null, new[] { v1, v2, v3 }) { } + + public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4) + : base(group, new[] { n1, n2, n3, n4 }, null, new[] { v1, v2, v3, v4 }) { } + + public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5) + : base(group, new[] { n1, n2, n3, n4, n5 }, null, new[] { v1, v2, v3, v4, v5 }) { } + + public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6) + : base(group, new[] { n1, n2, n3, n4, n5, n6 }, null, new[] { v1, v2, v3, v4, v5, v6 }) { } + + public SubEnumDrawer(string group, string n1, float v1, string n2, float v2, string n3, float v3, string n4, float v4, string n5, float v5, string n6, float v6, string n7, float v7) + : base(group, new[] { n1, n2, n3, n4, n5, n6, n7 }, null, new[] { v1, v2, v3, v4, v5, v6, v7 }) { } + + protected override string GetKeywordName(string propName, string name) { return "_"; } + + public override void Apply(MaterialProperty prop) { } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubEnumDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubEnumDrawer.cs.meta new file mode 100644 index 000000000..d1b190e3e --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubEnumDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 013f548c15894ab42baddf9d7889a502 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubIntRangeDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubIntRangeDrawer.cs new file mode 100644 index 000000000..41ba29d8a --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubIntRangeDrawer.cs @@ -0,0 +1,49 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Similar to builtin IntRange() + /// + /// group: parent group name (Default: none) + /// Target Property Type: Range + /// + public class SubIntRangeDrawer : SubDrawer + { + public SubIntRangeDrawer(string group) + { + this.group = group; + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Range; } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + RevertableHelper.FixGUIWidthMismatch(prop.GetPropertyType(), editor); + + if (prop.GetPropertyType() != ShaderPropertyType.Range) + { + EditorGUI.LabelField(position, "IntRange used on a non-range property: " + prop.name, EditorStyles.helpBox); + } + else + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 0.0f; + int num = EditorGUI.IntSlider(position, label, (int)prop.floatValue, (int)prop.rangeLimits.x, (int)prop.rangeLimits.y); + EditorGUI.showMixedValue = false; + EditorGUIUtility.labelWidth = labelWidth; + if (Helper.EndChangeCheck(metaDatas, prop)) + { + prop.floatValue = num; + } + } + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubIntRangeDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubIntRangeDrawer.cs.meta new file mode 100644 index 000000000..20981f6b2 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubIntRangeDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cad3b7cf3502fb6469a84d3bbc650fe3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubKeywordEnumDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubKeywordEnumDrawer.cs new file mode 100644 index 000000000..43067df8f --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubKeywordEnumDrawer.cs @@ -0,0 +1,34 @@ +// Copyright (c) Jason Ma + +namespace LWGUI +{ + public class SubKeywordEnumDrawer : KWEnumDrawer + { + public SubKeywordEnumDrawer(string group, string kw1, string kw2) + : base(group, new[] { kw1, kw2 }, new[] { kw1, kw2 }) { } + + public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3) + : base(group, new[] { kw1, kw2, kw3 }, new[] { kw1, kw2, kw3 }) { } + + public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4) + : base(group, new[] { kw1, kw2, kw3, kw4 }, new[] { kw1, kw2, kw3, kw4 }) { } + + public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5) + : base(group, new[] { kw1, kw2, kw3, kw4, kw5 }, new[] { kw1, kw2, kw3, kw4, kw5 }) { } + + public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6) + : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6 }) { } + + public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7) + : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7 }) { } + + public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7, string kw8) + : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8 }) { } + + public SubKeywordEnumDrawer(string group, string kw1, string kw2, string kw3, string kw4, string kw5, string kw6, string kw7, string kw8, string kw9) + : base(group, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8, kw9 }, new[] { kw1, kw2, kw3, kw4, kw5, kw6, kw7, kw8, kw9 }) { } + + protected override string GetKeywordName(string propName, string name) { return (propName + "_" + name).Replace(' ', '_').ToUpperInvariant(); } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubKeywordEnumDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubKeywordEnumDrawer.cs.meta new file mode 100644 index 000000000..d5e3e4923 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubKeywordEnumDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb8756df640ae7340aecbd9bd5b69cd0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubPowerSliderDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubPowerSliderDrawer.cs new file mode 100644 index 000000000..279bc4f1e --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubPowerSliderDrawer.cs @@ -0,0 +1,71 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Similar to builtin PowerSlider() + /// + /// group: parent group name (Default: none) + /// power: power of slider (Default: 1) + /// presetFileName: "Shader Property Preset" asset name, it rounds up the float to choose which Preset to use. + /// You can create new Preset by + /// "Right Click > Create > LWGUI > Shader Property Preset" in Project window, + /// *any Preset in the entire project cannot have the same name* + /// Target Property Type: Range + /// + public class SubPowerSliderDrawer : SubDrawer, IPresetDrawer + { + public string presetFileName; + + private float _power = 1; + + public SubPowerSliderDrawer(float power) : this("_", power) { } + + public SubPowerSliderDrawer(string group, float power) : this(group, power, string.Empty) { } + + public SubPowerSliderDrawer(string group, float power, string presetFileName) + { + this.group = group; + this._power = Mathf.Clamp(power, 0, float.MaxValue); + this.presetFileName = presetFileName; + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Range; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); + PresetDrawer.SetPresetAssetToStaticData(inoutPropertyStaticData, presetFileName); + } + + public string GetPresetFileName() => presetFileName; + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + RevertableHelper.FixGUIWidthMismatch(prop.GetPropertyType(), editor); + EditorGUI.showMixedValue = prop.hasMixedValue; + var rect = position; + var oldValue = prop.floatValue; + ReflectionHelper.DoPowerRangeProperty(rect, prop, label, _power); + if (prop.floatValue != oldValue) + { + PresetHelper.GetPresetAsset(presetFileName)?.TryGetPreset(prop.floatValue)?.ApplyToEditingMaterial(editor, metaDatas.perMaterialData); + } + EditorGUI.showMixedValue = false; + } + + public override void Apply(MaterialProperty prop) + { + base.Apply(prop); + if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) + { + PresetDrawer.ApplyPresetWithoutPropertyChanges(presetFileName, prop); + } + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubPowerSliderDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubPowerSliderDrawer.cs.meta new file mode 100644 index 000000000..e11f910ce --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubPowerSliderDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: add135b9cec858a4594cb70c27996b4c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubToggleDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubToggleDrawer.cs new file mode 100644 index 000000000..050106acc --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubToggleDrawer.cs @@ -0,0 +1,82 @@ +// Copyright (c) Jason Ma + +using System; +using LWGUI.Timeline; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Similar to builtin Toggle() + /// + /// group: parent group name (Default: none) + /// keyword: keyword used for toggle, "_" = ignore, none or "__" = Property Name + "_ON", always Upper (Default: none) + /// preset File Name: "Shader Property Preset" asset name, see Preset() for detail (Default: none) + /// Target Property Type: Float + /// + public class SubToggleDrawer : SubDrawer, IPresetDrawer + { + private string _keyWord = String.Empty; + private string _presetFileName = String.Empty; + + public SubToggleDrawer() { } + + public SubToggleDrawer(string group) : this(group, String.Empty, String.Empty) { } + + public SubToggleDrawer(string group, string keyWord) : this(group, keyWord, String.Empty) { } + + public SubToggleDrawer(string group, string keyWord, string presetFileName) + { + this.group = group; + this._keyWord = keyWord; + this._presetFileName = presetFileName; + } + + protected override bool IsMatchPropType(MaterialProperty property) + { + return property.GetPropertyType() is ShaderPropertyType.Float; + } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); + PresetDrawer.SetPresetAssetToStaticData(inoutPropertyStaticData, _presetFileName); + } + + public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) + { + inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = inDefaultProp.floatValue > 0 ? "On" : "Off"; + } + + public string GetPresetFileName() => _presetFileName; + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.BeginChangeCheck(); + EditorGUI.showMixedValue = prop.hasMixedValue; + var value = EditorGUI.Toggle(position, label, !Helper.Approximately(prop.floatValue, 0)); + if (Helper.EndChangeCheck(metaDatas, prop)) + { + prop.floatValue = value ? 1.0f : 0.0f; + var keyword = Helper.GetKeywordName(_keyWord, prop.name); + Helper.SetShaderKeywordEnabled(editor.targets, keyword, value); + PresetHelper.GetPresetAsset(_presetFileName)?.TryGetPreset(prop.floatValue)?.ApplyToEditingMaterial(editor, metaDatas.perMaterialData); + TimelineHelper.SetKeywordToggleToTimeline(prop, editor, keyword); + } + EditorGUI.showMixedValue = false; + } + + public override void Apply(MaterialProperty prop) + { + base.Apply(prop); + if (!prop.hasMixedValue && VersionControlHelper.IsWriteable(prop.targets)) + { + Helper.SetShaderKeywordEnabled(prop.targets, Helper.GetKeywordName(_keyWord, prop.name), prop.floatValue > 0f); + PresetDrawer.ApplyPresetWithoutPropertyChanges(_presetFileName, prop); + } + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubToggleDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubToggleDrawer.cs.meta new file mode 100644 index 000000000..4026c85ce --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Numeric/SubToggleDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 331ebf4a8183cf3449c56f96443ec24b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other.meta new file mode 100644 index 000000000..a6d3bc2e1 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6bd503fc2f476ef43a556f98bba549b5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other/ButtonDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other/ButtonDrawer.cs new file mode 100644 index 000000000..85c584455 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other/ButtonDrawer.cs @@ -0,0 +1,174 @@ +// Copyright (c) Jason Ma + +using System; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Draw one or more Buttons within the same row, using the Display Name to control the appearance and behavior of the buttons + /// + /// Declaring a set of Button Name and Button Command in Display Name generates a Button, separated by '@': + /// ButtonName0@ButtonCommand0@ButtonName1@ButtonCommand1 + /// + /// Button Name can be any other string, the format of Button Command is: + /// TYPE:Argument + /// + /// The following TYPEs are currently supported: + /// - URL: Open the URL, Argument is the URL + /// - C#: Call the public static C# function, Argument is NameSpace.Class.Method(arg0, arg1, ...), + /// for target function signatures, see: LWGUI.ButtonDrawer.TestMethod(). + /// + /// The full example: + /// [Button(_)] _button0 ("URL Button@URL:https://github.com/JasonMa0012/LWGUI@C#:LWGUI.ButtonDrawer.TestMethod(1234, abcd)", Float) = 0 + /// + /// group: parent group name (Default: none) + /// Target Property Type: Any + /// + public class ButtonDrawer : SubDrawer + { + private const string _urlPrefix = "URL:"; + private const string _csPrefix = "C#:"; + private const string _separator = "@"; + + public ButtonDrawer() { } + + public ButtonDrawer(string group) + { + this.group = group; + } + + protected override float GetVisibleHeight(MaterialProperty prop) => 24; + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + inoutPropertyStaticData.groupName = group; + + // Display Name: ButtonName@URL:XXX@ButtonName@CS:NameSpace.Class.Method(arg0, arg1, ...)@... + var buttonNameAndCommands = inProp.displayName.Split(_separator); + if (buttonNameAndCommands != null && buttonNameAndCommands.Length > 0 && buttonNameAndCommands.Length % 2 == 0) + { + for (int i = 0; i < buttonNameAndCommands.Length; i++) + { + if (i % 2 == 0) + { + inoutPropertyStaticData.buttonDisplayNames.Add(buttonNameAndCommands[i]); + inoutPropertyStaticData.buttonDisplayNameWidths.Add(EditorStyles.label.CalcSize(new GUIContent(buttonNameAndCommands[i])).x); + } + else + { + inoutPropertyStaticData.buttonCommands.Add(buttonNameAndCommands[i]); + } + } + } + else + { + Debug.LogError($"LWGUI: ButtonDrawer with invalid Display Name Commands: { buttonNameAndCommands } ! prop: { inProp.name }"); + } + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + var buttonDisplayNames = metaDatas.GetPropStaticData(prop).buttonDisplayNames; + var buttonDisplayNameWidths = metaDatas.GetPropStaticData(prop).buttonDisplayNameWidths; + var buttonCommands = metaDatas.GetPropStaticData(prop).buttonCommands; + if (buttonDisplayNames == null || buttonCommands == null || buttonDisplayNames.Count == 0 || buttonCommands.Count == 0 + || buttonDisplayNames.Count != buttonCommands.Count) + { + return; + } + + var enbaled = GUI.enabled; + GUI.enabled = true; + + position = EditorGUI.IndentedRect(position); + var rect = new Rect(position.x, position.y, 0, position.height); + var spaceWidth = (position.width - buttonDisplayNameWidths.Sum()) / buttonDisplayNames.Count; + + for (int i = 0; i < buttonDisplayNames.Count; i++) + { + var displayName = buttonDisplayNames[i]; + var displayNameRelativeWidth = buttonDisplayNameWidths[i]; + var command = buttonCommands[i]; + rect.xMax = rect.xMin + displayNameRelativeWidth + spaceWidth; + + if (GUI.Button(rect, new GUIContent(displayName, command))) + { + if (command.StartsWith(_urlPrefix)) + { + Application.OpenURL(command.Substring(_urlPrefix.Length, command.Length - _urlPrefix.Length)); + } + else if (command.StartsWith(_csPrefix)) + { + var csCommand = command.Substring(_csPrefix.Length, command.Length - _csPrefix.Length); + + // Get method name and args + string className = null, methodName = null; + string[] args = null; + { + var lastPointIndex = csCommand.LastIndexOf('.'); + if (lastPointIndex != -1) + { + className = csCommand.Substring(0, lastPointIndex); + var leftBracketIndex = csCommand.IndexOf('('); + if (leftBracketIndex != -1) + { + methodName = csCommand.Substring(lastPointIndex + 1, leftBracketIndex - lastPointIndex - 1); + args = csCommand.Substring(leftBracketIndex + 1, csCommand.Length - leftBracketIndex - 2) + ?.Split(',').Select(s => s.TrimStart()).ToArray(); + } + } + } + + // Find and call method + if (!string.IsNullOrEmpty(className) && !string.IsNullOrEmpty(methodName) && args != null) + { + Type type = ReflectionHelper.GetAllTypes().FirstOrDefault((type1 => type1.Name == className || type1.FullName == className)); + if (type != null) + { + var methodInfo = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public); + if (methodInfo != null) + { + methodInfo.Invoke(null, new object[]{ prop, editor, metaDatas, args }); + } + else + { + Debug.LogError($"LWGUI: Method {methodName} not found in {className}"); + } + } + else + { + Debug.LogError($"LWGUI: Class {className} not found"); + } + } + else + { + Debug.LogError($"LWGUI: Invalid C# command: {csCommand}"); + } + } + else + { + Debug.LogError($"LWGUI: Unknown command type: {command}"); + } + } + + rect.xMin = rect.xMax; + } + + GUI.enabled = enbaled; + } + + public static void TestMethod(MaterialProperty prop, MaterialEditor editor, LWGUIMetaDatas metaDatas, string[] args) + { + Debug.Log($"LWGUI: ButtonDrawer.TestMethod({prop}, {editor}, {metaDatas}, {args})"); + + foreach (var arg in args) + { + Debug.Log(arg); + } + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other/ButtonDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other/ButtonDrawer.cs.meta new file mode 100644 index 000000000..64cad049f --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Other/ButtonDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1dcbe4f8b78506748993e7cf6ba90335 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture.meta new file mode 100644 index 000000000..5a239412d --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f0fa359403898274583e7d3f33c1e381 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/ImageDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/ImageDrawer.cs new file mode 100644 index 000000000..e4498cb4f --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/ImageDrawer.cs @@ -0,0 +1,112 @@ +// Copyright (c) Jason Ma + +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace LWGUI +{ + /// + /// Draw an image preview. + /// display name: The path of the image file relative to the Unity project, such as: "Assets/test.png", "Doc/test.png", "../test.png" + /// + /// group: parent group name (Default: none) + /// Target Property Type: Any + /// + public class ImageDrawer : SubDrawer + { + public ImageDrawer() { } + + public ImageDrawer(string group) + { + this.group = group; + } + + protected override float GetVisibleHeight(MaterialProperty prop) { return 0; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + var inputPath = (inProp.displayName ?? string.Empty).Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); + string imageAbsPath = null; + + try + { + // If the display path already starts with Assets (project-relative), resolve from project root + if (inputPath.StartsWith("Assets")) + { + imageAbsPath = IOHelper.GetAbsPath(inputPath); + } + // If it's an absolute path, use it directly + else if (Path.IsPathRooted(inputPath)) + { + imageAbsPath = inputPath; + } + else + { + // Try resolving relative to the shader file location + var shaderAssetPath = AssetDatabase.GetAssetPath(inShader); + if (!string.IsNullOrEmpty(shaderAssetPath)) + { + var shaderFullPath = IOHelper.GetAbsPath(shaderAssetPath); + var shaderDir = Path.GetDirectoryName(shaderFullPath); + if (!string.IsNullOrEmpty(shaderDir)) + { + // Combine and normalize to resolve ../ segments + var candidate = Path.GetFullPath(Path.Combine(shaderDir, inputPath)); + if (File.Exists(candidate)) + { + imageAbsPath = candidate; + } + } + } + // Fallback: try project-root relative resolution + if (imageAbsPath == null) + { + var candidate2 = IOHelper.GetAbsPath(inputPath); + if (File.Exists(candidate2)) imageAbsPath = candidate2; + } + } + + if (!string.IsNullOrEmpty(imageAbsPath) && File.Exists(imageAbsPath)) + { + var fileData = File.ReadAllBytes(imageAbsPath); + Texture2D texture = new Texture2D(2, 2); + + // LoadImage will auto-resize the texture dimensions + if (texture.LoadImage(fileData)) + { + inoutPropertyStaticData.image = texture; + } + else + { + Debug.LogError($"LWGUI: Failed to load image data into texture: { imageAbsPath }"); + } + } + else + { + Debug.LogError($"LWGUI: Image path not found: { inputPath }"); + } + } + catch (Exception ex) + { + Debug.LogError($"LWGUI: Exception while resolving image path '{inputPath}': {ex.Message}"); + } + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + var image = metaDatas.GetPropStaticData(prop).image; + if (image) + { + var scaledheight = Mathf.Max(0, image.height / (image.width / Helper.GetCurrentPropertyLayoutWidth())); + var rect = EditorGUILayout.GetControlRect(true, scaledheight); + rect = RevertableHelper.IndentRect(EditorGUI.IndentedRect(rect)); + EditorGUI.DrawPreviewTexture(rect, image); + + if (GUI.enabled) + prop.textureValue = null; + } + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/ImageDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/ImageDrawer.cs.meta new file mode 100644 index 000000000..1127d5de1 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/ImageDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 343ef9dd839214847b6a04dad67bca69 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasDrawer.cs new file mode 100644 index 000000000..f9346d11e --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasDrawer.cs @@ -0,0 +1,166 @@ +// Copyright (c) Jason Ma + +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Draw a "Ramp Atlas Scriptable Object" selector and texture preview. + /// The Ramp Atlas SO is responsible for storing multiple ramps and generating the corresponding Ramp Atlas Texture. + /// Use it together with RampAtlasIndexer() to sample specific ramps in Shader using Index, similar to UE's Curve Atlas. + /// Note: Currently, the material only saves Texture reference and Int value, + /// if you manually modify the Ramp Atlas, the references will not update automatically! + /// + /// group: parent group name (Default: none) + /// defaultFileName: the default file name when creating a Ramp Atlas SO (Default: RampAtlas) + /// rootPath: the default directory when creating a Ramp Atlas SO, replace '/' with '.' (for example: Assets.Art.RampAtlas). (Default: Assets) + /// colorSpace: the Color Space of Ramp Atlas Texture. (sRGB/Linear) (Default: sRGB) + /// defaultWidth: default Ramp Atlas Texture width (Default: 256) + /// defaultHeight: default Ramp Atlas Texture height (Default: 4) + /// showAtlasPreview: Draw the preview of Ramp Atlas below (True/False) (Default: True) + /// rampAtlasTypeName: custom RampAtlas type name for user-defined RampAtlas classes (Default: LwguiRampAtlas) + /// Target Property Type: Texture2D + /// + public class RampAtlasDrawer : SubDrawer + { + public string rootPath = "Assets"; + public string defaultFileName = "RampAtlas"; + public bool defaultAtlasSRGB = true; + public int defaultAtlasWidth = 256; + public int defaultAtlasHeight = 2; + public bool showAtlasPreview = true; + public Type rampAtlasType = typeof(LwguiRampAtlas); + + protected LwguiRampAtlas _rampAtlasSO; + + public RampAtlasDrawer() : this(string.Empty) { } + + public RampAtlasDrawer(string group) : this(group, "RampAtlas") { } + + public RampAtlasDrawer(string group, string defaultFileName) : this(group, defaultFileName, "Assets") { } + + public RampAtlasDrawer(string group, string defaultFileName, string rootPath) : this(group, defaultFileName, rootPath, "sRGB") { } + + public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace) : this(group, defaultFileName, rootPath, colorSpace, 256) { } + + public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, 4) { } + + public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, float defaultHeight) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, defaultHeight, "true") { } + + public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, float defaultHeight, string showAtlasPreview) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, defaultHeight, showAtlasPreview, "") { } + + public RampAtlasDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, float defaultHeight, string showAtlasPreview, string rampAtlasTypeName) + { + if (!rootPath.StartsWith(this.rootPath)) + { + Debug.LogError("LWGUI: Ramp Atlas Root Path: '" + rootPath + "' must start with 'Assets'!"); + rootPath = this.rootPath; + } + this.group = group; + this.defaultFileName = defaultFileName; + this.rootPath = rootPath.Replace('.', '/'); + this.defaultAtlasSRGB = colorSpace.ToLower() == "srgb"; + this.defaultAtlasWidth = (int)Mathf.Max(2, defaultWidth); + this.defaultAtlasHeight = (int)Mathf.Max(2, defaultHeight); + this.showAtlasPreview = Helper.StringToBool(showAtlasPreview); + + // Resolve custom RampAtlas type + if (!string.IsNullOrEmpty(rampAtlasTypeName)) + { + var customType = ReflectionHelper.GetTypeByName(rampAtlasTypeName); + if (customType != null && typeof(LwguiRampAtlas).IsAssignableFrom(customType)) + { + rampAtlasType = customType; + } + else + { + Debug.LogError($"LWGUI: RampAtlas type '{rampAtlasTypeName}' not found or not derived from LwguiRampAtlas!"); + } + } + } + + protected override bool IsMatchPropType(MaterialProperty property) => property.GetPropertyType() == ShaderPropertyType.Texture; + + protected override float GetVisibleHeight(MaterialProperty prop) => + EditorGUIUtility.singleLineHeight + + (prop.textureValue && showAtlasPreview ? MaterialEditor.GetDefaultPropertyHeight(prop) + 2.0f : 0); + + public override void GetCustomContextMenus(GenericMenu menu, Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) + { + menu.AddSeparator(""); + menu.AddItem(new GUIContent("Create Ramp Atlas"), false, () => + { + _rampAtlasSO = LwguiRampAtlas.CreateRampAtlasSO(prop, metaDatas, rampAtlasType); + if (_rampAtlasSO) + { + prop.textureValue = _rampAtlasSO.rampAtlasTexture; + LWGUI.OnValidate(metaDatas); + } + }); + + if (_rampAtlasSO) + { + menu.AddItem(new GUIContent("Clone Ramp Atlas"), false, () => + { + var newRampAtlasSO = LwguiRampAtlas.CloneRampAtlasSO(_rampAtlasSO, rampAtlasType); + if (newRampAtlasSO) + { + _rampAtlasSO = newRampAtlasSO; + prop.textureValue = _rampAtlasSO.rampAtlasTexture; + LWGUI.OnValidate(metaDatas); + } + }); + } + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.PrefixLabel(position, label); + + var labelWidth = EditorGUIUtility.labelWidth; + var indentLevel = EditorGUI.indentLevel; + EditorGUIUtility.labelWidth = 0; + EditorGUI.indentLevel = 0; + + var fieldRect = MaterialEditor.GetRectAfterLabelWidth(position); + var rampAtlasSORect = new Rect(fieldRect.x, fieldRect.y, fieldRect.width, EditorGUIUtility.singleLineHeight); + var rampAtlasTextureRect = new Rect(fieldRect.x, rampAtlasSORect.yMax + 2.0f, fieldRect.width, MaterialEditor.GetDefaultPropertyHeight(prop)); + + _rampAtlasSO = LwguiRampAtlas.LoadRampAtlasSO(prop.textureValue); + + // Disable ObjectField's Context Menu + var e = Event.current; + if (e?.type == EventType.MouseDown && Event.current.button == 1 + && (rampAtlasSORect.Contains(e.mousePosition))) + { + e.Use(); + } + + EditorGUI.BeginChangeCheck(); + _rampAtlasSO = (LwguiRampAtlas)EditorGUI.ObjectField(rampAtlasSORect, GUIContent.none, _rampAtlasSO, rampAtlasType, false); + if (EditorGUI.EndChangeCheck()) + { + prop.textureValue = LwguiRampAtlas.LoadRampAtlasTexture(_rampAtlasSO); + + if (_rampAtlasSO && !prop.textureValue) + { + Debug.LogError($"LWGUI: Can NOT load the Ramp Atlas Texture from: { _rampAtlasSO.name }"); + } + } + + if (showAtlasPreview && prop.textureValue && !prop.hasMixedValue) + { + var filter = prop.textureValue.filterMode; + prop.textureValue.filterMode = FilterMode.Point; + EditorGUI.DrawPreviewTexture(rampAtlasTextureRect, prop.textureValue); + prop.textureValue.filterMode = filter; + } + + EditorGUIUtility.labelWidth = labelWidth; + EditorGUI.indentLevel = indentLevel; + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasDrawer.cs.meta new file mode 100644 index 000000000..8fc956a58 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 122a05b8239d8484abbafc922575270b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs new file mode 100644 index 000000000..65e29a760 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs @@ -0,0 +1,309 @@ +// Copyright (c) Jason Ma + +using LWGUI.LwguiGradientEditor; +using LWGUI.Runtime.LwguiGradient; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Visually similar to Ramp(), but RampAtlasIndexer() must be used together with RampAtlas(). + /// The actual stored value is the index of the current Ramp in the Ramp Atlas SO, used for sampling the Ramp Atlas Texture in the Shader. + /// + /// group: parent group name. + /// rampAtlasPropName: RampAtlas() property name. + /// defaultRampName: default ramp name. (Default: Ramp) + /// colorSpace: default ramp color space. (sRGB/Linear) (Default: sRGB) + /// viewChannelMask: editable channels. (Default: RGBA) + /// timeRange: the abscissa display range (1/24/2400), is used to optimize the editing experience when the abscissa is time of day. (Default: 1) + /// Target Property Type: Float + /// + public class RampAtlasIndexerDrawer : RampDrawer + { + public string rampAtlasPropName = string.Empty; + public string defaultRampName = "Ramp"; + + private MaterialProperty _rampAtlasProp; + public MaterialProperty rampAtlasProp + { + get + { + if (_rampAtlasProp == null) + { + var prop = metaDatas?.GetProperty(rampAtlasPropName); + if (prop != null && prop.GetPropertyType() == ShaderPropertyType.Texture) + _rampAtlasProp = prop; + } + return _rampAtlasProp; + } + set => _rampAtlasProp = value; + } + + private LwguiRampAtlas _rampAtlasSO; + public LwguiRampAtlas rampAtlasSO + { + get => _rampAtlasSO ??= LwguiRampAtlas.LoadRampAtlasSO(rampAtlasProp?.textureValue); + set => _rampAtlasSO = value; + } + + private IRamp _currentRamp; + private bool _rampAtlasSOHasMixedValue; + private bool _isOutOfRange; + + private static readonly float _previewRowHeight = EditorGUIUtility.singleLineHeight; + private static readonly float _previewRowSpacing = 2f; + + private int currentRowCount => rampAtlasSO?.RowCountPerRamp ?? 1; + + protected override float rampPreviewHeight => currentRowCount * _previewRowHeight + Mathf.Max(0, currentRowCount - 1) * _previewRowSpacing; + + public RampAtlasIndexerDrawer(string group, string rampAtlasPropName) : this(group, rampAtlasPropName, "Ramp") {} + + public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName) : this(group, rampAtlasPropName, defaultRampName, "sRGB") {} + + public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName, string colorSpace) : this(group, rampAtlasPropName, defaultRampName, colorSpace, "RGBA") {} + + public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName, string colorSpace, string viewChannelMask) : this(group, rampAtlasPropName, defaultRampName, colorSpace, viewChannelMask, 1) {} + + public RampAtlasIndexerDrawer(string group, string rampAtlasPropName, string defaultRampName, string colorSpace, string viewChannelMask, float timeRange) + { + this.group = group; + this.rampAtlasPropName = rampAtlasPropName; + this.defaultRampName = defaultRampName; + this.colorSpace = colorSpace.ToLower() == "linear" ? ColorSpace.Linear : ColorSpace.Gamma; + this.viewChannelMask = LwguiGradient.ChannelMask.None; + { + viewChannelMask = viewChannelMask.ToLower(); + for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) + { + if (viewChannelMask.Contains(LwguiGradient.channelNames[c])) + this.viewChannelMask |= LwguiGradient.ChannelIndexToMask(c); + } + } + this.timeRange = LwguiGradient.GradientTimeRange.One; + { + if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFour) + this.timeRange = LwguiGradient.GradientTimeRange.TwentyFour; + else if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFourHundred) + this.timeRange = LwguiGradient.GradientTimeRange.TwentyFourHundred; + } + } + + protected override bool IsMatchPropType(MaterialProperty property) => property.GetPropertyType() is ShaderPropertyType.Float or ShaderPropertyType.Int; + + protected override void OnRampPropUpdate(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + if (doRegisterUndo) + OnGradientEditorChange(null); + } + + protected override void OnGradientEditorChange(LwguiGradient gradient) + { + rampAtlasSO?.UpdateTexturePixels(); + } + + protected override void OnEditRampMap(MaterialProperty prop, LwguiGradient gradient) + { + OnGradientEditorChange(null); + } + + protected override void OnSaveRampMap(MaterialProperty prop, LwguiGradient gradient) + { + rampAtlasSO?.SaveTexture(checkoutAndForceWrite:true); + rampAtlasSO?.SaveRampAtlasSO(); + } + + protected override LwguiGradient GetLwguiGradient(MaterialProperty prop, out bool isDirty) + { + isDirty = false; + if (rampAtlasSO && (int)prop.GetNumericValue() < rampAtlasSO.RampCount) + { + _currentRamp = rampAtlasSO.GetRamp((int)prop.GetNumericValue()); + if (_currentRamp == null) + return null; + + isDirty = EditorUtility.IsDirty(rampAtlasSO); + colorSpace = _currentRamp.ColorSpace; + viewChannelMask = _currentRamp.ChannelMask; + timeRange = _currentRamp.TimeRange; + return _currentRamp.Gradient; + } + else + return null; + } + + protected override void CloneRampMap(MaterialProperty prop, MaterialEditor editor, LwguiGradient gradient) + { + // Create or Clone a Ramp + if (rampAtlasSO) + { + bool shouldCreateRamp = gradient == null || _currentRamp == null; + var newIndex = rampAtlasSO.RampCount; + var newRamp = rampAtlasSO.AddRamp(shouldCreateRamp ? null : _currentRamp); + + if (shouldCreateRamp) + { + newRamp.Name = defaultRampName; + newRamp.ColorSpace = colorSpace; + newRamp.ChannelMask = viewChannelMask; + newRamp.TimeRange = timeRange; + } + + prop.SetNumericValue(newIndex); + + if (rampAtlasSO.TotalRowCount > rampAtlasSO.rampAtlasHeight) + rampAtlasSO.rampAtlasHeight *= 2; + + rampAtlasSO.UpdateTexturePixels(); + } + // Create a Ramp Atlas SO + else + { + var newRampAtlasSO = LwguiRampAtlas.CreateRampAtlasSO(rampAtlasProp, metaDatas); + if (newRampAtlasSO) + { + rampAtlasSO = newRampAtlasSO; + rampAtlasProp.textureValue = rampAtlasSO.rampAtlasTexture; + } + } + } + + protected void SwitchRamp(MaterialProperty prop, int index) + { + prop.SetNumericValue(index); + LWGUI.OnValidate(metaDatas); + } + + protected override LwguiGradient DiscardRampMap(MaterialProperty prop, LwguiGradient gradient) + { + rampAtlasSO?.DiscardChanges(); + _currentRamp = rampAtlasSO?.GetRamp((int)prop.GetNumericValue()); + return _currentRamp?.Gradient; + } + + // Selector button is drawn together with preview in DrawRampObjectField + protected override void DrawRampSelector(Rect selectButtonRect, MaterialProperty prop, LwguiGradient gradient) { } + + /// + /// Draw rampAtlasSO Fallback Field + /// + protected override void DrawRampObjectField(Rect rampFieldRect, MaterialProperty prop, LwguiGradient gradient) + { + if (!rampAtlasSO || _rampAtlasSOHasMixedValue) + { + EditorGUI.BeginChangeCheck(); + var newRampAtlasSO = EditorGUI.ObjectField(rampFieldRect, rampAtlasSO, typeof(LwguiRampAtlas), false) as LwguiRampAtlas; + if (EditorGUI.EndChangeCheck()) + { + rampAtlasSO = newRampAtlasSO; + metaDatas.GetProperty(rampAtlasPropName).textureValue = rampAtlasSO?.rampAtlasTexture; + } + } + } + + /// + /// Draw Ramp Preview And Selector + /// + protected override void DrawPreviewTextureOverride(Rect previewRect, Rect fieldRect, MaterialProperty prop, LwguiGradient gradient) + { + if (!rampAtlasSO || _rampAtlasSOHasMixedValue) + return; + + var previewWidth = previewRect.width; + var selectorButtonWidth = EditorGUIUtility.singleLineHeight; + + if (_currentRamp == null || _isOutOfRange || EditorGUI.showMixedValue) + { + // Draw Invalid Ramp Fallback + // Draw border + GUI.Box(fieldRect, "None", EditorStyles.objectField); + + // Draw button + var buttonRect = new Rect(previewRect.xMax - 1, fieldRect.y + 1, selectorButtonWidth - 0, rampPreviewHeight - 2); + if (GUI.Button(buttonRect, GUIContent.none, GUIStyles.objectFieldButton)) + { + RampSelectorWindow.ShowWindow(prop, rampAtlasSO, SwitchRamp); + } + } + else + { + var gradients = _currentRamp.GetGradients(); + var gradientCount = gradients?.Length ?? 0; + if (gradientCount == 0) return; + + // Draw gradient previews (clickable to edit) + for (int i = 0; i < gradientCount; i++) + { + if (gradients[i] == null) continue; + + var rowY = fieldRect.y + i * (_previewRowHeight + _previewRowSpacing); + var rowRect = new Rect(fieldRect.x, rowY, previewWidth, _previewRowHeight); + + // Draw border + GUI.Box(rowRect, GUIContent.none, EditorStyles.objectField); + + // Draw gradient with alpha channel (clickable to edit) + var innerRect = new Rect(rowRect.x + 1, rowRect.y + 1, rowRect.width - 2, rowRect.height - 2); + LwguiGradientEditorHelper.GradientPreviewField(innerRect, gradients[i], colorSpace, viewChannelMask, timeRange, OnGradientEditorChange); + } + + // Draw selector button (ObjectField picker style, stretches to cover all preview rows) + { + // Draw border + var selectButtonRect = new Rect(previewRect.xMax - 2, fieldRect.y, selectorButtonWidth + 2, rampPreviewHeight); + GUI.Box(selectButtonRect, GUIContent.none, EditorStyles.objectField); + + // Draw button + var innerRect = new Rect(selectButtonRect.x + 0, selectButtonRect.y + 1, selectButtonRect.width - 1, selectButtonRect.height - 2); + if (GUI.Button(innerRect, GUIContent.none, GUIStyles.objectFieldButton)) + { + RampSelectorWindow.ShowWindow(prop, rampAtlasSO, SwitchRamp); + } + } + } + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + rampAtlasProp = metaDatas.GetProperty(rampAtlasPropName); + if (rampAtlasProp == null || rampAtlasProp.GetPropertyType() != ShaderPropertyType.Texture) + { + Helper.DrawShaderPropertyWithErrorLabel(position, prop, label, editor, "Invalid rampAtlasPropName"); + Debug.LogError($"LWGUI: Property { prop.name } has invalid rampAtlasPropName: { rampAtlasPropName }"); + return; + } + + // Add Info to label + var currentIndex = (int)prop.GetNumericValue(); + label.tooltip += $"\nCurrent Value: {currentIndex}"; + if (rampAtlasSO) + { + _isOutOfRange = currentIndex >= rampAtlasSO.RampCount; + var info = _isOutOfRange ? "OUT OF RANGE!" : rampAtlasSO.GetRamp(currentIndex)?.Name ?? "NULL"; + label.text += $" ({ currentIndex }: { info } - { rampAtlasSO.RampCount })"; + } + else + { + _isOutOfRange = false; + label.text += $" ({ currentIndex } - NULL)"; + } + + // Handle Mixed Value + _rampAtlasSOHasMixedValue = rampAtlasProp.hasMixedValue; + var showMixedValue = EditorGUI.showMixedValue; + EditorGUI.showMixedValue = prop.hasMixedValue || _rampAtlasSOHasMixedValue; + + + base.DrawProp(position, prop, label, editor); + + + // Clear + _rampAtlasProp = null; + _rampAtlasSO = null; + _currentRamp = null; + EditorGUI.showMixedValue = showMixedValue; + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs.meta new file mode 100644 index 000000000..ce22f6e7c --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampAtlasIndexerDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4fd29490f9fb904680cb50a2f83ceb5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs new file mode 100644 index 000000000..4bf893905 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs @@ -0,0 +1,321 @@ +// Copyright (c) Jason Ma + +using System; +using System.IO; +using LWGUI.LwguiGradientEditor; +using LWGUI.Runtime.LwguiGradient; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Draw an unreal style Ramp Map Editor (Default Ramp Map Resolution: 256 * 2) + /// NEW: The new LwguiGradient type has both the Gradient and Curve editors, and can be used in C# scripts and runtime, and is intended to replace UnityEngine.Gradient + /// + /// group: parent group name (Default: none) + /// defaultFileName: default Ramp Map file name when create a new one (Default: RampMap) + /// rootPath: the path where ramp is stored, replace '/' with '.' (for example: Assets.Art.Ramps). when selecting ramp, it will also be filtered according to the path (Default: Assets) + /// colorSpace: switch sRGB / Linear in ramp texture import setting (Default: sRGB) + /// defaultWidth: default Ramp Width. (Default: 256) + /// viewChannelMask: editable channels. (Default: RGBA) + /// timeRange: the abscissa display range (1/24/2400), is used to optimize the editing experience when the abscissa is time of day. (Default: 1) + /// Target Property Type: Texture2D + /// + public class RampDrawer : SubDrawer + { + public static readonly string DefaultRootPath = "Assets"; + + public string rootPath = "Assets"; + public string saveFilePanelTitle = "Create New Ramp Texture"; + public string defaultFileName = "RampMap"; + public string fileExtension = "png"; + public int defaultWidth = 256; + public int defaultHeight = 2; + public ColorSpace colorSpace = ColorSpace.Gamma; + public LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All; + public LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One; + public bool doRegisterUndo; + + private static readonly float _rampButtonsHeight = EditorGUIUtility.singleLineHeight; + + protected virtual float rampPreviewHeight => EditorGUIUtility.singleLineHeight; + + protected override float GetVisibleHeight(MaterialProperty prop) { return rampPreviewHeight + _rampButtonsHeight; } + + public RampDrawer() : this(String.Empty) { } + + public RampDrawer(string group) : this(group, "RampMap") { } + + public RampDrawer(string group, string defaultFileName) : this(group, defaultFileName, DefaultRootPath, 256) { } + + public RampDrawer(string group, string defaultFileName, float defaultWidth) : this(group, defaultFileName, DefaultRootPath, defaultWidth) { } + + public RampDrawer(string group, string defaultFileName, string rootPath, float defaultWidth) : this(group, defaultFileName, rootPath, "sRGB", defaultWidth) { } + + public RampDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, "RGBA") { } + + public RampDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, string viewChannelMask) : this(group, defaultFileName, rootPath, colorSpace, defaultWidth, viewChannelMask, 1) { } + + public RampDrawer(string group, string defaultFileName, string rootPath, string colorSpace, float defaultWidth, string viewChannelMask, float timeRange) + { + if (!rootPath.StartsWith(DefaultRootPath)) + { + Debug.LogError("LWGUI: Ramp Root Path: '" + rootPath + "' must start with 'Assets'!"); + rootPath = DefaultRootPath; + } + this.group = group; + this.defaultFileName = defaultFileName; + this.rootPath = rootPath.Replace('.', '/'); + this.colorSpace = colorSpace.ToLower() == "linear" ? ColorSpace.Linear : ColorSpace.Gamma; + this.defaultWidth = (int)Mathf.Max(2, defaultWidth); + this.viewChannelMask = LwguiGradient.ChannelMask.None; + { + viewChannelMask = viewChannelMask.ToLower(); + for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) + { + if (viewChannelMask.Contains(LwguiGradient.channelNames[c])) + this.viewChannelMask |= LwguiGradient.ChannelIndexToMask(c); + } + + if (this.viewChannelMask == (LwguiGradient.ChannelMask.RGB | LwguiGradient.ChannelMask.Alpha)) + this.viewChannelMask = LwguiGradient.ChannelMask.All; + } + this.timeRange = LwguiGradient.GradientTimeRange.One; + { + if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFour) + this.timeRange = LwguiGradient.GradientTimeRange.TwentyFour; + else if ((int)timeRange == (int)LwguiGradient.GradientTimeRange.TwentyFourHundred) + this.timeRange = LwguiGradient.GradientTimeRange.TwentyFourHundred; + } + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Texture; } + + protected virtual void OnRampPropUpdate(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) { } + + protected virtual void OnCreateNewRampMap(MaterialProperty prop) { } + + protected virtual void OnGradientEditorChange(LwguiGradient gradient) { } + + protected virtual void OnEditRampMap(MaterialProperty prop, LwguiGradient gradient) { } + + protected virtual void OnSaveRampMap(MaterialProperty prop, LwguiGradient gradient) { } + + protected virtual void OnDiscardRampMap(MaterialProperty prop, LwguiGradient gradient) { } + + protected virtual void OnSwitchRampMap(MaterialProperty prop, Texture2D newRampMap, int index) { } + + protected virtual LwguiGradient GetLwguiGradient(MaterialProperty prop, out bool isDirty) + { + return RampHelper.GetGradientFromTexture(prop.textureValue, out isDirty, false, doRegisterUndo); + } + + protected virtual void EditWhenNoRampMap(MaterialProperty prop, MaterialEditor editor) + { + LwguiGradientWindow.CloseWindow(); + CreateNewRampMap(prop, editor); + OnCreateNewRampMap(prop); + LWGUI.OnValidate(metaDatas); + } + + protected virtual void CreateNewRampMap(MaterialProperty prop, MaterialEditor editor) + { + CloneRampMap(prop, editor, null); + } + + protected virtual void CloneRampMap(MaterialProperty prop, MaterialEditor editor, LwguiGradient gradient) + { + string createdFileRelativePath = string.Empty; + while (true) + { + var absRootPath = IOHelper.GetAbsPath(rootPath); + if (!Directory.Exists(absRootPath)) + Directory.CreateDirectory(absRootPath); + + // TODO: Warning: + // PropertiesGUI() is being called recursively. If you want to render the default gui for shader properties then call PropertiesDefaultGUI() instead + var absPath = EditorUtility.SaveFilePanel(saveFilePanelTitle, rootPath, defaultFileName, fileExtension); + + if (absPath.StartsWith(absRootPath)) + { + createdFileRelativePath = IOHelper.GetRelativePath(absPath); + break; + } + else if (absPath != string.Empty) + { + var retry = EditorUtility.DisplayDialog("Invalid Path", $"Please select the subdirectory of '{absRootPath}'", "Retry", "Cancel"); + if (!retry) break; + } + else + { + break; + } + } + + if (!string.IsNullOrEmpty(createdFileRelativePath)) + { + var width = prop.textureValue != null ? prop.textureValue.width : defaultWidth; + var height = prop.textureValue != null ? prop.textureValue.height : defaultHeight; + RampHelper.CreateAndSaveNewGradientTexture(width, height, createdFileRelativePath, colorSpace == ColorSpace.Linear, gradient); + prop.textureValue = AssetDatabase.LoadAssetAtPath(createdFileRelativePath); + EditorGUIUtility.PingObject(prop.textureValue); + } + } + + protected virtual void ChangeRampMap(MaterialProperty prop, LwguiGradient gradient) + { + RampHelper.SetGradientToTexture(prop.textureValue, gradient, false); + } + + protected virtual void SaveRampMap(MaterialProperty prop, LwguiGradient gradient) + { + RampHelper.SetGradientToTexture(prop.textureValue, gradient, true); + } + + protected virtual void SwitchRampMap(MaterialProperty prop, Texture2D newRampMap, int index) + { + prop.textureValue = newRampMap; + OnSwitchRampMap(prop, newRampMap, index); + LWGUI.OnValidate(metaDatas); + } + + protected virtual LwguiGradient DiscardRampMap(MaterialProperty prop, LwguiGradient gradient) + { + // Tex > Gradient + gradient = RampHelper.GetGradientFromTexture(prop.textureValue, out _, true); + // GradientObject > Tex + RampHelper.SetGradientToTexture(prop.textureValue, gradient, true); + return gradient; + } + + protected virtual void DrawRampSelector(Rect selectButtonRect, MaterialProperty prop, LwguiGradient gradient) + { + RampHelper.RampMapSelectorOverride(selectButtonRect, prop, rootPath, SwitchRampMap); + } + + // Manual replace ramp map + protected virtual void DrawRampObjectField(Rect rampFieldRect, MaterialProperty prop, LwguiGradient gradient) + { + EditorGUI.BeginChangeCheck(); + var newManualSelectedTexture = (Texture2D)EditorGUI.ObjectField(rampFieldRect, prop.textureValue, typeof(Texture2D), false); + if (Helper.EndChangeCheck(metaDatas, prop)) + { + if (newManualSelectedTexture && !AssetDatabase.GetAssetPath(newManualSelectedTexture).StartsWith(rootPath)) + EditorUtility.DisplayDialog("Invalid Path", "Please select the subdirectory of '" + rootPath + "'", "OK"); + else + SwitchRampMap(prop, newManualSelectedTexture, 0); + } + } + + protected virtual void DrawPreviewTextureOverride(Rect previewRect, Rect fieldRect, MaterialProperty prop, LwguiGradient gradient) + { + if (!prop.hasMixedValue && gradient != null) + { + LwguiGradientEditorHelper.DrawGradientWithSeparateAlphaChannel(previewRect, gradient, colorSpace, viewChannelMask); + } + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + var labelWidth = EditorGUIUtility.labelWidth; + var indentLevel = EditorGUI.indentLevel; + + OnRampPropUpdate(position, prop, label, editor); + + var gradient = GetLwguiGradient(prop, out var isDirty); + + // Draw Label + var labelRect = new Rect(position); + { + labelRect.height = rampPreviewHeight; + EditorGUI.PrefixLabel(labelRect, label); + } + + // Ramp buttons Rect + var buttonRect = new Rect(position); + { + EditorGUIUtility.labelWidth = 0; + EditorGUI.indentLevel = 0; + buttonRect.yMin = buttonRect.yMax - EditorGUIUtility.singleLineHeight; + buttonRect = MaterialEditor.GetRectAfterLabelWidth(buttonRect); + if (buttonRect.width < 50f) return; + } + + // Draw Ramp Editor + RampHelper.RampEditor(buttonRect, ref gradient, colorSpace, viewChannelMask, timeRange, isDirty, + out bool hasGradientChanges, + out bool doEditWhenNoGradient, + out doRegisterUndo, + out bool doClone, + out bool doCreate, + out bool doSaveGradient, + out bool doDiscardGradient, + OnGradientEditorChange); + + // Edit When No Gradient + if (doEditWhenNoGradient) + { + EditWhenNoRampMap(prop, editor); + } + + // Clone + if (doClone) + { + LwguiGradientWindow.CloseWindow(); + CloneRampMap(prop, editor, gradient); + OnCreateNewRampMap(prop); + LWGUI.OnValidate(metaDatas); + } + + // Create + if (doCreate) + { + LwguiGradientWindow.CloseWindow(); + CreateNewRampMap(prop, editor); + OnCreateNewRampMap(prop); + LWGUI.OnValidate(metaDatas); + } + + // Change + if (hasGradientChanges && gradient != null) + { + ChangeRampMap(prop, gradient); + OnEditRampMap(prop, gradient); + } + + // Save + if (doSaveGradient && gradient != null) + { + SaveRampMap(prop, gradient); + OnSaveRampMap(prop, gradient); + } + + // Discard + if (doDiscardGradient) + { + LwguiGradientWindow.CloseWindow(); + gradient = DiscardRampMap(prop, gradient); + OnDiscardRampMap(prop, gradient); + } + + // Texture Object Field, handle switch texture event + var rampFieldRect = MaterialEditor.GetRectAfterLabelWidth(labelRect); + rampFieldRect.height = labelRect.height; + var previewRect = new Rect(rampFieldRect.x + 0.5f, rampFieldRect.y + 0.5f, rampFieldRect.width - 18, rampFieldRect.height - 0.5f); + { + var selectButtonRect = new Rect(previewRect.xMax, rampFieldRect.y, rampFieldRect.width - previewRect.width, rampFieldRect.height); + DrawRampSelector(selectButtonRect, prop, gradient); + + DrawRampObjectField(rampFieldRect, prop, gradient); + } + + // Preview texture override (larger preview, hides texture name) + DrawPreviewTextureOverride(previewRect, rampFieldRect, prop, gradient); + + EditorGUIUtility.labelWidth = labelWidth; + EditorGUI.indentLevel = indentLevel; + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs.meta new file mode 100644 index 000000000..acc961912 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/RampDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f4cae92fbbe1b44b984adee7caea5a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/TexDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/TexDrawer.cs new file mode 100644 index 000000000..9d5f72352 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/TexDrawer.cs @@ -0,0 +1,93 @@ +// Copyright (c) Jason Ma + +using System; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Draw a Texture property in single line with a extra property + /// + /// group: parent group name (Default: none) + /// extraPropName: extra property name (Default: none) + /// Target Property Type: Texture + /// Extra Property Type: Color, Vector + /// Target Property Type: Texture2D + /// + public class TexDrawer : SubDrawer + { + private string _extraPropName = String.Empty; + private ChannelDrawer _channelDrawer = new ChannelDrawer(); + + public TexDrawer() { } + + public TexDrawer(string group) : this(group, String.Empty) { } + + public TexDrawer(string group, string extraPropName) + { + this.group = group; + this._extraPropName = extraPropName; + } + + protected override float GetVisibleHeight(MaterialProperty prop) { return EditorGUIUtility.singleLineHeight; } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Texture; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); + inoutPropertyStaticData.AddExtraProperty(_extraPropName); + } + + public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) + { + var defaultExtraProp = inoutPerMaterialData.GetPropDynamicData(_extraPropName)?.defaultProperty; + if (defaultExtraProp != null) + { + var text = string.Empty; + if (defaultExtraProp.GetPropertyType() == ShaderPropertyType.Vector) + text = ChannelDrawer.GetChannelName(defaultExtraProp); + else + text = RevertableHelper.GetPropertyDefaultValueText(defaultExtraProp); + + inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = + RevertableHelper.GetPropertyDefaultValueText(inDefaultProp) + ", " + text; + } + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.showMixedValue = prop.hasMixedValue; + var rect = position; + + MaterialProperty extraProp = metaDatas.GetProperty(_extraPropName); + if (extraProp != null + // && ( + // extraProp.type == MaterialProperty.PropType.Color + // || extraProp.type == MaterialProperty.PropType.Vector + // ) + ) + { + var i = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + + var extraRect = MaterialEditor.GetRightAlignedFieldRect(rect); + extraRect.height = rect.height; + + if (extraProp.GetPropertyType() == ShaderPropertyType.Vector) + _channelDrawer.OnGUI(extraRect, extraProp, GUIContent.none, editor); + else + editor.ShaderProperty(extraRect, extraProp, GUIContent.none); + + EditorGUI.indentLevel = i; + } + + editor.TexturePropertyMiniThumbnail(rect, prop, label.text, label.tooltip); + + EditorGUI.showMixedValue = false; + } + } +} + diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/TexDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/TexDrawer.cs.meta new file mode 100644 index 000000000..8485db0f1 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Texture/TexDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01d437464f05cec4c94a6d090d664a62 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector.meta new file mode 100644 index 000000000..e66d768b3 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65fd85b7ea5b45c49891bdc4c027d8cf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ChannelDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ChannelDrawer.cs new file mode 100644 index 000000000..f6a0f95cf --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ChannelDrawer.cs @@ -0,0 +1,96 @@ +// Copyright (c) Jason Ma + +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Draw a R/G/B/A drop menu: + /// R = (1, 0, 0, 0) + /// G = (0, 1, 0, 0) + /// B = (0, 0, 1, 0) + /// A = (0, 0, 0, 1) + /// RGB Average = (1f / 3f, 1f / 3f, 1f / 3f, 0) + /// RGB Luminance = (0.2126f, 0.7152f, 0.0722f, 0) + /// None = (0, 0, 0, 0) + /// + /// group: parent group name (Default: none) + /// Target Property Type: Vector, used to dot() with Texture Sample Value + /// + public class ChannelDrawer : SubDrawer + { + private static GUIContent[] _names = new[] + { + new GUIContent("R"), + new GUIContent("G"), + new GUIContent("B"), + new GUIContent("A"), + new GUIContent("RGB Average"), + new GUIContent("RGB Luminance"), + new GUIContent("None") + }; + private static int[] _intValues = new int[] { 0, 1, 2, 3, 4, 5, 6 }; + private static Vector4[] _vector4Values = new[] + { + new Vector4(1, 0, 0, 0), + new Vector4(0, 1, 0, 0), + new Vector4(0, 0, 1, 0), + new Vector4(0, 0, 0, 1), + new Vector4(1f / 3f, 1f / 3f, 1f / 3f, 0), + new Vector4(0.2126f, 0.7152f, 0.0722f, 0), + new Vector4(0, 0, 0, 0) + }; + + public ChannelDrawer() { } + + public ChannelDrawer(string group) + { + this.group = group; + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Vector; } + + private static int GetChannelIndex(MaterialProperty prop) + { + int index = -1; + for (int i = 0; i < _vector4Values.Length; i++) + { + if (prop.vectorValue == _vector4Values[i]) + index = i; + } + if (index == -1) + { + Debug.LogError("LWGUI: Channel Property: " + prop.name + " invalid vector found, reset to A"); + prop.vectorValue = _vector4Values[3]; + index = 3; + } + return index; + } + + public static string GetChannelName(MaterialProperty prop) + { + return _names[GetChannelIndex(prop)].text; + } + + public override void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) + { + inoutPerMaterialData.propDynamicDatas[inProp.name].defaultValueDescription = GetChannelName(inDefaultProp); + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + EditorGUI.BeginChangeCheck(); + + EditorGUI.showMixedValue = prop.hasMixedValue; + var index = GetChannelIndex(prop); + int num = EditorGUI.IntPopup(position, label, index, _names, _intValues); + EditorGUI.showMixedValue = false; + if (Helper.EndChangeCheck(metaDatas, prop)) + { + prop.vectorValue = _vector4Values[num]; + } + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ChannelDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ChannelDrawer.cs.meta new file mode 100644 index 000000000..c55342d04 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ChannelDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 339426a90d6e874498d6f906e064d12a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ColorDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ColorDrawer.cs new file mode 100644 index 000000000..e6a6727cb --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ColorDrawer.cs @@ -0,0 +1,89 @@ +// Copyright (c) Jason Ma + +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEngine.Rendering; + +namespace LWGUI +{ + /// + /// Display up to 4 colors in a single line + /// + /// group: parent group name (Default: none) + /// color2-4: extra color property name + /// Target Property Type: Color + /// + public class ColorDrawer : SubDrawer + { + private string[] _colorStrings = new string[3]; + + public ColorDrawer(string group, string color2) : this(group, color2, String.Empty, String.Empty) { } + + public ColorDrawer(string group, string color2, string color3) : this(group, color2, color3, String.Empty) { } + + public ColorDrawer(string group, string color2, string color3, string color4) + { + this.group = group; + this._colorStrings[0] = color2; + this._colorStrings[1] = color3; + this._colorStrings[2] = color4; + } + + protected override bool IsMatchPropType(MaterialProperty property) { return property.GetPropertyType() == ShaderPropertyType.Color; } + + public override void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) + { + base.BuildStaticMetaData(inShader, inProp, inProps, inoutPropertyStaticData); + foreach (var colorPropName in _colorStrings) + { + inoutPropertyStaticData.AddExtraProperty(colorPropName); + } + } + + public override void DrawProp(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) + { + var cProps = new Stack(); + for (int i = 0; i < 4; i++) + { + if (i == 0) + { + cProps.Push(prop); + continue; + } + + var p = metaDatas.GetProperty(_colorStrings[i - 1]); + if (p != null && IsMatchPropType(p)) + cProps.Push(p); + } + + var count = cProps.Count; + var colorArray = cProps.ToArray(); + + EditorGUI.PrefixLabel(position, label); + + for (int i = 0; i < count; i++) + { + EditorGUI.BeginChangeCheck(); + var cProp = colorArray[i]; + EditorGUI.showMixedValue = cProp.hasMixedValue; + var r = new Rect(position); + var interval = 13 * i * (-0.25f + EditorGUI.indentLevel * 1.25f); + var w = EditorGUIUtility.fieldWidth * (0.8f + EditorGUI.indentLevel * 0.2f); + r.xMin += r.width - w * (i + 1) + interval; + r.xMax -= w * i - interval; + + var src = cProp.colorValue; + var isHdr = (colorArray[i].GetPropertyFlags() & ShaderPropertyFlags.HDR) != ShaderPropertyFlags.None; + var dst = EditorGUI.ColorField(r, GUIContent.none, src, true, true, isHdr); + if (Helper.EndChangeCheck(metaDatas, cProp)) + { + cProp.colorValue = dst; + } + } + + EditorGUI.showMixedValue = false; + } + } +} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ColorDrawer.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ColorDrawer.cs.meta new file mode 100644 index 000000000..93f43e8fa --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ExtraDrawers/Vector/ColorDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a05aca16f43d8d844840af6e1bb5468a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ShaderDrawerBase.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ShaderDrawerBase.cs new file mode 100644 index 000000000..0a46ba3f2 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ShaderDrawerBase.cs @@ -0,0 +1,40 @@ +// Copyright (c) Jason Ma + +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace LWGUI +{ + public interface IBaseDrawer + { + public void BuildStaticMetaData(Shader inShader, MaterialProperty inProp, MaterialProperty[] inProps, PropertyStaticData inoutPropertyStaticData) {} + + public void GetDefaultValueDescription(Shader inShader, MaterialProperty inProp, MaterialProperty inDefaultProp, PerShaderData inPerShaderData, PerMaterialData inoutPerMaterialData) {} + + public void GetCustomContextMenus(GenericMenu menu, Rect rect, MaterialProperty prop, LWGUIMetaDatas metaDatas) {} + } + + public interface IPresetDrawer + { + public string GetPresetFileName(); + + public LwguiShaderPropertyPreset.Preset GetActivePreset(MaterialProperty inProp, LwguiShaderPropertyPreset lwguiShaderPropertyPreset) => + lwguiShaderPropertyPreset?.TryGetPreset(inProp?.floatValue ?? -1); + } + + public partial class PropertyStaticData + { + // Image + public Texture2D image; + + // Button + public List buttonDisplayNames = new(); + public List buttonCommands = new(); + public List buttonDisplayNameWidths = new(); + + // You can add more data that is determined during the initialization of the Drawer as a cache here, + // thereby avoiding the need to calculate it every frame in OnGUI(). + // >>>>>>>>>>>>>>>>>>>>>>>> Add new data here <<<<<<<<<<<<<<<<<<<<<<< + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ShaderDrawerBase.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ShaderDrawerBase.cs.meta new file mode 100644 index 000000000..003ed5443 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/ShaderDrawers/ShaderDrawerBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 188168c425384e21a48826d921aedfd5 +timeCreated: 1769324944 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/LWGUI.Timeline.Editor.asmdef b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/LWGUI.Timeline.Editor.asmdef index d1d74c9eb..73b0e2157 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/LWGUI.Timeline.Editor.asmdef +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/LWGUI.Timeline.Editor.asmdef @@ -6,7 +6,9 @@ "LWGUI.Timeline", "LWGUI.Runtime.Timeline", "Unity.Timeline", - "Unity.Timeline.Editor" + "Unity.Timeline.Editor", + "LWGUI.Runtime", + "Unity.InternalAPIEditorBridge.020" ], "includePlatforms": [ "Editor" diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/MaterialKeywordToggleTrackEditor.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/MaterialKeywordToggleTrackEditor.cs index 003effb39..f62d4b34f 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/MaterialKeywordToggleTrackEditor.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/Editor/MaterialKeywordToggleTrackEditor.cs @@ -23,11 +23,7 @@ namespace LWGUI.Timeline return; var targetToggleTrack = track as MaterialKeywordToggleTrack; - if (targetToggleTrack == null - || targetToggleTrack.srcAnimationTrack == null - || targetToggleTrack.srcAnimationClip == null - || string.IsNullOrEmpty(targetToggleTrack.propName) - ) + if (targetToggleTrack == null || !targetToggleTrack.IsValid()) return; var directors = Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); @@ -38,12 +34,8 @@ namespace LWGUI.Timeline if (targetRenderer == null || rootAnimator == null) continue; - if (TimelineHelper.GetMaterialPropertyEditorCurveFromAnimationClip(targetRenderer, targetToggleTrack.propName, rootAnimator, targetToggleTrack.srcAnimationClip, - out var srcAnimationCurve)) - { - TimelineHelper.CopyAnimationCurveToMaterialKeywordToggleTrack(targetToggleTrack.srcAnimationTrack, srcAnimationCurve, targetToggleTrack); - break; - } + TimelineHelper.CopyAnimationCurveToMaterialKeywordToggleTrack(targetToggleTrack.srcAnimationTrack, targetToggleTrack.srcAnimationCurve, targetToggleTrack); + break; } } } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/TimelineHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/TimelineHelper.cs index d5873a435..1e262451a 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/TimelineHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Editor/Timeline/TimelineHelper.cs @@ -53,9 +53,11 @@ namespace LWGUI.Timeline GroupTrack baseGroupTrack = null; TimelineAsset targetTimelineAsset = null; AnimationTrack srcAnimationTrack = null; + AnimationClip srcAnimationClip = null; + AnimationCurve srcAnimationCurve = null; Animator rootAnimator = null; - // Find the existing track + // Find tracks foreach (var director in directors) { if (director == null || director.playableAsset == null) @@ -71,18 +73,28 @@ namespace LWGUI.Timeline foreach (var trackAsset in allTrackAssets) { - if (trackAsset is AnimationTrack animationTrack) + // Find Src Animation Track + if (srcAnimationCurve == null && trackAsset is AnimationTrack animationTrack && animationTrack.IsRecording()) { var bindedAnimator = director.GetGenericBinding(animationTrack); if (parentAnimators.Contains(bindedAnimator)) { - srcAnimationTrack = animationTrack; - targetDirector = director; - targetTimelineAsset = timelineAsset; - rootAnimator = bindedAnimator as Animator; + // Find the Animation Curve + var animationClip = animationTrack.infiniteClip ?? animationTrack.curves; + if (animationClip != null + && GetMaterialPropertyEditorCurveFromAnimationClip(renderer, prop.name, bindedAnimator as Animator, animationClip, + out srcAnimationCurve)) + { + srcAnimationTrack = animationTrack; + srcAnimationClip = animationClip; + targetDirector = director; + targetTimelineAsset = timelineAsset; + rootAnimator = bindedAnimator as Animator; + } } } + // Find Exist MaterialKeywordToggleTrack if (trackAsset is MaterialKeywordToggleTrack materialKeywordTrack && director.GetGenericBinding(materialKeywordTrack) == renderer && materialKeywordTrack.keywordName == keywordName) @@ -103,10 +115,11 @@ namespace LWGUI.Timeline Debug.Assert(targetDirector != null && targetTimelineAsset != null && srcAnimationTrack != null + && srcAnimationCurve != null && rootAnimator != null, $"LWGUI: Unable to find the existing Animation Track for MaterialProperty({ prop.name }) and Material({(editor.target as Material).name })!"); - // Create a track + // Create a MaterialKeywordToggleTrack if (targetToggleTrack == null) { if (baseGroupTrack == null) @@ -123,22 +136,16 @@ namespace LWGUI.Timeline } targetToggleTrack = targetTimelineAsset.CreateTrack(); - targetToggleTrack.keywordName = keywordName; - targetToggleTrack.propName = prop.name; - targetToggleTrack.srcAnimationTrack = srcAnimationTrack; targetToggleTrack.SetGroup(targetGroupTrack); targetDirector.SetGenericBinding(targetToggleTrack, renderer); } - // Find the Animation Curve - AnimationClip srcAnimationClip = srcAnimationTrack.infiniteClip ?? srcAnimationTrack.curves; - if (srcAnimationClip != null && GetMaterialPropertyEditorCurveFromAnimationClip(renderer, prop.name, rootAnimator, srcAnimationClip, - out var srcAnimationCurve)) - { - targetToggleTrack.srcAnimationClip = srcAnimationClip; - - CopyAnimationCurveToMaterialKeywordToggleTrack(srcAnimationTrack, srcAnimationCurve, targetToggleTrack); - } + // Set Target Track Config + targetToggleTrack.keywordName = keywordName; + targetToggleTrack.propName = prop.name; + targetToggleTrack.srcAnimationTrack = srcAnimationTrack; + targetToggleTrack.srcAnimationClip = srcAnimationClip; + targetToggleTrack.srcAnimationCurve = srcAnimationCurve; TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved | RefreshReason.ContentsModified); } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README.md b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README.md index d1f806312..7e99211f9 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README.md +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README.md @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4de9bed47fa972dfbc25b87dbcb14500a2bd0c2a85565d5a6d2b654eb90df230 -size 46185 +oid sha256:f237d859aa149fcce30a2040139ac0b76d6438474fd3bf938dc119fcf0098476 +size 63063 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.md b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.md index 5fc126c63..c8e5101d6 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.md +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/README_CN.md @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0ab14ca0bb64c565f5a5069a6e8ecf35726b90d8132edd95bb99395699a704c -size 44461 +oid sha256:870b922b71c1b1c7fd5775d556777a0800c25e53fd074a98237e23687a6a88dc +size 59327 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiGradient.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiGradient.cs index 51ac0f9b5..0498facb8 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiGradient.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiGradient.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using System; using System.Collections.Generic; @@ -50,8 +50,8 @@ namespace LWGUI.Runtime.LwguiGradient #region Const - public static readonly Color[] channelColors = new[] { Color.red, Color.green, Color.blue, Color.white }; - public static readonly char[] channelNames = new[] { 'r', 'g', 'b', 'a' }; + public static readonly Color[] channelColors = { Color.red, Color.green, Color.blue, Color.white }; + public static readonly char[] channelNames = { 'r', 'g', 'b', 'a' }; public static AnimationCurve defaultCurve => new (new Keyframe(0, 1).SetLinearTangentMode(), new Keyframe(1, 1).SetLinearTangentMode()); @@ -62,6 +62,11 @@ namespace LWGUI.Runtime.LwguiGradient // The complete data is stored by RGBA Curves and can be converted into Texture [SerializeField] private List _curves; + // Reusable buffer to reduce per-call allocations when generating preview pixels + [NonSerialized] private static Color[] _pixelsCache; + [NonSerialized] private static int _pixelsCacheWidth; + [NonSerialized] private static int _pixelsCacheHeight; + public List rawCurves { get @@ -154,50 +159,23 @@ namespace LWGUI.Runtime.LwguiGradient public LwguiGradient(List inRgbaCurves) => SetRgbaCurves(inRgbaCurves); - public static LwguiGradient white - { - get => new (); - } + public static LwguiGradient white => new (); - public static LwguiGradient gray - { - get => new (new []{Color.gray, Color.gray}, new []{0.0f, 1.0f}); - } + public static LwguiGradient gray => new (new []{Color.gray, Color.gray}, new []{0.0f, 1.0f}); - public static LwguiGradient black - { - get => new (new []{Color.black, Color.black}, new []{0.0f, 1.0f}); - } + public static LwguiGradient black => new (new []{Color.black, Color.black}, new []{0.0f, 1.0f}); - public static LwguiGradient red - { - get => new (new []{Color.red, Color.red}, new []{0.0f, 1.0f}); - } + public static LwguiGradient red => new (new []{Color.red, Color.red}, new []{0.0f, 1.0f}); - public static LwguiGradient green - { - get => new (new []{Color.green, Color.green}, new []{0.0f, 1.0f}); - } + public static LwguiGradient green => new (new []{Color.green, Color.green}, new []{0.0f, 1.0f}); - public static LwguiGradient blue - { - get => new (new []{Color.blue, Color.blue}, new []{0.0f, 1.0f}); - } + public static LwguiGradient blue => new (new []{Color.blue, Color.blue}, new []{0.0f, 1.0f}); - public static LwguiGradient cyan - { - get => new (new []{Color.cyan, Color.cyan}, new []{0.0f, 1.0f}); - } + public static LwguiGradient cyan => new (new []{Color.cyan, Color.cyan}, new []{0.0f, 1.0f}); - public static LwguiGradient magenta - { - get => new (new []{Color.magenta, Color.magenta}, new []{0.0f, 1.0f}); - } + public static LwguiGradient magenta => new (new []{Color.magenta, Color.magenta}, new []{0.0f, 1.0f}); - public static LwguiGradient yellow - { - get => new (new []{Color.yellow, Color.yellow}, new []{0.0f, 1.0f}); - } + public static LwguiGradient yellow => new (new []{Color.yellow, Color.yellow}, new []{0.0f, 1.0f}); #endregion @@ -207,8 +185,9 @@ namespace LWGUI.Runtime.LwguiGradient if (_curves != null) { - foreach (var curve in _curves) + for (int i = 0; i < _curves.Count; i++) { + var curve = _curves[i]; if (curve != null) { hash = hash * 23 + curve.GetHashCode(); @@ -222,6 +201,8 @@ namespace LWGUI.Runtime.LwguiGradient public void Dispose() { _curves?.Clear(); + _pixelsCache = null; + _pixelsCacheWidth = _pixelsCacheHeight = 0; } public void Clear(ChannelMask channelMask = ChannelMask.All) @@ -249,9 +230,10 @@ namespace LWGUI.Runtime.LwguiGradient for (int c = 0; c < src._curves.Count; c++) { - foreach (var key in src._curves[c].keys) + var keys = src._curves[c].keys; + for (int k = 0; k < keys.Length; k++) { - _curves[c].AddKey(key); + _curves[c].AddKey(keys[k]); } } } @@ -306,7 +288,13 @@ namespace LWGUI.Runtime.LwguiGradient public Color Evaluate(float time, ChannelMask channelMask = ChannelMask.All, GradientTimeRange timeRange = GradientTimeRange.One) { - time /= (int)timeRange; + switch (timeRange) + { + case GradientTimeRange.One: break; + case GradientTimeRange.TwentyFour: time *= 1.0f / 24.0f; break; + case GradientTimeRange.TwentyFourHundred: time *= 1.0f / 2400.0f; break; + default: throw new ArgumentOutOfRangeException(nameof(timeRange), timeRange, null); + } if (channelMask == ChannelMask.Alpha) { @@ -314,6 +302,24 @@ namespace LWGUI.Runtime.LwguiGradient return new Color(alpha, alpha, alpha, 1); } + // Fast paths to avoid redundant mask checks and alpha evaluation + if (channelMask == ChannelMask.All) + { + return new Color( + rawCurves[(int)Channel.Red].Evaluate(time), + rawCurves[(int)Channel.Green].Evaluate(time), + rawCurves[(int)Channel.Blue].Evaluate(time), + rawCurves[(int)Channel.Alpha].Evaluate(time)); + } + if (channelMask == ChannelMask.RGB) + { + return new Color( + rawCurves[(int)Channel.Red].Evaluate(time), + rawCurves[(int)Channel.Green].Evaluate(time), + rawCurves[(int)Channel.Blue].Evaluate(time), + 1); + } + return new Color( IsChannelIndexInMask((int)Channel.Red, channelMask) ? rawCurves[(int)Channel.Red].Evaluate(time) : 0, IsChannelIndexInMask((int)Channel.Green, channelMask) ? rawCurves[(int)Channel.Green].Evaluate(time) : 0, @@ -334,16 +340,7 @@ namespace LWGUI.Runtime.LwguiGradient public Color[] GetPixels(int width, int height, ChannelMask channelMask = ChannelMask.All) { var pixels = new Color[width * height]; - for (var x = 0; x < width; x++) - { - var u = x / (float)width; - var col = Evaluate(u, channelMask); - for (int i = 0; i < height; i++) - { - pixels[x + i * width] = col; - } - } - + FillPixelsNonAlloc(pixels, width, height, channelMask); return pixels; } @@ -352,9 +349,10 @@ namespace LWGUI.Runtime.LwguiGradient if (outputPixels == null || currentIndex >= outputPixels.Length) return; + var invWidth = 1.0f / width; for (var x = 0; x < width; x++) { - var u = x / (float)width; + var u = x * invWidth; var col = Evaluate(u, channelMask); for (int i = 0; i < height; i++) { @@ -364,14 +362,44 @@ namespace LWGUI.Runtime.LwguiGradient } } + // Non-alloc helper to fill a provided buffer with gradient pixels + private void FillPixelsNonAlloc(Color[] buffer, int width, int height, ChannelMask channelMask = ChannelMask.All) + { + if (buffer == null || buffer.Length < width * height) return; + var invWidth = 1.0f / width; + int rowStride = width; + for (int x = 0; x < width; x++) + { + var u = x * invWidth; + var col = Evaluate(u, channelMask); + int idx = x; + for (int y = 0; y < height; y++) + { + buffer[idx] = col; + idx += rowStride; + } + } + } + + private void EnsurePixelCache(int width, int height) + { + if (_pixelsCache == null || _pixelsCacheWidth != width || _pixelsCacheHeight != height) + { + _pixelsCache = new Color[width * height]; + _pixelsCacheWidth = width; + _pixelsCacheHeight = height; + } + } + public Texture2D GetPreviewRampTexture(int width = 256, int height = 1, ColorSpace colorSpace = ColorSpace.Gamma, ChannelMask channelMask = ChannelMask.All) { if (LwguiGradientHelper.TryGetRampPreview(this, width, height, colorSpace, channelMask, out var cachedPreview)) return cachedPreview; - var rampPreview = new Texture2D(width, height, TextureFormat.RGBA32, false, colorSpace == ColorSpace.Linear); - var pixels = GetPixels(width, height, channelMask); - rampPreview.SetPixels(pixels); + var rampPreview = new Texture2D(width, height, TextureFormat.RGBA32, false, colorSpace == ColorSpace.Linear); + EnsurePixelCache(width, height); + FillPixelsNonAlloc(_pixelsCache, width, height, channelMask); + rampPreview.SetPixels(_pixelsCache); rampPreview.wrapMode = TextureWrapMode.Clamp; rampPreview.name = "LWGUI Gradient Preview"; rampPreview.Apply(); @@ -398,129 +426,121 @@ namespace LWGUI.Runtime.LwguiGradient } } - public class LwguiMergedColorCurves : IDisposable - { - public List> curves = new (); - - public LwguiMergedColorCurves() - { - for (int c = 0; c < (int)Channel.Num; c++) - curves.Add(new List()); - } - - public LwguiMergedColorCurves(List rgbaCurves) - { - for (int c = 0; c < (int)Channel.Num; c++) - curves.Add(new List()); - - // Get color keys - { - var timeColorDic = new Dictionary>(); - for (int c = 0; c < (int)Channel.Num - 1; c++) - { - var keys = rgbaCurves[c].keys; - for (int j = 0; j < keys.Length; j++) - { - var keyframe = keys[j]; - if (timeColorDic.ContainsKey(keyframe.time)) - { - timeColorDic[keyframe.time].Add((keyframe.value, j)); - } - else - { - timeColorDic.Add(keyframe.time, new List<(float value, int index)> { (keyframe.value, j) }); - } - } - } - - foreach (var kwPair in timeColorDic) - { - if (kwPair.Value.Count == (int)Channel.Num - 1) - { - for (int c = 0; c < (int)Channel.Num - 1; c++) - { - curves[c].Add(new LwguiKeyframe(kwPair.Key, kwPair.Value[c].value, kwPair.Value[c].index)); - } - } - } - } - - // Get alpha keys - for (int i = 0; i < rgbaCurves[(int)Channel.Alpha].keys.Length; i++) - { - var alphaKey = rgbaCurves[(int)Channel.Alpha].keys[i]; - curves[(int)Channel.Alpha].Add(new LwguiKeyframe(alphaKey.time, alphaKey.value, i)); - } - } - - public LwguiMergedColorCurves(Gradient gradient) - { - for (int c = 0; c < (int)Channel.Num; c++) - curves.Add(new List()); - - foreach (var colorKey in gradient.colorKeys) - { - for (int c = 0; c < (int)Channel.Num - 1; c++) - { - curves[c].Add(new LwguiKeyframe(colorKey.time, colorKey.color[c], 0)); - } - } - foreach (var alphaKey in gradient.alphaKeys) - { - curves[(int)Channel.Alpha].Add(new LwguiKeyframe(alphaKey.time, alphaKey.alpha, 0)); - } - } - - public Gradient ToGradient(int maxGradientKeyCount = 8) => new Gradient - { - colorKeys = curves[(int)Channel.Red].Select((keyframe, i) => new GradientColorKey( - new Color( - curves[(int)Channel.Red][i].value, - curves[(int)Channel.Green][i].value, - curves[(int)Channel.Blue][i].value), - curves[(int)Channel.Red][i].time)) - .Where((key, i) => i < maxGradientKeyCount).ToArray(), - - alphaKeys = curves[(int)Channel.Alpha].Select(alphaKey => new GradientAlphaKey(alphaKey.value, alphaKey.time)) - .Where((key, i) => i < maxGradientKeyCount).ToArray() - }; - - public List ToAnimationCurves() - { - var outCurves = new List(); - for (int c = 0; c < (int)Channel.Num; c++) - { - var curve = new AnimationCurve(); - foreach (var key in curves[c]) - { - curve.AddKey(new Keyframe(key.time, key.value).SetLinearTangentMode()); - } - curve.SetLinearTangents(); - outCurves.Add(curve); - } - - return outCurves; - } - - public LwguiGradient ToLwguiGradient() - { - return new LwguiGradient(ToAnimationCurves()); - } - - public void Dispose() - { - curves?.Clear(); - } - } - public static LwguiGradient FromGradient(Gradient gradient) { - return new LwguiMergedColorCurves(gradient).ToLwguiGradient(); + if (gradient == null) + return new LwguiGradient(); + + var curves = new List((int)Channel.Num); + for (int c = 0; c < (int)Channel.Num; c++) + curves[c] = new AnimationCurve(); + + var colorKeys = gradient.colorKeys; + for (int i = 0; i < colorKeys.Length; i++) + { + var ck = colorKeys[i]; + curves[(int)Channel.Red] .AddKey(new Keyframe(ck.time, ck.color.r).SetLinearTangentMode()); + curves[(int)Channel.Green].AddKey(new Keyframe(ck.time, ck.color.g).SetLinearTangentMode()); + curves[(int)Channel.Blue] .AddKey(new Keyframe(ck.time, ck.color.b).SetLinearTangentMode()); + } + + var alphaKeys = gradient.alphaKeys; + for (int i = 0; i < alphaKeys.Length; i++) + { + var ak = alphaKeys[i]; + curves[(int)Channel.Alpha].AddKey(new Keyframe(ak.time, ak.alpha).SetLinearTangentMode()); + } + + for (int c = 0; c < (int)Channel.Num; c++) + curves[c].SetLinearTangents(); + + return new LwguiGradient(curves); } + /// Warning: This is a lossy conversion and will ignore keys that are not aligned with the RGB channels public Gradient ToGradient(int maxGradientKeyCount = 8) { - return new LwguiMergedColorCurves(rawCurves).ToGradient(maxGradientKeyCount); + if (rawCurves == null || rawCurves.Count < (int)Channel.Num) + { + return new Gradient(); + } + + var redKeys = rawCurves[(int)Channel.Red].keys; + var greenKeys = rawCurves[(int)Channel.Green].keys; + var blueKeys = rawCurves[(int)Channel.Blue].keys; + var alphaKeys = rawCurves[(int)Channel.Alpha].keys; + + int maxColorCount = Math.Max(Math.Max(redKeys.Length, greenKeys.Length), blueKeys.Length); + var timeColorDic = new Dictionary(maxColorCount); + + // R + for (int i = 0; i < redKeys.Length; i++) + { + float time = redKeys[i].time; + timeColorDic[time] = (redKeys[i].value, 0, 0, 1); + } + + // G + for (int i = 0; i < greenKeys.Length; i++) + { + float time = greenKeys[i].time; + if (timeColorDic.TryGetValue(time, out var existing)) + { + timeColorDic[time] = (existing.r, greenKeys[i].value, existing.b, existing.count + 1); + } + else + { + timeColorDic[time] = (0, greenKeys[i].value, 0, 1); + } + } + + // B + for (int i = 0; i < blueKeys.Length; i++) + { + float time = blueKeys[i].time; + if (timeColorDic.TryGetValue(time, out var existing)) + { + timeColorDic[time] = (existing.r, existing.g, blueKeys[i].value, existing.count + 1); + } + else + { + timeColorDic[time] = (0, 0, blueKeys[i].value, 1); + } + } + + // Collect aligned RGB channels + var validColorKeys = new List(timeColorDic.Count); + foreach (var kvp in timeColorDic) + { + if (kvp.Value.count == 3) + { + validColorKeys.Add(new GradientColorKey( + new Color(kvp.Value.r, kvp.Value.g, kvp.Value.b), + kvp.Key)); + } + } + + validColorKeys.Sort((a, b) => a.time.CompareTo(b.time)); + int colorKeyCount = Math.Min(validColorKeys.Count, maxGradientKeyCount); + var colorKeys = new GradientColorKey[colorKeyCount]; + for (int i = 0; i < colorKeyCount; i++) + { + colorKeys[i] = validColorKeys[i]; + } + + // A + int alphaKeyCount = Math.Min(alphaKeys.Length, maxGradientKeyCount); + var alphaKeysArray = new GradientAlphaKey[alphaKeyCount]; + for (int i = 0; i < alphaKeyCount; i++) + { + alphaKeysArray[i] = new GradientAlphaKey(alphaKeys[i].value, alphaKeys[i].time); + } + + return new Gradient + { + colorKeys = colorKeys, + alphaKeys = alphaKeysArray + }; } #endregion diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiMergedColorCurves.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiMergedColorCurves.cs new file mode 100644 index 000000000..75892f703 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiMergedColorCurves.cs @@ -0,0 +1,139 @@ +// Copyright (c) Jason Ma + +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace LWGUI.Runtime.LwguiGradient +{ + public class LwguiMergedColorCurves : IDisposable + { + public List> curves = new (); + + public LwguiMergedColorCurves() + { + for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) + curves.Add(new List()); + } + + public LwguiMergedColorCurves(List rgbaCurves) + { + for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) + curves.Add(new List()); + + // Get color keys + { + var timeColorDic = new Dictionary>(); + for (int c = 0; c < (int)LwguiGradient.Channel.Num - 1; c++) + { + var keys = rgbaCurves[c].keys; + for (int j = 0; j < keys.Length; j++) + { + var keyframe = keys[j]; + if (timeColorDic.ContainsKey(keyframe.time)) + { + timeColorDic[keyframe.time].Add((keyframe.value, j)); + } + else + { + timeColorDic.Add(keyframe.time, new List<(float value, int index)> { (keyframe.value, j) }); + } + } + } + + foreach (var kwPair in timeColorDic) + { + if (kwPair.Value.Count == (int)LwguiGradient.Channel.Num - 1) + { + for (int c = 0; c < (int)LwguiGradient.Channel.Num - 1; c++) + { + curves[c].Add(new LwguiGradient.LwguiKeyframe(kwPair.Key, kwPair.Value[c].value, kwPair.Value[c].index)); + } + } + } + } + + // Get alpha keys + for (int i = 0; i < rgbaCurves[(int)LwguiGradient.Channel.Alpha].keys.Length; i++) + { + var alphaKey = rgbaCurves[(int)LwguiGradient.Channel.Alpha].keys[i]; + curves[(int)LwguiGradient.Channel.Alpha].Add(new LwguiGradient.LwguiKeyframe(alphaKey.time, alphaKey.value, i)); + } + } + + public LwguiMergedColorCurves(Gradient gradient) + { + for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) + curves.Add(new List()); + + foreach (var colorKey in gradient.colorKeys) + { + for (int c = 0; c < (int)LwguiGradient.Channel.Num - 1; c++) + { + curves[c].Add(new LwguiGradient.LwguiKeyframe(colorKey.time, colorKey.color[c], 0)); + } + } + foreach (var alphaKey in gradient.alphaKeys) + { + curves[(int)LwguiGradient.Channel.Alpha].Add(new LwguiGradient.LwguiKeyframe(alphaKey.time, alphaKey.alpha, 0)); + } + } + + public Gradient ToGradient(int maxGradientKeyCount = 8) + { + var rKeys = curves[(int)LwguiGradient.Channel.Red]; + var gKeys = curves[(int)LwguiGradient.Channel.Green]; + var bKeys = curves[(int)LwguiGradient.Channel.Blue]; + var aKeys = curves[(int)LwguiGradient.Channel.Alpha]; + + var colorCount = Math.Min(Math.Min(rKeys.Count, Math.Min(gKeys.Count, bKeys.Count)), maxGradientKeyCount); + var alphaCount = Math.Min(aKeys.Count, maxGradientKeyCount); + + var colorKeys = new GradientColorKey[colorCount]; + for (int i = 0; i < colorCount; i++) + { + colorKeys[i] = new GradientColorKey(new Color(rKeys[i].value, gKeys[i].value, bKeys[i].value), rKeys[i].time); + } + + var alphaKeys = new GradientAlphaKey[alphaCount]; + for (int i = 0; i < alphaCount; i++) + { + alphaKeys[i] = new GradientAlphaKey(aKeys[i].value, aKeys[i].time); + } + + var gradient = new Gradient + { + colorKeys = colorKeys, + alphaKeys = alphaKeys + }; + return gradient; + } + + public List ToAnimationCurves() + { + var outCurves = new List(); + for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) + { + var curve = new AnimationCurve(); + foreach (var key in curves[c]) + { + curve.AddKey(new Keyframe(key.time, key.value).SetLinearTangentMode()); + } + curve.SetLinearTangents(); + outCurves.Add(curve); + } + + return outCurves; + } + + public LwguiGradient ToLwguiGradient() + { + return new LwguiGradient(ToAnimationCurves()); + } + + public void Dispose() + { + curves?.Clear(); + } + } +} \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiMergedColorCurves.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiMergedColorCurves.cs.meta new file mode 100644 index 000000000..8aa474e26 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/LwguiGradient/LwguiMergedColorCurves.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b3c8699fbeb046d188d2a6b5984c96a9 +timeCreated: 1765706773 \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/RuntimeHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/RuntimeHelper.cs index e5d6b79e3..7049983d5 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/RuntimeHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/RuntimeHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma namespace LWGUI.Runtime { diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/Timeline/MaterialKeywordToggle/MaterialKeywordToggleTrack.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/Timeline/MaterialKeywordToggle/MaterialKeywordToggleTrack.cs index 1124ae2d6..7d0a3c07c 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/Timeline/MaterialKeywordToggle/MaterialKeywordToggleTrack.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Runtime/Timeline/MaterialKeywordToggle/MaterialKeywordToggleTrack.cs @@ -19,10 +19,11 @@ namespace LWGUI.Runtime.Timeline [TrackBindingType(typeof(Renderer))] public class MaterialKeywordToggleTrack : TrackAsset { - public string keywordName; - public string propName; + public string keywordName; + public string propName; public AnimationTrack srcAnimationTrack = null; - public AnimationClip srcAnimationClip = null; + public AnimationClip srcAnimationClip = null; + public AnimationCurve srcAnimationCurve = null; // Creates a runtime instance of the track, represented by a PlayableBehaviour. // The runtime instance performs mixing on the timeline clips. @@ -42,6 +43,17 @@ namespace LWGUI.Runtime.Timeline return ScriptPlayable.Create(graph, template, inputCount); } + + public bool IsValid() + { + return keywordName != "_" + && !string.IsNullOrWhiteSpace(keywordName) + && !string.IsNullOrWhiteSpace(propName) + && srcAnimationTrack != null + && srcAnimationClip != null + && srcAnimationCurve != null + ; + } } } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_KeywordTest.mat b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_KeywordTest.mat index 274ce9d28..ff59508a9 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_KeywordTest.mat +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_KeywordTest.mat @@ -13,7 +13,7 @@ Material: m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _KEYWORDENUM_KEY2 - - _KWENUM_KEY2 + - _KWENUM_KEY1 - _SUBKEYWORDENUM_KEY1 m_InvalidKeywords: [] m_LightmapFlags: 4 @@ -33,7 +33,7 @@ Material: - _group: 1 - _group_toggle1: 0 - _keywordEnum: 1 - - _kwenum: 1 + - _kwenum: 0 - _preset2: 0 - _subEnum: 1 - _subKeywordEnum: 0 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_BlendMode.asset b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_BlendMode.asset index 755c94835..e9b9dce67 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_BlendMode.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_BlendMode.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5eb524c626557a7c6c6cf679fb5cdb2ad45991129f20c949c3c29662f8d4ad8 -size 1799 +oid sha256:3dcd34e294f111bc272fb0417bf6a74c3fb103d2985c78c5cdaee441a5a9da1e +size 1860 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset index d6fbf8132..7a180f435 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_Preset_Toggle.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:697432701ec45f2e63788bcb2474e2c11d6b60e7175393b6b3fe020f190abe0d -size 744 +oid sha256:fa1bfa672ccff5cc878509b352c6ebbec599a72539e759476d392e3f4b0d3fab +size 773 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.asset b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.asset index 5041dce52..59e2e96a1 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c5e5859675e5c3c28d332a1910fa30f7b2252e734895d727bde1a0524db8db5 -size 522 +oid sha256:3ba4c1eb19eba631d6124db4f337fb43bc62b8aeb46881558400f157b0a7d911 +size 6361 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga index f3b7bb045..09571d7d2 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba5e63ab21eeb215e1861afb16758b71a8ddfaa0f0bb9cd30c503babaaf56fc0 -size 8210 +oid sha256:36f9d02c349287f8720516013dd56df8f5676f782a4f0ffc43bb1ea918c6369f +size 4114 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga.meta index 33892f261..097e5c27c 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_RampAtlas.tga.meta @@ -3,7 +3,7 @@ guid: cfbe5a628e96c0d4bae3645ad922a368 TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 12 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 @@ -122,9 +122,6 @@ TextureImporter: nameFileIdTable: {} mipmapLimitGroupName: pSDRemoveMatte: 0 - userData: '{"MonoBehaviour":{"m_Enabled":true,"m_EditorHideFlags":0,"m_Name":"LWGUI_RampAtlas","m_EditorClassIdentifier":"","rampAtlasWidth":256,"rampAtlasHeight":8,"rampAtlasSRGB":true,"_ramps":[{"name":"Default - Ramp","gradient":{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]},"colorSpace":0,"channelMask":15,"timeRange":1},{"name":"Default - Ramp","gradient":{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":-0.00004999999873689376,"value":0.0,"inSlope":0.0,"outSlope":0.9999500513076782,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.9999500513076782,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":-0.00004999999873689376,"value":0.9492826461791992,"inSlope":0.0,"outSlope":0.05071482062339783,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.05071482062339783,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":-0.00004999999873689376,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]},"colorSpace":0,"channelMask":15,"timeRange":1},{"name":"New - Ramp","gradient":{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]},"colorSpace":0,"channelMask":-1,"timeRange":1},{"name":"Green","gradient":{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]},"colorSpace":1,"channelMask":10,"timeRange":24}],"_saveTextureToggle":false}}' + userData: '{"MonoBehaviour":{"m_Enabled":true,"m_EditorHideFlags":0,"m_Name":"LWGUI_RampAtlas","m_EditorClassIdentifier":"","rampAtlasWidth":256,"rampAtlasHeight":4,"rampAtlasSRGB":true,"_saveTextureToggle":false,"_ramps":[{"name":"0","colorSpace":1,"channelMask":-1,"timeRange":1,"gradient":{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.5,"value":0.0,"inSlope":0.0,"outSlope":2.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":2.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.5,"value":0.0,"inSlope":0.0,"outSlope":2.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":2.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.5,"value":0.0,"inSlope":0.0,"outSlope":2.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":2.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.5,"value":0.0,"inSlope":0.0,"outSlope":2.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":2.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}},{"name":"1","colorSpace":1,"channelMask":-1,"timeRange":1,"gradient":{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":1.8975205421447755,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":0.40370455384254458,"value":0.7660377025604248,"inSlope":1.8975205421447755,"outSlope":0.3923596739768982,"tangentMode":69,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":0.3923596739768982,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":0.5978978872299194,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":0.40370455384254458,"value":0.24137410521507264,"inSlope":0.5978978872299194,"outSlope":1.2722314596176148,"tangentMode":69,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.2722314596176148,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":0.5978978872299194,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":0.40370455384254458,"value":0.24137410521507264,"inSlope":0.5978978872299194,"outSlope":1.2722314596176148,"tangentMode":69,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":1.2722314596176148,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.0,"value":0.0,"inSlope":0.0,"outSlope":0.1829485297203064,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0},{"serializedVersion":"3","time":0.5503421425819397,"value":0.1006842851638794,"inSlope":0.1829485297203064,"outSlope":2.0,"tangentMode":69,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":1.0,"value":1.0,"inSlope":2.0,"outSlope":0.0,"tangentMode":69,"weightedMode":0,"inWeight":0.0,"outWeight":0.0}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}}]}}' assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA.mat b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA.mat index 40118c359..814c72e2d 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA.mat +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA.mat @@ -35,11 +35,11 @@ Material: m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _Ramp2: - m_Texture: {fileID: 2800000, guid: fad186cbfd0faf2488e2edb774c6d08f, type: 3} + m_Texture: {fileID: 2800000, guid: a5406a04c724bbc4296e1588506e80a2, type: 3} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _RampAtlas: - m_Texture: {fileID: 2800000, guid: a515311e7e4a4694191895bf48c01468, type: 3} + m_Texture: {fileID: 2800000, guid: cfbe5a628e96c0d4bae3645ad922a368, type: 3} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _normal: @@ -61,10 +61,12 @@ Material: - _PresetGroup: 0 - _Queue: 2000 - _RampAtlasIndex0: 0 - - _RampAtlasIndex1: 2 - - _RampAtlasIndex2: 3 + - _RampAtlasIndex1: 1 + - _RampAtlasIndex2: 1 - _RampAtlasIndexer: 0 - _SrcBlend: 5 + - _Stencil: 0 + - _StencilWithDescription: 0 - _ZTest: 4 - _ZWrite: 0 - _blendMode: 1 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA1.mat b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA1.mat index c65066fc7..4bc55988a 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA1.mat +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_SampleDrawerA1.mat @@ -39,7 +39,7 @@ Material: m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _RampAtlas: - m_Texture: {fileID: 2800000, guid: 5d501ab9fed726e4baa7d838819327e9, type: 3} + m_Texture: {fileID: 2800000, guid: cfbe5a628e96c0d4bae3645ad922a368, type: 3} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _normal: @@ -61,9 +61,12 @@ Material: - _PresetGroup: 0 - _Queue: 2000 - _RampAtlasIndex0: 0 - - _RampAtlasIndex1: 2 + - _RampAtlasIndex1: 1 + - _RampAtlasIndex2: 3 - _RampAtlasIndexer: 0 - _SrcBlend: 5 + - _Stencil: 0 + - _StencilWithDescription: 0 - _ZTest: 4 - _ZWrite: 0 - _blendMode: 1 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset1.asset b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset1.asset index e61993612..cf0fa3df4 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset1.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset1.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23bfcf4bea7ac5799c9fc379dc9aafb6e5950daa91e200a5b6013622ba0fe313 -size 713 +oid sha256:f31dae1e17736894e9d53c20741098cc71f20a325c2f3aff8de4d0c2be637f7f +size 738 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset2.asset b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset2.asset index bda6dcbcd..a0ed20cac 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset2.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset2.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2bfa47ab3f2df575732f42275a8efb57a0f423160dfb49d6c93105794aecccb7 -size 1097 +oid sha256:14cf8e033f2ace8d36da9e043555c1dec52764fdf127091ded677f3758178dd3 +size 1134 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset_Keywords.asset b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset_Keywords.asset new file mode 100644 index 000000000..a54dd324f --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset_Keywords.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16675409ba99b2e457a43291c919e3f76ae88c4c3090fbc9e074554273a918cd +size 834 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset_Keywords.asset.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset_Keywords.asset.meta new file mode 100644 index 000000000..29070514a --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/LWGUI_ShaderPropertyPreset_Keywords.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b7e21c9b67507684e8080d56f964afbe +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png index 9ae93a06c..2f4643c68 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64d9d1133d796d2bae48b0d7ce69a57fc47fbc54dcf9ebf339ebdd99c4b20532 -size 312 +oid sha256:cdc5bd3827c481fa840a79150e9f95473f0e913c276f51b3d831843c7f244dcd +size 314 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png.meta b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png.meta index 9e8f6d761..b02ee7089 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png.meta +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/RampMap_sRGB.png.meta @@ -3,7 +3,7 @@ guid: fad186cbfd0faf2488e2edb774c6d08f TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 12 + serializedVersion: 13 mipmaps: mipMapMode: 0 enableMipMap: 0 @@ -122,6 +122,6 @@ TextureImporter: nameFileIdTable: {} mipmapLimitGroupName: pSDRemoveMatte: 0 - userData: '{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3519061505794525,"value":0.9137465953826904,"inSlope":-1.1610162258148194,"outSlope":-1.1610162258148194,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.4040227234363556,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.711692214012146,"inSlope":1.9705389738082886,"outSlope":1.9705389738082886,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3519061505794525,"value":0.740675151348114,"inSlope":-0.3736116290092468,"outSlope":-0.3736116290092468,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7129190564155579,"inSlope":-0.38241732120513918,"outSlope":-0.38241732120513918,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.46618008613586428,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3519061505794525,"value":0.24506132304668427,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7358490228652954,"inSlope":1.559748649597168,"outSlope":1.559748649597168,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.849056601524353,"inSlope":0.8733886480331421,"outSlope":0.8733886480331421,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.20000000298023225,"value":0.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3499511182308197,"value":0.13333334028720857,"inSlope":1.2060123682022095,"outSlope":1.2060123682022095,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}#{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3519061505794525,"value":0.9137465953826904,"inSlope":-1.1610162258148194,"outSlope":-1.1610162258148194,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.4040227234363556,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.711692214012146,"inSlope":1.9705389738082886,"outSlope":1.9705389738082886,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3519061505794525,"value":0.740675151348114,"inSlope":-0.3736116290092468,"outSlope":-0.3736116290092468,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7129190564155579,"inSlope":-0.38241732120513918,"outSlope":-0.38241732120513918,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.46618008613586428,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3519061505794525,"value":0.24506132304668427,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7358490228652954,"inSlope":1.559748649597168,"outSlope":1.559748649597168,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.849056601524353,"inSlope":0.8733886480331421,"outSlope":0.8733886480331421,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.20000000298023225,"value":0.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3499511182308197,"value":0.13333334028720857,"inSlope":1.2060123682022095,"outSlope":1.2060123682022095,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}' + userData: '{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.34017595648765566,"value":0.9137465953826904,"inSlope":-1.1610162258148194,"outSlope":-1.1610162258148194,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.4040227234363556,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.711692214012146,"inSlope":1.9705389738082886,"outSlope":1.9705389738082886,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.34017595648765566,"value":0.740675151348114,"inSlope":-0.3736116290092468,"outSlope":-0.3736116290092468,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7129190564155579,"inSlope":-0.36756616830825808,"outSlope":-0.36756616830825808,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.46618008613586428,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.34017595648765566,"value":0.24506132304668427,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7358490228652954,"inSlope":1.499176025390625,"outSlope":1.499176025390625,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.849056601524353,"inSlope":0.8733886480331421,"outSlope":0.8733886480331421,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.20000000298023225,"value":0.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3499511182308197,"value":0.13333334028720857,"inSlope":1.2060123682022095,"outSlope":1.2060123682022095,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}#{"_curves":[{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.34017595648765566,"value":0.9137465953826904,"inSlope":-1.1610162258148194,"outSlope":-1.1610162258148194,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.4040227234363556,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.711692214012146,"inSlope":1.9705389738082886,"outSlope":1.9705389738082886,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.34017595648765566,"value":0.740675151348114,"inSlope":-0.3736116290092468,"outSlope":-0.3736116290092468,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7129190564155579,"inSlope":-0.36756616830825808,"outSlope":-0.36756616830825808,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.46618008613586428,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.2003910094499588,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.34017595648765566,"value":0.24506132304668427,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.497556209564209,"value":0.7358490228652954,"inSlope":1.499176025390625,"outSlope":1.499176025390625,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":0.849056601524353,"inSlope":0.8733886480331421,"outSlope":0.8733886480331421,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4},{"serializedVersion":"2","m_Curve":[{"serializedVersion":"3","time":0.20000000298023225,"value":0.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.3499511182308197,"value":0.13333334028720857,"inSlope":1.2060123682022095,"outSlope":1.2060123682022095,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.6422287225723267,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408},{"serializedVersion":"3","time":0.800000011920929,"value":1.0,"inSlope":0.0,"outSlope":0.0,"tangentMode":136,"weightedMode":0,"inWeight":0.3333333432674408,"outWeight":0.3333333432674408}],"m_PreInfinity":2,"m_PostInfinity":2,"m_RotationOrder":4}]}' assetBundleName: assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerA.shader b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerA.shader index 1b93dddc2..dbc15de00 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerA.shader +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerA.shader @@ -60,8 +60,8 @@ [SubToggle(Preset)] _ZWrite ("ZWrite ", Float) = 1 [SubEnum(Preset, UnityEngine.Rendering.CompareFunction)] _ZTest ("ZTest", Float) = 4 // 4 is LEqual [SubEnum(Preset, RGBA, 15, RGB, 14)] _ColorMask ("ColorMask", Float) = 15 // 15 is RGBA (binary 1111) - [BitMask(Preset)] _Stencil ("Stencil", Integer) = 0 - [BitMask(Preset, Left, Bit6, Bit5, Bit4, Description, Bit2, Bit1, Right)] _StencilWithDescription ("Stencil With Description", Integer) = 0 + [BitMask(Preset)] _Stencil ("Stencil", Int) = 0 + [BitMask(Preset, Left, Bit6, Bit5, Bit4, Description, Bit2, Bit1, Right)] _StencilWithDescription ("Stencil With Description", Int) = 0 } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerB.shader b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerB.shader index d618b5910..059ae0c34 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerB.shader +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleDrawerB.shader @@ -18,12 +18,12 @@ [Sub(Group1)] [HDR] _color1 ("Sub HDR Color", color) = (0.7, 0.7, 1, 1) [SubTitle(Group1, Conditional Display Samples Enum)] - [KWEnum(Group1, Name 1, _KEY1, Name 2, _KEY2, Name 3, _KEY3)] _enum ("KWEnum", float) = 0 - [Sub(Group1)][ShowIf(_enum, Equal, 0)] _key1_Float1 ("Key1 Float", float) = 0 - [Sub(Group1)][ShowIf(_enum, Equal, 1)] _key2_Float2 ("Key2 Float", float) = 0 - [SubIntRange(Group1)][ShowIf(_enum, Equal, 2)] _key3_Int_Range ("Key3 Int Range", Range(0, 10)) = 0 - [ShowIf(_enum, Equal, 0)][ShowIf(Or, _enum, Equal, 2)] - [SubPowerSlider(Group1, 3)] _key13_PowerSlider ("Key1 or Key3 Power Slider", Range(0, 1)) = 0 + [KWEnum(Group1, Keyword 1, _Keyword1, Keyword 2, _Keyword2, Keyword 3, _Keyword3)] _enum ("KWEnum", float) = 0 + [ShowIf(_enum, Equal, 0)][Sub(Group1)] _Keyword1_Float1 ("Show If Keyword1", float) = 0 + [ShowIf(_enum, Equal, 1)][Sub(Group1)] _Keyword2_Float2 ("Show If Keyword2", float) = 0 + [ShowIf(_enum, Equal, 2)][SubIntRange(Group1)] _Keyword3_Int_Range ("Show If Keyword3", Range(0, 10)) = 0 + [ShowIf(_enum, Equal, 0)][ShowIf(Or, _enum, Equal, 2)][SubPowerSlider(Group1, 3)] _Keyword13_PowerSlider ("Show If Keyword 1 or 3", Range(0, 1)) = 0 + [ActiveIf(_enum, E, 1)][Sub(Group1)] _Keyword1_Float2 ("Active If Keyword2", float) = 0 [Main(Group2, _, off, off)] _group2 ("Group - Without Toggle", float) = 0 @@ -37,7 +37,7 @@ [Advanced][Tex(Group2, _AdvancedColor0)] _AdvancedTex1 ("Advanced Tex 1", 2D) = "white" { } [Advanced][HideInInspector] _AdvancedColor0 ("Advanced Color 0", Color) = (1, 1, 1, 1) [AdvancedHeaderProperty][Sub(Group2)] _AdvancedFloat ("Advanced Image", float) = 0 - [Advanced][Image(Group2)] _AdvancedImage ("../image-20220828003810353.png", float) = 0 + [Advanced][Image(Group2)] _AdvancedImage ("../assets~/809c4a1c-ce80-48b1-b415-7e8d4bea716e-16616214059841.png", float) = 0 [Title(Channel Samples)] [Channel] _textureChannelMask ("Texture Channel Mask (Default G)", Vector) = (0, 1, 0, 0) diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleKeyword.shader b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleKeyword.shader index e1cf7bbf7..ce30e9a27 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleKeyword.shader +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/Test/SampleKeyword.shader @@ -11,29 +11,27 @@ Shader "Hidden" _kwenum ("KWEnum", float) = 0 [Toggle(_TOGGLE_KEYWORD)] _toggle1 ("Toggle", float) = 0 + + [SubPowerSlider(_, 1, LWGUI_ShaderPropertyPreset_Keywords)] _subPowerSlider ("SubPowerSlider with Preset", Range(0, 1)) = 0 [Main(g0, _GROUP_TOGGLE_KEYWORD)] _group_toggle1 ("Group Toggle", float) = 0 - [Main(g1, _, on, on)] - [PassSwitch(Always)] - _group ("Pass Switch Group", float) = 1 - [SubEnum(g1, Off, 0, On, 1)] _ZWrite ("ZWrite Mode", Float) = 1 - [SubToggle(g1, _SUBTOGGLE_KEYWORD)] _toggle ("Sub Toggle", float) = 0 - [SubKeywordEnum(g1, key1, key2)] + [SubEnum(g0, Off, 0, On, 1)] _ZWrite ("ZWrite Mode", Float) = 1 + [SubToggle(g0, _SUBTOGGLE_KEYWORD)] _toggle ("Sub Toggle", float) = 0 + [SubKeywordEnum(g0, key1, key2)] _subKeywordEnum ("SubKeywordEnum", float) = 0 } SubShader { - Pass { - Tags { "RenderType" = "Opaque" "LightMode" = "Always" } - LOD 100 + Tags { "RenderType" = "Opaque" } + CGPROGRAM #pragma vertex vert #pragma fragment frag - // make fog work - #pragma multi_compile_fog + #pragma multi_compile_fog + #pragma multi_compile _KWENUM_KEY1 _KWENUM_KEY2 #pragma multi_compile _KEYWORDENUM_KEY1 _KEYWORDENUM_KEY2 #pragma multi_compile _SUBKEYWORDENUM_KEY1 _SUBKEYWORDENUM_KEY2 @@ -71,7 +69,8 @@ Shader "Hidden" fixed4 frag(v2f i) : SV_Target { - fixed4 col = 0; + fixed4 col = 1; + col.a = 1; #if _KWENUM_KEY1 col.x += 0; @@ -98,13 +97,14 @@ Shader "Hidden" #if _TOGGLE_KEYWORD col.z += 0.25; #endif - + #if _GROUP_TOGGLE_KEYWORD col.z += 0.25; #endif + + col.rgb = frac(col.rgb); - - return frac(col); + return col; } ENDCG } diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientDrawer.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientDrawer.cs index 28ff550ee..b4bd801e1 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientDrawer.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientDrawer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using System; using UnityEngine; diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditor.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditor.cs index a3bcce800..1572fedb3 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditor.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditor.cs @@ -20,7 +20,7 @@ namespace LWGUI.LwguiGradientEditor public float selectedKeysAverageTime = 0; public uint selectedChannel = 0; public bool isOnlyColorKeySelected; - public LwguiGradient.LwguiMergedColorCurves mergedCurves; + public LwguiMergedColorCurves mergedCurves; public bool hasMixedTime; public bool hasMixedFloatValue; // Selected multiple keys with different values in a same Curve @@ -69,7 +69,7 @@ namespace LWGUI.LwguiGradientEditor if (selectedFloatValue == float.NegativeInfinity) selectedFloatValue = 0; - mergedCurves = new LwguiGradient.LwguiMergedColorCurves(selectedAnimationCurves); + mergedCurves = new LwguiMergedColorCurves(selectedAnimationCurves); var noAlphaKeySelected = mergedCurves.curves[(int)LwguiGradient.Channel.Alpha].Count == 0; hasMixedColorValue = noAlphaKeySelected && hasMixedChannelValue. Where((_, c) => c < (int)LwguiGradient.Channel.Alpha).Any(b => b); @@ -77,7 +77,7 @@ namespace LWGUI.LwguiGradientEditor } else { - mergedCurves = new LwguiGradient.LwguiMergedColorCurves(); + mergedCurves = new LwguiMergedColorCurves(); } } @@ -201,7 +201,7 @@ namespace LWGUI.LwguiGradientEditor var lastSelectedGradientKey = _gradientEditor != null && _selectedGradientKey != null ? new GradientEditor.Swatch(_selectedGradientKey.m_Time, _selectedGradientKey.m_Value, _selectedGradientKey.m_IsAlpha) : null; - var lwguiMergedCurves = new LwguiGradient.LwguiMergedColorCurves(lwguiGradient.rawCurves); + var lwguiMergedCurves = new LwguiMergedColorCurves(lwguiGradient.rawCurves); _gradientEditor ??= new GradientEditor(); _gradientEditor.Init(lwguiMergedCurves.ToGradient(ReflectionHelper.maxGradientKeyCount), 1024, colorSpace == ColorSpace.Linear, colorSpace); @@ -754,7 +754,7 @@ namespace LWGUI.LwguiGradientEditor // Get curve key index _curveEditor.SelectNone(); - var lwguiMergedCurves = new LwguiGradient.LwguiMergedColorCurves(lwguiGradient.rawCurves); + var lwguiMergedCurves = new LwguiMergedColorCurves(lwguiGradient.rawCurves); for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++) { if (selectedGradientKeyIndexes[c] < 0) diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditorHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditorHelper.cs index 0989b40be..47fa8e1e2 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditorHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditorHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using System; using System.Collections.Generic; @@ -11,6 +11,7 @@ namespace LWGUI.LwguiGradientEditor public static class LwguiGradientEditorHelper { private static readonly int s_LwguiGradientHash = "s_LwguiGradientHash".GetHashCode(); + private static readonly int s_LwguiGradientPreviewHash = "s_LwguiGradientPreviewHash".GetHashCode(); private static int s_LwguiGradientID; // GradientEditor.DrawGradientWithBackground() @@ -154,6 +155,57 @@ namespace LWGUI.LwguiGradientEditor } EditorGUI.EndProperty(); } + + /// + /// Draw a clickable gradient preview that opens the gradient editor when clicked. + /// This method handles change detection and Undo/Redo like GradientEditButton. + /// + public static bool GradientPreviewField(Rect rect, LwguiGradient gradient, + ColorSpace colorSpace, + LwguiGradient.ChannelMask viewChannelMask, + LwguiGradient.GradientTimeRange timeRange, + LwguiGradientWindow.ChangeGradientCallback onChange = null) + { + int id = GUIUtility.GetControlID(s_LwguiGradientPreviewHash, FocusType.Keyboard, rect); + var evt = Event.current; + + // When drawing the modifying Gradient Field and it has changed + if ((GUIUtility.keyboardControl == id || s_LwguiGradientID == id) + && evt.GetTypeForControl(id) == EventType.ExecuteCommand + && evt.commandName == LwguiGradientWindow.LwguiGradientChangedCommand) + { + GUI.changed = true; + HandleUtility.Repaint(); + } + + // Sync Undo/Redo result to editor window + if (s_LwguiGradientID == id + && evt.commandName == "UndoRedoPerformed") + { + LwguiGradientWindow.UpdateCurrentGradient(gradient); + } + + // Draw gradient preview + if (evt.type == EventType.Repaint) + { + DrawGradientWithSeparateAlphaChannel(rect, gradient, colorSpace, viewChannelMask); + } + + // Handle click to open editor + bool clicked = false; + if (evt.type == EventType.MouseDown && evt.button == 0 && rect.Contains(evt.mousePosition)) + { + clicked = true; + evt.Use(); + + s_LwguiGradientID = id; + GUIUtility.keyboardControl = id; + LwguiGradientWindow.Show(gradient, colorSpace, viewChannelMask, timeRange, GUIView.current, onChange); + GUIUtility.ExitGUI(); + } + + return clicked; + } public static bool GradientEditButton(Rect position, GUIContent icon, LwguiGradient gradient, ColorSpace colorSpace = ColorSpace.Gamma, diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md index f57ec9496..20d7c972f 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/README.md @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88860e5608ea81fdf6fc157eab86b84dce83707188b99d0eafc1a427f174f4fa -size 2713 +oid sha256:32e30a180073a4e9b31d222a0bdcfd7fe51fb9571b2152c1236a3029b42a986c +size 2748 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/ReflectionHelper.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/ReflectionHelper.cs index b6e1cb110..9d949d539 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/ReflectionHelper.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/ReflectionHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) Jason Ma +// Copyright (c) Jason Ma using System; using System.Collections.Generic; @@ -269,5 +269,57 @@ namespace LWGUI } #endregion + + + #region Type Lookup + + private static Dictionary _typeCache = new Dictionary(); + + /// + /// Get a Type by its name, searching all loaded assemblies. + /// Supports both full type name (Namespace.ClassName) and simple type name. + /// + public static Type GetTypeByName(string typeName) + { + if (string.IsNullOrEmpty(typeName)) + return null; + + if (_typeCache.TryGetValue(typeName, out var cachedType)) + return cachedType; + + // Try to get type directly + var type = Type.GetType(typeName); + if (type != null) + { + _typeCache[typeName] = type; + return type; + } + + // Search in all loaded assemblies + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + type = assembly.GetType(typeName); + if (type != null) + { + _typeCache[typeName] = type; + return type; + } + + // Try to find by simple name (without namespace) + foreach (var t in assembly.GetTypes()) + { + if (t.Name == typeName || t.FullName == typeName) + { + _typeCache[typeName] = t; + return t; + } + } + } + + _typeCache[typeName] = null; + return null; + } + + #endregion } } \ No newline at end of file diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/UnityEditorExtension.cs b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/UnityEditorExtension.cs index 773a3b4d0..b7b9c7545 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/UnityEditorExtension.cs +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/UnityEditorExtension/UnityEditorExtension.cs @@ -19,7 +19,8 @@ namespace LWGUI ApplyMaterialPropertyAndDecoratorDrawers(objs); } - // Called after edit or undo + // Called after edit, sets its attached value for each Drawer (usually Keywords, no modification of other properties is involved) + // If you find that the default value of the newly created material does not meet expectations, please call PresetHelper.ApplyPresetsInMaterial() public static void ApplyMaterialPropertyAndDecoratorDrawers(Object[] targets) { if (!EditorMaterialUtility.disableApplyMaterialPropertyDrawers) diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/package.json b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/package.json index 7b93286e5..7d2422493 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/package.json +++ b/Assets/NiloToonURP/Editor/ShaderGUI/LWGUI-main/package.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72837249eae8361090da677d7bef632063390a0e4f2611323b6a46877bf16a21 +oid sha256:11f5fb5d7f4654d4e9a930c9842704152a77f81de667591ab1655f11f8f63f85 size 586 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_FurPreset_LWGUI_ShaderPropertyPreset.asset b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_FurPreset_LWGUI_ShaderPropertyPreset.asset new file mode 100644 index 000000000..2213aebe6 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_FurPreset_LWGUI_ShaderPropertyPreset.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:085914e78078281c2a141c09aeb7542ccb154bf1a69d8599d9bc3650f07d2dbc +size 60969 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_FurPreset_LWGUI_ShaderPropertyPreset.asset.meta b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_FurPreset_LWGUI_ShaderPropertyPreset.asset.meta new file mode 100644 index 000000000..163e37c43 --- /dev/null +++ b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_FurPreset_LWGUI_ShaderPropertyPreset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b1a02f3f63f5cc4a87a0ffc38681d5a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_MatCapAdditivePreset_LWGUI_ShaderPropertyPreset.asset b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_MatCapAdditivePreset_LWGUI_ShaderPropertyPreset.asset index 11e599dd0..55424829c 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_MatCapAdditivePreset_LWGUI_ShaderPropertyPreset.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_MatCapAdditivePreset_LWGUI_ShaderPropertyPreset.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c7d327cdf5f763edcabdd2389cf4ba89f8cf935394a287148687701ce529a62 -size 11382 +oid sha256:747073d68783d6b8406a72ec504d999a7e07c99d948a3eef86a6ba8aed896642 +size 11740 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolvePatternMap_LWGUI_ShaderPropertyPreset.asset b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolvePatternMap_LWGUI_ShaderPropertyPreset.asset index b2fc5abc0..20f8c12d1 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolvePatternMap_LWGUI_ShaderPropertyPreset.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolvePatternMap_LWGUI_ShaderPropertyPreset.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e68e8d17348b2ed709308448ec6a8c6947a09d03b11676367e48a860d8ca315d -size 1079 +oid sha256:8d7b1a7ddf93fe22f9bed05000d803a7b9dd8c0832c3e108c4806c6872e3f96e +size 1115 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolveThresholdMap_LWGUI_ShaderPropertyPreset.asset b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolveThresholdMap_LWGUI_ShaderPropertyPreset.asset index fa1e6832c..ff9e584db 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolveThresholdMap_LWGUI_ShaderPropertyPreset.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_PerMaterialDissolveThresholdMap_LWGUI_ShaderPropertyPreset.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d44679b0f758fcdb2444c384a400ab355657aee5fbfba6ee9112ab0c24176794 -size 3404 +oid sha256:3543d3ea057b6f69398ede412d5b1378b074febe2b0ed91893131e3bf167f989 +size 3510 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_ZOffsetPreset_LWGUI_ShaderPropertyPreset.asset b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_ZOffsetPreset_LWGUI_ShaderPropertyPreset.asset index 9df0f5925..ba8330d77 100644 --- a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_ZOffsetPreset_LWGUI_ShaderPropertyPreset.asset +++ b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToon LWGUI presets/NiloToonCharacter_ZOffsetPreset_LWGUI_ShaderPropertyPreset.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:784e3403da9097047b3270b484fb082af902672a7dfbadd2a43238d9b3cd2559 -size 5783 +oid sha256:cf8cff36bdca0f556b86b62b0645e64028297b1efcaa18f9e1c3fe139e615bdd +size 5979 diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToonCharacterFurShaderGUI.cs b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToonCharacterFurShaderGUI.cs deleted file mode 100644 index 6772beedc..000000000 --- a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToonCharacterFurShaderGUI.cs +++ /dev/null @@ -1,298 +0,0 @@ -// 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); - } - } -} diff --git a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToonCharacterFurShaderGUI.cs.meta b/Assets/NiloToonURP/Editor/ShaderGUI/NiloToonCharacterFurShaderGUI.cs.meta deleted file mode 100644 index 74130d153..000000000 --- a/Assets/NiloToonURP/Editor/ShaderGUI/NiloToonCharacterFurShaderGUI.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 3ad6027c1c29b71488586df1e8150fa7 \ No newline at end of file diff --git a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_001_DefaultHardShadow.mat b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_001_DefaultHardShadow.mat index 278668a38..80d8d19f0 100644 --- a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_001_DefaultHardShadow.mat +++ b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_001_DefaultHardShadow.mat @@ -627,6 +627,7 @@ Material: - _HairStrandSpecularShapeFrequency: 750 - _HairStrandSpecularShapePositionOffset: 0 - _HairStrandSpecularShapeShift: 0.015 + - _HairStrandSpecularShowInShadowArea: 1 - _HairStrandSpecularTintMapUsage: 1 - _IgnoreDefaultMainLightFaceShadow: 1 - _IndirectLightFlatten: 1 diff --git a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_002_PinkSoftness8Shadow(ExtraSpecular).mat b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_002_PinkSoftness8Shadow(ExtraSpecular).mat index c50eb46a1..42e1e8e3e 100644 --- a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_002_PinkSoftness8Shadow(ExtraSpecular).mat +++ b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_002_PinkSoftness8Shadow(ExtraSpecular).mat @@ -1067,6 +1067,7 @@ Material: - _HairStrandSpecularShapeFrequency: 750 - _HairStrandSpecularShapePositionOffset: 0 - _HairStrandSpecularShapeShift: 0.015 + - _HairStrandSpecularShowInShadowArea: 1 - _HairStrandSpecularTintMapUsage: 1 - _HeightAmplitude: 0.02 - _HeightCenter: 0.5 diff --git a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_003_DefaultSoftness4Shadow.mat b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_003_DefaultSoftness4Shadow.mat index ee6ec94b0..b0ef339e8 100644 --- a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_003_DefaultSoftness4Shadow.mat +++ b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_003_DefaultSoftness4Shadow.mat @@ -949,6 +949,7 @@ Material: - _HairStrandSpecularShapeFrequency: 750 - _HairStrandSpecularShapePositionOffset: 0 - _HairStrandSpecularShapeShift: 0.015 + - _HairStrandSpecularShowInShadowArea: 1 - _HairStrandSpecularTintMapUsage: 1 - _HighColor_Power: 0 - _IgnoreDefaultMainLightFaceShadow: 0 diff --git a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_004_OrangeSoftness9LightShadow.mat b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_004_OrangeSoftness9LightShadow.mat index 28eb1c08e..97007ed2e 100644 --- a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_004_OrangeSoftness9LightShadow.mat +++ b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_004_OrangeSoftness9LightShadow.mat @@ -1767,6 +1767,7 @@ Material: - _HairStrandSpecularShapeFrequency: 750 - _HairStrandSpecularShapePositionOffset: 0 - _HairStrandSpecularShapeShift: 0.015 + - _HairStrandSpecularShowInShadowArea: 1 - _HairStrandSpecularTintMapUsage: 1 - _HighColor_Power: 0 - _IDMask1: 0 diff --git a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_005_DarkRedSoftness4Shadow.asset b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_005_DarkRedSoftness4Shadow.asset index d9e253dc3..ee52a266d 100644 --- a/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_005_DarkRedSoftness4Shadow.asset +++ b/Assets/NiloToonURP/Runtime/Materials/SkinMaterialTemplates/NiloSkinMaterialTemplate_005_DarkRedSoftness4Shadow.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6362c4ffe61bead3daa5fc100592b1a578fcb5c5ea1d7efd29a23e4c2dca8195 -size 45387 +oid sha256:a981de161d32f993b9e46187d8727309d066de1292208a3b1156a0b05bd7c3a3 +size 45433 diff --git a/Assets/NiloToonURP/Runtime/NiloToonCharacterLightController.cs b/Assets/NiloToonURP/Runtime/NiloToonCharacterLightController.cs index be9630035..e06d8b575 100644 --- a/Assets/NiloToonURP/Runtime/NiloToonCharacterLightController.cs +++ b/Assets/NiloToonURP/Runtime/NiloToonCharacterLightController.cs @@ -1,6 +1,8 @@ using System.Collections; using System.Collections.Generic; +#if UNITY_EDITOR using UnityEditor; +#endif using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Serialization; @@ -176,4 +178,4 @@ namespace NiloToon.NiloToonURP } } #endif -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/NiloToonCharacterMainLightOverrider.cs b/Assets/NiloToonURP/Runtime/NiloToonCharacterMainLightOverrider.cs index 8af87e0b1..c50922769 100644 --- a/Assets/NiloToonURP/Runtime/NiloToonCharacterMainLightOverrider.cs +++ b/Assets/NiloToonURP/Runtime/NiloToonCharacterMainLightOverrider.cs @@ -1,6 +1,8 @@ using System.Collections; using System.Collections.Generic; +#if UNITY_EDITOR using UnityEditor; +#endif using UnityEngine; namespace NiloToon.NiloToonURP @@ -194,4 +196,4 @@ namespace NiloToon.NiloToonURP } #endif -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/NiloToonLightSourceModifier.cs b/Assets/NiloToonURP/Runtime/NiloToonLightSourceModifier.cs index d9140e78b..b73260811 100644 --- a/Assets/NiloToonURP/Runtime/NiloToonLightSourceModifier.cs +++ b/Assets/NiloToonURP/Runtime/NiloToonLightSourceModifier.cs @@ -1,7 +1,9 @@ using System; using System.Collections; using System.Collections.Generic; +#if UNITY_EDITOR using UnityEditor; +#endif using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Serialization; @@ -338,4 +340,4 @@ namespace NiloToon.NiloToonURP } } #endif -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/NiloToonPerCharacterRenderController.cs b/Assets/NiloToonURP/Runtime/NiloToonPerCharacterRenderController.cs index 122144b1c..fbf69a2cd 100644 --- a/Assets/NiloToonURP/Runtime/NiloToonPerCharacterRenderController.cs +++ b/Assets/NiloToonURP/Runtime/NiloToonPerCharacterRenderController.cs @@ -1109,20 +1109,10 @@ namespace NiloToon.NiloToonURP if (regenerateSmoothedNormalInUV8) { - NiloBakeSmoothNormalTSToMeshUv8.GenGOSmoothedNormalToUV8(gameObject); + NiloBakeSmoothNormalTSToMeshUv8.GenGOSmoothedNormalToUV8(gameObject); } - + AutoFillInMissingProperties(); - - // Streamingle: 이미 등록된 renderer에도 updateWhenOffscreen 적용 (씬에 미리 있던 캐릭터 대응). - // RefillAllRenderers는 새 등록 때만 호출되므로 OnEnable에서 한 번 더 강제. - for (int i = 0; i < allRenderers.Count; i++) - { - if (allRenderers[i] is SkinnedMeshRenderer existingSmr && !existingSmr.updateWhenOffscreen) - { - existingSmr.updateWhenOffscreen = true; - } - } // To support VRMBlendShapeProxy, NiloToon now generates material instances on OnEnable(), which is before VRMBlendShapeProxy's Start() // Note: @@ -1547,15 +1537,7 @@ namespace NiloToon.NiloToonURP // we don't want to add particle/vfx/trail....renderers if(!(renderer is MeshRenderer or SkinnedMeshRenderer)) continue; - - // Streamingle: Pass.cs의 manual DrawRenderer로 cullResults 우회 시, - // SkinnedMeshRenderer가 화면 밖이면 Unity가 본 매트릭스 갱신을 skip하여 stale pose가 그려질 수 있음. - // updateWhenOffscreen=true 강제. (localBounds는 GetCharacterBoundCenter에 영향 주므로 건드리지 않음) - if (renderer is SkinnedMeshRenderer smr && !smr.updateWhenOffscreen) - { - smr.updateWhenOffscreen = true; - } - + var NiloToonPerCharacterRenderControllerFound = renderer.transform.GetComponentInParent(); if(NiloToonPerCharacterRenderControllerFound) { diff --git a/Assets/NiloToonURP/Runtime/NiloToonRendererRedrawer.cs b/Assets/NiloToonURP/Runtime/NiloToonRendererRedrawer.cs index 67e67ec84..d607e009d 100644 --- a/Assets/NiloToonURP/Runtime/NiloToonRendererRedrawer.cs +++ b/Assets/NiloToonURP/Runtime/NiloToonRendererRedrawer.cs @@ -2,7 +2,9 @@ using System; using System.Collections; using System.Collections.Generic; using UnityEngine; +#if UNITY_EDITOR using UnityEditor; +#endif using UnityEngine.Rendering; using UnityEngine.Serialization; @@ -389,4 +391,4 @@ namespace NiloToon.NiloToonURP } } #endif -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonAllInOneRendererFeature.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonAllInOneRendererFeature.cs index e8eb019c9..ce0702dcc 100644 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonAllInOneRendererFeature.cs +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonAllInOneRendererFeature.cs @@ -28,6 +28,9 @@ namespace NiloToon.NiloToonURP [Header("Motion Blur")] public NiloToonMotionBlurPass.Settings motionBlurSettings = new NiloToonMotionBlurPass.Settings(); + [Header("Fur (Standalone Only)")] + public NiloToonFurPass.Settings furSettings = new NiloToonFurPass.Settings(); + [Header("Prepass Buffer")] [Revertible] public bool forceRenderPrepassBuffer = false; @@ -65,6 +68,7 @@ namespace NiloToon.NiloToonURP NiloToonAnimePostProcessPass AnimePostProcessPass; NiloToonPrepassBufferRTPass PrepassBufferRTPass; NiloToonUberPostProcessPass UberPostProcessPass; + NiloToonFurPass FurPass; #if UNITY_2022_3_OR_NEWER NiloToonMotionBlurPass MotionBlurPass; #endif @@ -120,6 +124,8 @@ namespace NiloToon.NiloToonURP if (MotionBlurPass == null) MotionBlurPass = new NiloToonMotionBlurPass(settings); #endif + if (FurPass == null) + FurPass = new NiloToonFurPass(settings); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Configures where the render pass should be injected. @@ -162,6 +168,9 @@ namespace NiloToon.NiloToonURP // AnimePostProcessPass's renderPassEvent will be decided by the pass itself UberPostProcessPass.renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing + UberPostProcessPass.settings.renderPassEventTimingOffset; + + // Fur soft alpha must render after skybox, but still before regular transparent objects. + FurPass.renderPassEvent = RenderPassEvent.BeforeRenderingTransparents - 1; } // Here you can inject one or multiple render passes in the renderer. @@ -177,6 +186,7 @@ namespace NiloToon.NiloToonURP // since we can't call ConfigureInput() inside RecordRenderGraph() //---------------------------------------------------------------- SetToonParamPass.ConfigureInputs(renderer); + PrepassBufferRTPass.ConfigureInputs(SetToonParamPass.isDeferredRendering); ScreenSpaceOutlinePass.ConfigureInput(renderingData.cameraData.cameraType); #if UNITY_2022_3_OR_NEWER MotionBlurPass.ConfigureInputs(renderingData.cameraData.camera); @@ -204,6 +214,8 @@ namespace NiloToon.NiloToonURP renderer.EnqueuePass(ToonOutlinePass_RightAfterTransparent); renderer.EnqueuePass(ScreenSpaceOutlinePass); renderer.EnqueuePass(ExtraThickOutlinePass); + if (FurPass.ShouldEnqueue()) + renderer.EnqueuePass(FurPass); renderer.EnqueuePass(AnimePostProcessPass); if (settings.MiscSettings.EnableSkyboxDrawBeforeOpaque && renderingData.cameraData.camera.clearFlags == CameraClearFlags.Skybox) @@ -240,9 +252,12 @@ namespace NiloToon.NiloToonURP bool shouldDrawPrepass = renderingData.cameraData.postProcessEnabled && isAnyNiloPostEnabled; shouldDrawPrepass |= isAnyNiloToonPerCharacterScriptRequiresPrepass; shouldDrawPrepass |= settings.forceRenderPrepassBuffer; + bool shouldRenderFurPrepassBuffer = FurPass.ShouldRenderFurPrepassBuffer(); + shouldDrawPrepass |= shouldRenderFurPrepassBuffer; if (shouldDrawPrepass) { + PrepassBufferRTPass.SetFurEnabled(shouldRenderFurPrepassBuffer); renderer.EnqueuePass(PrepassBufferRTPass); } //-------------------------------------------------------------------------- @@ -284,6 +299,7 @@ namespace NiloToon.NiloToonURP UberPostProcessPass?.Dispose(); SphereShadowTestRTPass?.Dispose(); MotionBlurPass?.Dispose(); + AnimePostProcessPass?.Dispose(); // null all passes SetToonParamPass = null; @@ -298,6 +314,7 @@ namespace NiloToon.NiloToonURP PrepassBufferRTPass = null; UberPostProcessPass = null; MotionBlurPass = null; + FurPass = null; } #endif @@ -362,4 +379,3 @@ namespace NiloToon.NiloToonURP #endregion } } - diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonFurRendererFeature.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonFurRendererFeature.cs deleted file mode 100644 index 30de94e84..000000000 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonFurRendererFeature.cs +++ /dev/null @@ -1,60 +0,0 @@ -// NiloToon Fur Renderer Feature -// Add this to your URP Renderer to enable fur shell rendering -// This allows single-material fur shaders to work properly -// -// Note: Fur mask rendering is now integrated into NiloToonPrepassBufferRTPass -// The fur mask is automatically rendered to G and B channels of _NiloToonPrepassBufferTex - -using System; -using UnityEngine; -using UnityEngine.Rendering.Universal; - -namespace NiloToon.NiloToonURP -{ - [Serializable] - public class NiloToonFurRendererFeatureSettings - { - [Header("Fur Shell Settings")] - public NiloToonFurShellPass.Settings furShellSettings = new NiloToonFurShellPass.Settings(); - } - - public class NiloToonFurRendererFeature : ScriptableRendererFeature - { - public NiloToonFurRendererFeatureSettings settings = new NiloToonFurRendererFeatureSettings(); - - NiloToonFurShellPass FurShellPass; - - public override void Create() - { - ReInitPassesIfNeeded(); - } - - private void ReInitPassesIfNeeded() - { - if (FurShellPass == null) - FurShellPass = new NiloToonFurShellPass(settings.furShellSettings); - - // Set render pass events - FurShellPass.renderPassEvent = settings.furShellSettings.renderTiming; - } - - public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) - { - ReInitPassesIfNeeded(); - - // Update render timing in case it changed - FurShellPass.renderPassEvent = settings.furShellSettings.renderTiming; - - // Enqueue fur shell pass for actual fur rendering - // Note: Fur mask is rendered via NiloToonPrepassBufferRTPass (NiloToonFurShellMask LightMode) - renderer.EnqueuePass(FurShellPass); - } - -#if UNITY_2022_2_OR_NEWER - protected override void Dispose(bool disposing) - { - FurShellPass = null; - } -#endif - } -} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonFurRendererFeature.cs.meta b/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonFurRendererFeature.cs.meta deleted file mode 100644 index eb7d4cb12..000000000 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/NiloToonFurRendererFeature.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 4076e5ecd1634a74eaabed924c9a971c \ No newline at end of file diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAnimePostProcessPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAnimePostProcessPass.cs index 6a07092f1..3351ff3ed 100644 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAnimePostProcessPass.cs +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAnimePostProcessPass.cs @@ -198,6 +198,14 @@ namespace NiloToon.NiloToonURP public override void OnCameraCleanup(CommandBuffer cmd) { } + +#if UNITY_2022_2_OR_NEWER + public void Dispose() + { + CoreUtils.Destroy(material); + material = null; + } +#endif class PassData { @@ -279,4 +287,4 @@ namespace NiloToon.NiloToonURP } #endif } -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAverageShadowTestRTPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAverageShadowTestRTPass.cs index cf71f0d13..b6aa9bb71 100644 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAverageShadowTestRTPass.cs +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonAverageShadowTestRTPass.cs @@ -50,6 +50,10 @@ namespace NiloToon.NiloToonURP #endif static readonly int _SphereShadowMapRT_SID = Shader.PropertyToID("_SphereShadowMapRT"); + static readonly int _GlobalAverageShadowTestBoundingSphereDataArray_SID = Shader.PropertyToID("_GlobalAverageShadowTestBoundingSphereDataArray"); + static readonly int _GlobalAverageShadowStrength_SID = Shader.PropertyToID("_GlobalAverageShadowStrength"); + static readonly int _BlitScaleBias_SID = Shader.PropertyToID("_BlitScaleBias"); + static readonly int _NiloToonAverageShadowMapRT_SID = Shader.PropertyToID("_NiloToonAverageShadowMapRT"); public NiloToonAverageShadowTestRTPass(NiloToonRendererFeatureSettings allSettings) { @@ -162,6 +166,8 @@ namespace NiloToon.NiloToonURP public void Dispose() { shadowTestResultRTH?.Release(); + CoreUtils.Destroy(material); + material = null; } #endif bool shouldRenderRT(Camera camera) @@ -222,8 +228,8 @@ namespace NiloToon.NiloToonURP { var shadowControlVolumeEffect = VolumeManager.instance.stack.GetComponent(); - cmd.SetGlobalFloatArray("_GlobalAverageShadowTestBoundingSphereDataArray", shaderDataArray); // once set, we can't change the size of array in GPU anymore, it is not Unity's fault but graphics API's design. - cmd.SetGlobalFloat("_GlobalAverageShadowStrength", shadowControlVolumeEffect.charAverageShadowStrength.value); + cmd.SetGlobalFloatArray(_GlobalAverageShadowTestBoundingSphereDataArray_SID, shaderDataArray); // once set, we can't change the size of array in GPU anymore, it is not Unity's fault but graphics API's design. + cmd.SetGlobalFloat(_GlobalAverageShadowStrength_SID, shadowControlVolumeEffect.charAverageShadowStrength.value); } private bool InitMaterialIfNeeded() @@ -243,6 +249,7 @@ namespace NiloToon.NiloToonURP private void UpdateShaderDataArray(Camera camera) { // TODO: shadow will be wrong if number of active character in scene is more than MAX_SHADOW_SLOT_COUNT-1 + Array.Clear(shaderDataArray, 0, shaderDataArray.Length); // reserve the right most slot for camera, other slots for each active character for (int i = 0; i < Mathf.Min(MAX_SHADOW_SLOT_COUNT - 1, NiloToonAllInOneRendererFeature.characterList.Count); i++) @@ -297,9 +304,8 @@ namespace NiloToon.NiloToonURP var resourceData = frameData.Get(); var cameraData = frameData.Get(); - if(!InitMaterialIfNeeded()) return; - - UpdateShaderDataArray(cameraData.camera); + // IMPORTANT: Always create RT even if we won't render to it, because character shaders always sample it + // We need to ensure it exists and is cleared to white (no shadow) as a safe default GetRTDescriptor(out var renderTextureDescriptor); @@ -309,15 +315,21 @@ namespace NiloToon.NiloToonURP // simplifies your code. TextureHandle destination = UniversalRenderer.CreateRenderGraphTexture(renderGraph, renderTextureDescriptor, - "_NiloToonAverageShadowTestRT", true); + "_NiloToonAverageShadowTestRT", true, FilterMode.Point); passData.destTex = destination; + + TextureHandle mainLightShadowmap = resourceData.mainShadowsTexture; + if (mainLightShadowmap.IsValid()) + builder.UseTexture(mainLightShadowmap, AccessFlags.Read); // Declare that this render pass uses the temporary destination texture // as its color render target. // This is similar to cmd.SetRenderTarget prior to the RenderGraph API. builder.SetRenderAttachment(destination, 0); + builder.SetGlobalTextureAfterPass(destination, _NiloToonAverageShadowMapRT_SID); + // RenderGraph automatically determines that it can remove this render pass // because its results, which are stored in the temporary destination texture, // are not used by other passes. @@ -327,26 +339,38 @@ namespace NiloToon.NiloToonURP builder.AllowGlobalStateModification(true); + // Prepare material and data before the render func + bool materialReady = InitMaterialIfNeeded(); + bool shouldRender = shouldRenderRT(cameraData.camera); + + // ===== RENDERING SAFETY FIX: Get all data BEFORE lambda to avoid race conditions ===== + float shadowStrength = 1f; + if (materialReady && shouldRender) + { + UpdateShaderDataArray(cameraData.camera); + + // Cache volume data before lambda execution to avoid accessing VolumeManager during rendering + var shadowControlVolumeEffect = VolumeManager.instance.stack.GetComponent(); + shadowStrength = shadowControlVolumeEffect.charAverageShadowStrength.value; + } + // Set the ExecutePass method as the rendering function that render graph calls // for the render pass. // This sample uses a lambda expression to avoid memory allocations. builder.SetRenderFunc((PassData data, RasterGraphContext context) => { - context.cmd.ClearRenderTarget(true,true,Color.white); + // Always clear to white (no shadow) as default, matching non-RG behavior + context.cmd.ClearRenderTarget(true, true, Color.white); - if (shouldRenderRT(cameraData.camera)) + // Only render shadow data if conditions are met + if (materialReady && shouldRender) { - //CMDSetGlobalParam(context.cmd); - var shadowControlVolumeEffect = VolumeManager.instance.stack.GetComponent(); var cmd = context.cmd; - cmd.SetGlobalFloatArray("_GlobalAverageShadowTestBoundingSphereDataArray", shaderDataArray); // once set, we can't change the size of array in GPU anymore, it is not Unity's fault but graphics API's design. - cmd.SetGlobalFloat("_GlobalAverageShadowStrength", shadowControlVolumeEffect.charAverageShadowStrength.value); - + cmd.SetGlobalFloatArray(_GlobalAverageShadowTestBoundingSphereDataArray_SID, shaderDataArray); // once set, we can't change the size of array in GPU anymore, it is not Unity's fault but graphics API's design. + cmd.SetGlobalFloat(_GlobalAverageShadowStrength_SID, shadowStrength); // Use cached value from above + // special temp fix for RG - // * Blitter.BlitTexture(context.cmd, data.copySourceTexture,new Vector4(1, 1, 0, 0), 0, false); - // * may solve this problem - cmd.SetGlobalVector("_BlitScaleBias", new Vector4(1, 1, 0, 0)); - material.SetVector("_BlitScaleBias", new Vector4(1, 1, 0, 0)); + cmd.SetGlobalVector(_BlitScaleBias_SID, new Vector4(1, 1, 0, 0)); // Records a rendering command to copy, or blit, the contents of the source texture // to the color render target of the render pass. @@ -355,10 +379,8 @@ namespace NiloToon.NiloToonURP CoreUtils.DrawFullScreen(cmd, material); } }); - - builder.SetGlobalTextureAfterPass(destination, Shader.PropertyToID("_NiloToonAverageShadowMapRT")); } } #endif } -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonCharSelfShadowMapRTPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonCharSelfShadowMapRTPass.cs index 96c9f44aa..29f957be0 100644 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonCharSelfShadowMapRTPass.cs +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonCharSelfShadowMapRTPass.cs @@ -174,31 +174,6 @@ namespace NiloToon.NiloToonURP List validCharList = new List(); List finalValidCharList = new List(); - // Streamingle: shader → "NiloToonSelfShadowCaster" pass index 캐시. - // Unity 6 RG path는 main camera cullResults 만 쓰므로 카메라가 캐릭터 안 보면 shadow map 비어 그림자 사라짐. - // ExecutePass에서 manual DrawRenderer로 cullResults 우회. shader 별 pass index 조회는 비싸 캐시 필요. - static readonly Dictionary s_shadowCasterPassIndexCache = new Dictionary(); - static readonly ShaderTagId s_lightModeTagId = new ShaderTagId("LightMode"); - static readonly ShaderTagId s_shadowCasterTagId = new ShaderTagId("NiloToonSelfShadowCaster"); - - static int GetShadowCasterPassIndex(Shader shader) - { - if (shader == null) return -1; - if (s_shadowCasterPassIndexCache.TryGetValue(shader, out int cached)) return cached; - int found = -1; - int passCount = shader.passCount; - for (int i = 0; i < passCount; i++) - { - if (shader.FindPassTagValue(i, s_lightModeTagId) == s_shadowCasterTagId) - { - found = i; - break; - } - } - s_shadowCasterPassIndexCache[shader] = found; - return found; - } - // Constructor(will not call on every frame) public NiloToonCharSelfShadowMapRTPass(NiloToonRendererFeatureSettings allSettings) @@ -473,15 +448,27 @@ namespace NiloToon.NiloToonURP // https://docs.microsoft.com/en-us/windows/win32/dxtecharts/common-techniques-to-improve-shadow-depth-maps //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + GeometryUtility.CalculateFrustumPlanes(camera, cameraPlanes); + validCharList.Clear(); - // [1] Streamingle: 메인 카메라 frustum cull 제거. (controller bound 기반 필터) - // 캐릭터가 메인 카메라 frustum 밖이어도 ortho box / keyword 가 정상 동작해야 함. - // 실제 cullResults 우회는 ExecutePass의 manual DrawRenderer 가 담당. + // [1] filter list foreach (var targetChar in NiloToonAllInOneRendererFeature.characterList) { + // if target is not valid, skip it if (targetChar == null) continue; - if (!targetChar.isActiveAndEnabled) continue; + if (!targetChar.isActiveAndEnabled) continue; // character GameObject not enabled(not rendering) but in list + + // if character bounding sphere is completely not visible in game camera frustum, skip it + var boundRadius = targetChar.GetCharacterBoundRadius(); + var centerPosWS = targetChar.GetCharacterBoundCenter(); + // TODO: this section is not correct, which may incorrectly cull effective shadow caster that is OUTSIDE of main camera frustum + if (!GeometryUtility.TestPlanesAABB(cameraPlanes, new Bounds(centerPosWS, Vector3.one * boundRadius))) + { + continue; + } + + // it is a valid visible char, add to list validCharList.Add(targetChar); } @@ -615,7 +602,43 @@ namespace NiloToon.NiloToonURP } #endif - // Streamingle: cullResults / custom culling 코드 제거. manual DrawRenderer가 cullResults에 의존하지 않으므로 불필요. + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // set culling for shadow camera -> do culling + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + camera.TryGetCullingParameters(out var cullingParameters); + + // update culling matrix + cullingParameters.cullingMatrix = shadowCamProjectionMatrix * shadowCamViewMatrix; + + // update culling planes + GeometryUtility.CalculateFrustumPlanes(cullingParameters.cullingMatrix, cameraPlanes); + for (int i = 0; i < cameraPlanes.Length; i++) + { + cullingParameters.SetCullingPlane(i, cameraPlanes[i]); + } + + CullingResults cullResults; + + bool terrainExist = false; + if (settings.terrainCrashSafeGuard) + { + terrainExist = Terrain.activeTerrains.Length != 0; + } + if (settings.perfectCullingForShadowCasters && !terrainExist) + { + // use the above new cullResults in DrawRenderers() below, + // so even a renderer is not visible in the perspective of main camera, + // it can still render correctly in shadow camera's perspective due to this new culling + + // (2021-07-14) unity will crash if code running this line and terrain exist in scene + // (2024-03-21) enable this will make VLB's SRP batcher mode flicker randomly, not sure why, should we do something to revert this culling line? + cullResults = context.Cull(ref cullingParameters); // original working code, but will crash if terrain exist + } + else + { + // (2021-07-14) a special temp fix to avoid terrain crashing unity, but will make shadow culling not always correctly if shadow caster is not existing on screen + cullResults = renderingData.cullResults; + } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Set uniform (before context.DrawRenderers) @@ -685,12 +708,12 @@ namespace NiloToon.NiloToonURP */ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Streamingle: cullResults 의존성 완전 제거. context.DrawRenderers + custom culling 모두 제거. - // characterList의 모든 NiloToon 캐릭터를 manual draw로 그려 카메라 frustum 무관하게 shadow map 채움. + // draw all char renderer using SRP batching (must set all uniforms and executed before draw!) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - DrawNiloToonCharsManuallyLegacy(cmd); - context.ExecuteCommandBuffer(cmd); - cmd.Clear(); + ShaderTagId shaderTagId = new ShaderTagId("NiloToonSelfShadowCaster"); + var drawSetting = CreateDrawingSettings(shaderTagId, ref renderingData, SortingCriteria.CommonOpaque); + var filterSetting = new FilteringSettings(RenderQueueRange.opaque); + context.DrawRenderers(cullResults, ref drawSetting, ref filterSetting); // using custom cullResults from shadow camera's perspective, instead of main camera's cull result // Note: Since we are providing our own _NiloToonSelfShadowWorldToClip to shader for VP transform, // this section is not needed anymore, it will trigger a bug in multi pass mode XR @@ -789,7 +812,8 @@ namespace NiloToon.NiloToonURP // copy and edit of https://docs.unity3d.com/6000.0/Documentation/Manual/urp/render-graph-draw-objects-in-a-pass.html private class PassData { - // Streamingle: RendererListHandle 제거. manual DrawRenderer로 대체됨. + // Create a field to store the list of objects to draw + public RendererListHandle rendererListHandle; public bool shouldRender; public Matrix4x4 _NiloToonSelfShadowWorldToClip; public Vector4 _NiloToonSelfShadowParam; @@ -816,10 +840,21 @@ namespace NiloToon.NiloToonURP UniversalCameraData cameraData = frameContext.Get(); UniversalRenderingData renderingData = frameContext.Get(); UniversalLightData lightData = frameContext.Get(); + + SortingCriteria sortFlags = SortingCriteria.CommonOpaque; //cameraData.defaultOpaqueSortFlags; + RenderQueueRange renderQueueRange = RenderQueueRange.opaque; + FilteringSettings filterSettings = new FilteringSettings(renderQueueRange, ~0); - // Streamingle: RendererList 기반 그리기 제거. ExecutePass의 manual DrawRenderer가 - // characterList를 직접 그리므로 cullResults에 의존하는 RendererList는 불필요 + double-draw 방지. - // RendererList CPU 컬링 비용도 절약. + // Redraw only objects that have their LightMode tag set to "NiloToonSelfShadowCaster" + ShaderTagId shadersToOverride = new ShaderTagId("NiloToonSelfShadowCaster"); + + // Create drawing settings + DrawingSettings drawSettings = RenderingUtils.CreateDrawingSettings(shadersToOverride, renderingData, cameraData, lightData, sortFlags); + + // Create the list of objects to draw + var rendererListParameters = new RendererListParams(renderingData.cullResults, drawSettings, filterSettings); + + // create RT (temp) // Create texture properties that match the screen size @@ -836,17 +871,21 @@ namespace NiloToon.NiloToonURP { shouldRender = true; } - + + // Convert the list to a list handle that the render graph system can use + passData.rendererListHandle = renderGraph.CreateRendererList(rendererListParameters); passData.shouldRender = shouldRender; - + RenderTextureDescriptor renderTextureDescriptor = new RenderTextureDescriptor(shadowMapSize, shadowMapSize, RenderTextureFormat.Shadowmap, 16); // Create a temporary texture TextureHandle shadowMapRT = UniversalRenderer.CreateRenderGraphTexture(renderGraph, renderTextureDescriptor, "_NiloToonCharSelfShadowMapRT", true); - + // Set the render target as the color and depth textures of the active camera texture UniversalResourceData resourceData = frameContext.Get(); - + + builder.UseRendererList(passData.rendererListHandle); + //builder.SetRenderAttachment(resourceData.activeColorTexture, 0); builder.SetRenderAttachmentDepth(shadowMapRT, AccessFlags.Write); @@ -997,15 +1036,29 @@ namespace NiloToon.NiloToonURP // https://docs.microsoft.com/en-us/windows/win32/dxtecharts/common-techniques-to-improve-shadow-depth-maps //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + GeometryUtility.CalculateFrustumPlanes(camera, cameraPlanes); + validCharList.Clear(); - // [1] Streamingle: 메인 카메라 frustum cull 제거. (controller bound 기반 필터) - // 캐릭터가 메인 카메라 frustum 밖이어도 ortho box / keyword 가 정상 동작해야 함. - // 실제 cullResults 우회는 ExecutePass의 manual DrawRenderer 가 담당. + // [1] filter list foreach (var targetChar in NiloToonAllInOneRendererFeature.characterList) { + // if target is not valid, skip it if (targetChar == null) continue; - if (!targetChar.isActiveAndEnabled) continue; + if (!targetChar.isActiveAndEnabled) + continue; // character GameObject not enabled(not rendering) but in list + + // if character bounding sphere is completely not visible in game camera frustum, skip it + var boundRadius = targetChar.GetCharacterBoundRadius(); + var centerPosWS = targetChar.GetCharacterBoundCenter(); + // TODO: this section is not correct, which may incorrectly cull effective shadow caster that is OUTSIDE of main camera frustum + if (!GeometryUtility.TestPlanesAABB(cameraPlanes, + new Bounds(centerPosWS, Vector3.one * boundRadius))) + { + continue; + } + + // it is a valid visible char, add to list validCharList.Add(targetChar); } @@ -1275,67 +1328,10 @@ namespace NiloToon.NiloToonURP cmd.SetGlobalVector("_NiloToonSelfShadowSoftShadowParam", data._NiloToonSelfShadowSoftShadowParam); cmd.SetKeyword(GlobalKeyword.Create(_NILOTOON_RECEIVE_SELF_SHADOW_Keyword), true); - - // Streamingle: cullResults 의존성 완전 제거. manual draw만 사용. - // characterList의 모든 NiloToon 캐릭터를 직접 그려 카메라 frustum 무관하게 shadow map 채움. - DrawNiloToonCharsManually(cmd); - } - - static void DrawNiloToonCharsManually(RasterCommandBuffer cmd) - { - var charList = NiloToonAllInOneRendererFeature.characterList; - if (charList == null) return; - for (int c = 0; c < charList.Count; c++) - { - var character = charList[c]; - if (character == null || !character.isActiveAndEnabled) continue; - var renderers = character.allRenderers; - if (renderers == null) continue; - for (int r = 0; r < renderers.Count; r++) - { - var renderer = renderers[r]; - if (renderer == null || !renderer.enabled || !renderer.gameObject.activeInHierarchy) continue; - var sharedMats = renderer.sharedMaterials; - if (sharedMats == null) continue; - for (int subIdx = 0; subIdx < sharedMats.Length; subIdx++) - { - var mat = sharedMats[subIdx]; - if (mat == null) continue; - int passIdx = GetShadowCasterPassIndex(mat.shader); - if (passIdx < 0) continue; - cmd.DrawRenderer(renderer, mat, subIdx, passIdx); - } - } - } + + // Draw the objects in the list + cmd.DrawRendererList(data.rendererListHandle); } #endif - - static void DrawNiloToonCharsManuallyLegacy(CommandBuffer cmd) - { - var charList = NiloToonAllInOneRendererFeature.characterList; - if (charList == null) return; - for (int c = 0; c < charList.Count; c++) - { - var character = charList[c]; - if (character == null || !character.isActiveAndEnabled) continue; - var renderers = character.allRenderers; - if (renderers == null) continue; - for (int r = 0; r < renderers.Count; r++) - { - var renderer = renderers[r]; - if (renderer == null || !renderer.enabled || !renderer.gameObject.activeInHierarchy) continue; - var sharedMats = renderer.sharedMaterials; - if (sharedMats == null) continue; - for (int subIdx = 0; subIdx < sharedMats.Length; subIdx++) - { - var mat = sharedMats[subIdx]; - if (mat == null) continue; - int passIdx = GetShadowCasterPassIndex(mat.shader); - if (passIdx < 0) continue; - cmd.DrawRenderer(renderer, mat, subIdx, passIdx); - } - } - } - } } } \ No newline at end of file diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurMaskPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurMaskPass.cs deleted file mode 100644 index e50bf8af2..000000000 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurMaskPass.cs +++ /dev/null @@ -1,220 +0,0 @@ -// NiloToon Fur Mask Pass -// Renders fur shells to a dedicated mask buffer for fur area detection -// Separate from main fur rendering for cleaner architecture -// Based on NiloToonPrepassBufferRTPass pattern - -using System; -using UnityEngine; -using UnityEngine.Experimental.Rendering; -using UnityEngine.Rendering; -using UnityEngine.Rendering.RendererUtils; -#if UNITY_6000_0_OR_NEWER -using UnityEngine.Rendering.RenderGraphModule; -#endif -using UnityEngine.Rendering.Universal; - -namespace NiloToon.NiloToonURP -{ - public class NiloToonFurMaskPass : ScriptableRenderPass - { - static readonly ShaderTagId furShellMaskLightModeShaderTagId = new ShaderTagId("NiloToonFurShellMask"); - static readonly int FurMaskTexId = Shader.PropertyToID("_NiloToonFurMaskTex"); - - [Serializable] - public class Settings - { - [Tooltip("Create a mask buffer for fur area detection.\n" + - "This creates _NiloToonFurMaskTex which can be used for post-processing.\n\nDefault: ON")] - public bool Enabled = true; - } - - Settings settings; - RenderQueueRange renderQueueRange; - -#if UNITY_2022_2_OR_NEWER - RTHandle furMaskRTHColor; - RTHandle furMaskRTHDepth; -#else - RenderTargetHandle furMaskRTHandle; -#endif - - public NiloToonFurMaskPass(Settings settings) - { - this.settings = settings; - this.renderQueueRange = RenderQueueRange.all; - -#if !UNITY_2022_2_OR_NEWER - furMaskRTHandle.Init("_NiloToonFurMaskRT"); -#endif - - base.profilingSampler = new ProfilingSampler(nameof(NiloToonFurMaskPass)); - } - -#if UNITY_6000_0_OR_NEWER - [Obsolete] -#endif - public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) - { - if (!settings.Enabled) - return; - - var cameraData = renderingData.cameraData; - -#if UNITY_2022_2_OR_NEWER - // [color RTHandle's Descriptor] - same pattern as NiloToonPrepassBufferRTPass - var colorDesc = cameraData.cameraTargetDescriptor; - colorDesc.graphicsFormat = GraphicsFormat.R8G8B8A8_UNorm; - colorDesc.depthBufferBits = 0; - colorDesc.msaaSamples = 1; - - // [depth RTHandle's Descriptor] - create own depth buffer like PrepassBufferRTPass - var depthDesc = cameraData.cameraTargetDescriptor; - depthDesc.graphicsFormat = GraphicsFormat.None; // Depth only rendering - depthDesc.depthStencilFormat = cameraData.cameraTargetDescriptor.depthStencilFormat; - depthDesc.msaaSamples = 1; - - RenderingUtils.ReAllocateIfNeeded(ref furMaskRTHColor, colorDesc, name: "_NiloToonFurMaskColor"); - RenderingUtils.ReAllocateIfNeeded(ref furMaskRTHDepth, depthDesc, name: "_NiloToonFurMaskDepth"); - - // Set global RT - cmd.SetGlobalTexture(FurMaskTexId, furMaskRTHColor); - - // Configure target with own color and depth buffers - ConfigureTarget(furMaskRTHColor, furMaskRTHDepth); - ConfigureClear(ClearFlag.All, Color.black); -#else - var furMaskDesc = cameraData.cameraTargetDescriptor; - furMaskDesc.colorFormat = RenderTextureFormat.ARGB32; - furMaskDesc.depthStencilFormat = cameraData.cameraTargetDescriptor.depthStencilFormat; - furMaskDesc.msaaSamples = 1; - - cmd.GetTemporaryRT(furMaskRTHandle.id, furMaskDesc); - cmd.SetGlobalTexture(FurMaskTexId, furMaskRTHandle.Identifier()); - - ConfigureTarget(new RenderTargetIdentifier(furMaskRTHandle.Identifier(), 0, CubemapFace.Unknown, -1)); - ConfigureClear(ClearFlag.All, Color.black); -#endif - } - -#if UNITY_6000_0_OR_NEWER - [Obsolete] -#endif - public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) - { - if (!settings.Enabled) - return; - - // Never draw in Preview - Camera camera = renderingData.cameraData.camera; - if (camera.cameraType == CameraType.Preview) - return; - - var cmd = CommandBufferPool.Get(); - using (new ProfilingScope(cmd, base.profilingSampler)) - { - // Execute command buffer before DrawRenderers (frame debugger requirement) - context.ExecuteCommandBuffer(cmd); - cmd.Clear(); - - // Draw all fur shells with NiloToonFurShellMask pass - var filterSetting = new FilteringSettings(renderQueueRange); - var sortFlags = SortingCriteria.CommonTransparent; - var drawSettings = CreateDrawingSettings(furShellMaskLightModeShaderTagId, ref renderingData, sortFlags); - drawSettings.perObjectData = PerObjectData.None; - context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filterSetting); - } - - context.ExecuteCommandBuffer(cmd); - cmd.Clear(); - CommandBufferPool.Release(cmd); - } - - public override void OnCameraCleanup(CommandBuffer cmd) - { - // To Release a RTHandle, do it in ScriptableRendererFeature's Dispose(), don't do it in OnCameraCleanup(...) -#if !UNITY_2022_2_OR_NEWER - if (settings.Enabled) - { - cmd.ReleaseTemporaryRT(furMaskRTHandle.id); - } -#endif - } - -#if UNITY_2022_2_OR_NEWER - public void Dispose() - { - furMaskRTHColor?.Release(); - furMaskRTHDepth?.Release(); - } -#endif - -#if UNITY_6000_0_OR_NEWER - private class FurMaskPassData - { - public UniversalCameraData cameraData; - public TextureHandle colorTarget; - public TextureHandle depthTarget; - public RendererListHandle rendererList; - } - - public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) - { - if (!settings.Enabled) - return; - - var cameraData = frameData.Get(); - var resourceData = frameData.Get(); - var renderingData = frameData.Get(); - - // Skip Preview cameras - same check as Execute - if (cameraData.camera.cameraType == CameraType.Preview) - return; - - using (var builder = renderGraph.AddRasterRenderPass("NiloToon Fur Mask Buffer", out var passData, base.profilingSampler)) - { - passData.cameraData = cameraData; - - // Create render textures for RG - EXACT same descriptors as OnCameraSetup - var colorDesc = cameraData.cameraTargetDescriptor; - colorDesc.graphicsFormat = GraphicsFormat.R8G8B8A8_UNorm; - colorDesc.depthBufferBits = 0; - colorDesc.msaaSamples = 1; - - var depthDesc = cameraData.cameraTargetDescriptor; - depthDesc.graphicsFormat = GraphicsFormat.None; // Depth only rendering - depthDesc.depthStencilFormat = cameraData.cameraTargetDescriptor.depthStencilFormat; - depthDesc.msaaSamples = 1; - - passData.colorTarget = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorDesc, "_NiloToonFurMaskColor", false); - passData.depthTarget = UniversalRenderer.CreateRenderGraphTexture(renderGraph, depthDesc, "_NiloToonFurMaskDepth", false); - - // Create renderer list - EXACT same settings as Execute - var renderListDesc = new RendererListDesc(furShellMaskLightModeShaderTagId, renderingData.cullResults, cameraData.camera) - { - sortingCriteria = SortingCriteria.CommonTransparent, - renderQueueRange = renderQueueRange, - }; - passData.rendererList = renderGraph.CreateRendererList(renderListDesc); - - // Set up render targets - Match ConfigureTarget behavior - builder.SetRenderAttachment(passData.colorTarget, 0, AccessFlags.Write); - builder.SetRenderAttachmentDepth(passData.depthTarget, AccessFlags.Write); - - builder.UseRendererList(passData.rendererList); - - // Set global textures - Match cmd.SetGlobalTexture behavior - builder.SetGlobalTextureAfterPass(passData.colorTarget, FurMaskTexId); - - builder.SetRenderFunc((FurMaskPassData data, RasterGraphContext context) => - { - // Match ConfigureClear(ClearFlag.All, Color.black) behavior - context.cmd.ClearRenderTarget(RTClearFlags.All, Color.black, 1.0f, 0); - - // Match context.DrawRenderers behavior - context.cmd.DrawRendererList(data.rendererList); - }); - } - } -#endif - } -} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurMaskPass.cs.meta b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurMaskPass.cs.meta deleted file mode 100644 index 10d243597..000000000 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurMaskPass.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: d398264d435e9314bae19d3e5532f775 \ No newline at end of file diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurPass.cs new file mode 100644 index 000000000..41beb80e9 --- /dev/null +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurPass.cs @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// Fur rendering pass — draws lilToon-style barycentric fur shells. +// Two ShaderTagIds: depth prepass first, then color pass. +// Standalone/Editor only, and only when the current graphics device supports geometry shaders. +// Renderer feature toggle defaults OFF. + +using System; +using UnityEngine; +using UnityEngine.Rendering; +#if UNITY_6000_0_OR_NEWER +using UnityEngine.Rendering.RenderGraphModule; +#endif +using UnityEngine.Rendering.Universal; + +namespace NiloToon.NiloToonURP +{ + public class NiloToonFurPass : ScriptableRenderPass + { + [Serializable] + public class Settings + { + [Tooltip("Enable fur shell rendering for NiloToonCharacter materials that have Fur enabled.\n" + + "Standalone only. Has no effect on mobile platforms.\n\n" + + "Default: OFF")] + [OverrideDisplayName("Allow Render?")] + [Revertible] + public bool supportFur = false; + + [Tooltip("Render fur shells into the prepass buffer so fur silhouette edges are included in bloom/tonemapping character area detection and face mask.\n" + + "Without this, fur edges may be excluded from NiloToon post-processing effects.\n\n" + + "Default: ON")] + [DisableIf("supportFur", false)] + [OverrideDisplayName(" Draw in Nilo Prepass")] + [Revertible] + public bool furPrepassBuffer = true; + } + + static readonly ShaderTagId furDepthPrepassShaderTagId = new ShaderTagId("NiloToonFurDepthPrepass"); + static readonly ShaderTagId furColorShaderTagId = new ShaderTagId("NiloToonFur"); + + NiloToonRendererFeatureSettings allSettings; + Settings settings; + ProfilingSampler m_ProfilingSamplerFur; + + public NiloToonFurPass(NiloToonRendererFeatureSettings allSettings) + { + this.allSettings = allSettings; + this.settings = allSettings.furSettings; + m_ProfilingSamplerFur = new ProfilingSampler("NiloToonFurPass"); + } + + /// + /// Returns true when fur is active and fur prepass buffer rendering is enabled. + /// + public bool ShouldRenderFurPrepassBuffer() + { + return ShouldEnqueue() && settings.furPrepassBuffer; + } + + /// + /// Returns true only on standalone/editor platforms when fur support is enabled + /// and the current graphics device supports geometry shaders. + /// + public bool ShouldEnqueue() + { + if (!settings.supportFur) + return false; + +#if UNITY_STANDALONE || UNITY_EDITOR + return SystemInfo.supportsGeometryShaders; +#else + return false; +#endif + } + + //===================================================================== + // Legacy (pre-RenderGraph) path + //===================================================================== +#if !UNITY_6000_4_OR_NEWER +#if UNITY_6000_0_OR_NEWER + [Obsolete] +#endif + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + // do nothing + } + +#if UNITY_6000_0_OR_NEWER + [Obsolete] +#endif + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + if (!ShouldEnqueue()) + return; + + CommandBuffer cmd = CommandBufferPool.Get(); + using (new ProfilingScope(cmd, m_ProfilingSamplerFur)) + { + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + // Draw fur depth prepass first + DrawingSettings drawingSettingsDepth = CreateDrawingSettings(furDepthPrepassShaderTagId, ref renderingData, SortingCriteria.CommonOpaque); + FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.opaque); + NiloToonRenderingUtils.DrawRendererListOrRenderers(context, cmd, renderingData.cullResults, ref drawingSettingsDepth, ref filteringSettings); + + // Execute depth prepass before color pass + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + // Draw fur color pass + DrawingSettings drawingSettingsColor = CreateDrawingSettings(furColorShaderTagId, ref renderingData, SortingCriteria.CommonOpaque); + NiloToonRenderingUtils.DrawRendererListOrRenderers(context, cmd, renderingData.cullResults, ref drawingSettingsColor, ref filteringSettings); + } + + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + CommandBufferPool.Release(cmd); + } +#endif + + public override void OnCameraCleanup(CommandBuffer cmd) + { + // do nothing + } + + //===================================================================== + // RenderGraph path (Unity 6+) + //===================================================================== +#if UNITY_6000_0_OR_NEWER + class PassData + { + public RendererListHandle depthPrepassRendererListHandle; + public RendererListHandle colorRendererListHandle; + public bool shouldRender; + } + + public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) + { + string passName = "NiloToonFur(RG)"; + + using (var builder = renderGraph.AddRasterRenderPass(passName, out var passData)) + { + UniversalResourceData resourceData = frameData.Get(); + UniversalCameraData cameraData = frameData.Get(); + UniversalRenderingData renderingData = frameData.Get(); + UniversalLightData lightData = frameData.Get(); + + SortingCriteria sortFlags = SortingCriteria.CommonOpaque; + FilteringSettings filterSettings = new FilteringSettings(RenderQueueRange.opaque, ~0); + + // Depth prepass renderer list + DrawingSettings drawSettingsDepth = RenderingUtils.CreateDrawingSettings(furDepthPrepassShaderTagId, renderingData, cameraData, lightData, sortFlags); + var depthRendererListParams = new RendererListParams(renderingData.cullResults, drawSettingsDepth, filterSettings); + passData.depthPrepassRendererListHandle = renderGraph.CreateRendererList(depthRendererListParams); + + // Color pass renderer list + DrawingSettings drawSettingsColor = RenderingUtils.CreateDrawingSettings(furColorShaderTagId, renderingData, cameraData, lightData, sortFlags); + var colorRendererListParams = new RendererListParams(renderingData.cullResults, drawSettingsColor, filterSettings); + passData.colorRendererListHandle = renderGraph.CreateRendererList(colorRendererListParams); + + passData.shouldRender = ShouldEnqueue(); + + builder.UseRendererList(passData.depthPrepassRendererListHandle); + builder.UseRendererList(passData.colorRendererListHandle); + + if (resourceData.activeColorTexture.IsValid()) + builder.SetRenderAttachment(resourceData.activeColorTexture, 0); + if (resourceData.activeDepthTexture.IsValid()) + builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture, AccessFlags.Write); + + builder.AllowGlobalStateModification(true); + + builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecutePassRG(data, context)); + } + } + + static void ExecutePassRG(PassData data, RasterGraphContext context) + { + if (!data.shouldRender) + return; + + var cmd = context.cmd; + + // Draw depth prepass first, then color pass + cmd.DrawRendererList(data.depthPrepassRendererListHandle); + cmd.DrawRendererList(data.colorRendererListHandle); + } +#endif + } +} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurPass.cs.meta b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurPass.cs.meta new file mode 100644 index 000000000..20541f25d --- /dev/null +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurPass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be435eb8ed92e9e4fbe399429a11c1c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurShellPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurShellPass.cs deleted file mode 100644 index bedbd18d7..000000000 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurShellPass.cs +++ /dev/null @@ -1,115 +0,0 @@ -// NiloToon Fur Shell Pass -// Renders fur shell pass for materials with "NiloToonFurShell" LightMode tag -// Only handles fur rendering - mask buffer is handled by NiloToonFurMaskPass - -using System; -using UnityEngine; -using UnityEngine.Rendering; -#if UNITY_6000_0_OR_NEWER -using UnityEngine.Rendering.RenderGraphModule; -#endif -using UnityEngine.Rendering.Universal; - -namespace NiloToon.NiloToonURP -{ - public class NiloToonFurShellPass : ScriptableRenderPass - { - static readonly ShaderTagId furShellLightModeShaderTagId = new ShaderTagId("NiloToonFurShell"); - - [Serializable] - public class Settings - { - [Header("Fur Shell Settings")] - - [Tooltip("Enable to render fur shells.\n\nDefault: ON")] - public bool ShouldRenderFurShell = true; - - [Tooltip("When to render fur shells in the rendering pipeline.\n\nDefault: AfterRenderingSkybox + 1 (right after classic outline)")] - public RenderPassEvent renderTiming = RenderPassEvent.AfterRenderingSkybox + 1; - } - - Settings settings; - ProfilingSampler m_ProfilingSampler; - RenderQueueRange renderQueueRange; - - public NiloToonFurShellPass(Settings settings) - { - this.settings = settings; - m_ProfilingSampler = new ProfilingSampler("NiloToonFurShellPass"); - this.renderQueueRange = RenderQueueRange.all; - } - -#if UNITY_6000_0_OR_NEWER - [Obsolete] -#endif - public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) - { - if (!settings.ShouldRenderFurShell) - return; - - CommandBuffer cmd = CommandBufferPool.Get(); - - using (new ProfilingScope(cmd, m_ProfilingSampler)) - { - context.ExecuteCommandBuffer(cmd); - cmd.Clear(); - - DrawingSettings drawingSettings = CreateDrawingSettings( - furShellLightModeShaderTagId, - ref renderingData, - SortingCriteria.CommonTransparent - ); - - FilteringSettings filteringSettings = new FilteringSettings(renderQueueRange); - context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings); - } - - context.ExecuteCommandBuffer(cmd); - cmd.Clear(); - CommandBufferPool.Release(cmd); - } - -#if UNITY_6000_0_OR_NEWER - private class PassData - { - public RendererListHandle rendererListHandle; - } - - public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) - { - if (!settings.ShouldRenderFurShell) - return; - - UniversalRenderingData renderingData = frameData.Get(); - UniversalCameraData cameraData = frameData.Get(); - UniversalLightData lightData = frameData.Get(); - UniversalResourceData resourceData = frameData.Get(); - - using (var builder = renderGraph.AddRasterRenderPass("NiloToonFurShellPass", out var passData, m_ProfilingSampler)) - { - var drawingSettings = RenderingUtils.CreateDrawingSettings( - furShellLightModeShaderTagId, - renderingData, - cameraData, - lightData, - SortingCriteria.CommonTransparent - ); - - var filteringSettings = new FilteringSettings(renderQueueRange); - var renderListParams = new RendererListParams(renderingData.cullResults, drawingSettings, filteringSettings); - passData.rendererListHandle = renderGraph.CreateRendererList(renderListParams); - - builder.UseRendererList(passData.rendererListHandle); - - builder.SetRenderAttachment(resourceData.activeColorTexture, 0); - builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture); - - builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) => - { - rgContext.cmd.DrawRendererList(data.rendererListHandle); - }); - } - } -#endif - } -} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurShellPass.cs.meta b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurShellPass.cs.meta deleted file mode 100644 index 4954c697d..000000000 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonFurShellPass.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 6edb03bf5b2c68d4dbc8b39fac860935 \ No newline at end of file diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonPrepassBufferRTPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonPrepassBufferRTPass.cs index 75fdd4da1..0ebddad65 100644 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonPrepassBufferRTPass.cs +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonPrepassBufferRTPass.cs @@ -38,6 +38,13 @@ namespace NiloToon.NiloToonURP // Constants static readonly ShaderTagId shaderTagId = new ShaderTagId("NiloToonPrepassBuffer"); + static readonly ShaderTagId furPrepassBufferDepthShaderTagId = new ShaderTagId("NiloToonFurPrepassBufferDepth"); + static readonly ShaderTagId furPrepassBufferAlphaShaderTagId = new ShaderTagId("NiloToonFurPrepassBufferAlpha"); + static readonly int _NiloToonPrepassBufferTex_SID = Shader.PropertyToID("_NiloToonPrepassBufferTex"); + static readonly int _NiloToonPrepassBufferDepthTex_SID = Shader.PropertyToID("_NiloToonPrepassBufferDepthTex"); + + bool furEnabled; + public void SetFurEnabled(bool enabled) { furEnabled = enabled; } // Constructor(will not call every frame) public NiloToonPrepassBufferRTPass(NiloToonRendererFeatureSettings allSettings) @@ -50,6 +57,26 @@ namespace NiloToon.NiloToonURP base.profilingSampler = new ProfilingSampler(nameof(NiloToonPrepassBufferRTPass)); } + + /// + /// Declare depth input requirements so URP generates _CameraDepthTexture + /// (needed by this pass's occlusion test in the prepass fragment shader). + /// Called from AddRenderPasses each frame, before the pass is enqueued. + /// + public void ConfigureInputs(bool isDeferredRendering) + { + var input = ScriptableRenderPassInput.Depth; + // In deferred rendering, requesting Depth alone is not enough: + // URP generates _CameraDepthTexture from GBuffer, which runs during opaques + // and is too late for this prepass. Requesting Normal forces an early + // DepthNormalsOnly prepass, matching URP SSAO's workaround. + if (isDeferredRendering) + { + input |= ScriptableRenderPassInput.Normal; + } + ConfigureInput(input); + } + #if !UNITY_6000_4_OR_NEWER // This method is called before executing the render pass. // It can be used to configure render targets and their clear state. Also to create temporary render target textures. @@ -97,13 +124,14 @@ namespace NiloToon.NiloToonURP RenderingUtils.ReAllocateIfNeeded(ref prepassBufferRTHDepth, depthDesc, name: "_NiloToonPrepassBufferDepth"); //set global RT - cmd.SetGlobalTexture("_NiloToonPrepassBufferTex", prepassBufferRTHColor); - cmd.SetGlobalTexture("_NiloToonPrepassBufferDepthTex", prepassBufferRTHDepth); + cmd.SetGlobalTexture(_NiloToonPrepassBufferTex_SID, prepassBufferRTHColor); + cmd.SetGlobalTexture(_NiloToonPrepassBufferDepthTex_SID, prepassBufferRTHDepth); #else cmd.GetTemporaryRT(prepassBufferRTH.id, renderTextureDescriptor); //set global RT - cmd.SetGlobalTexture("_NiloToonPrepassBufferTex", prepassBufferRTH.Identifier()); + cmd.SetGlobalTexture(_NiloToonPrepassBufferTex_SID, prepassBufferRTH.Identifier()); + cmd.SetGlobalTexture(_NiloToonPrepassBufferDepthTex_SID, prepassBufferRTH.Identifier(), RenderTextureSubElement.Depth); #endif @@ -157,6 +185,21 @@ namespace NiloToon.NiloToonURP var drawSettings = CreateDrawingSettings(shaderTagId, ref renderingData, sortFlags); drawSettings.perObjectData = PerObjectData.None; context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filterSetting); + + // Draw fur shells into the prepass buffer so fur silhouettes are included + // by NiloToon bloom/tonemapping character area detection. + if (furEnabled) + { + var furFilterSetting = new FilteringSettings(RenderQueueRange.opaque); + + var furDepthDrawSettings = CreateDrawingSettings(furPrepassBufferDepthShaderTagId, ref renderingData, sortFlags); + furDepthDrawSettings.perObjectData = PerObjectData.None; + context.DrawRenderers(renderingData.cullResults, ref furDepthDrawSettings, ref furFilterSetting); + + var furAlphaDrawSettings = CreateDrawingSettings(furPrepassBufferAlphaShaderTagId, ref renderingData, sortFlags); + furAlphaDrawSettings.perObjectData = PerObjectData.None; + context.DrawRenderers(renderingData.cullResults, ref furAlphaDrawSettings, ref furFilterSetting); + } } // must write these line after using{} finished, to ensure profiler and frame debugger display correctness @@ -194,6 +237,9 @@ namespace NiloToon.NiloToonURP public TextureHandle colorTarget; public TextureHandle depthTarget; public RendererListHandle rendererList; + public RendererListHandle furDepthRendererList; + public RendererListHandle furAlphaRendererList; + public bool furEnabled; } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext) @@ -232,15 +278,38 @@ namespace NiloToon.NiloToonURP }; passData.rendererList = renderGraph.CreateRendererList(renderListDesc); + passData.furEnabled = furEnabled; + if (furEnabled) + { + var furDepthListDesc = new RendererListDesc(furPrepassBufferDepthShaderTagId, renderingData.cullResults, cameraData.camera) + { + sortingCriteria = cameraData.defaultOpaqueSortFlags, + renderQueueRange = RenderQueueRange.opaque, + }; + passData.furDepthRendererList = renderGraph.CreateRendererList(furDepthListDesc); + + var furAlphaListDesc = new RendererListDesc(furPrepassBufferAlphaShaderTagId, renderingData.cullResults, cameraData.camera) + { + sortingCriteria = cameraData.defaultOpaqueSortFlags, + renderQueueRange = RenderQueueRange.opaque, + }; + passData.furAlphaRendererList = renderGraph.CreateRendererList(furAlphaListDesc); + } + // Set up render targets - Match ConfigureTarget behavior builder.SetRenderAttachment(passData.colorTarget, 0, AccessFlags.Write); builder.SetRenderAttachmentDepth(passData.depthTarget, AccessFlags.Write); builder.UseRendererList(passData.rendererList); + if (furEnabled) + { + builder.UseRendererList(passData.furDepthRendererList); + builder.UseRendererList(passData.furAlphaRendererList); + } // Set global textures - Match cmd.SetGlobalTexture behavior - builder.SetGlobalTextureAfterPass(passData.colorTarget, Shader.PropertyToID("_NiloToonPrepassBufferTex")); - builder.SetGlobalTextureAfterPass(passData.depthTarget, Shader.PropertyToID("_NiloToonPrepassBufferDepthTex")); + builder.SetGlobalTextureAfterPass(passData.colorTarget, _NiloToonPrepassBufferTex_SID); + builder.SetGlobalTextureAfterPass(passData.depthTarget, _NiloToonPrepassBufferDepthTex_SID); builder.SetRenderFunc((PrepassBufferPassData data, RasterGraphContext context) => { @@ -249,9 +318,15 @@ namespace NiloToon.NiloToonURP // Match context.DrawRenderers behavior context.cmd.DrawRendererList(data.rendererList); + + if (data.furEnabled) + { + context.cmd.DrawRendererList(data.furDepthRendererList); + context.cmd.DrawRendererList(data.furAlphaRendererList); + } }); } } #endif } -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonSetToonParamPass.cs b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonSetToonParamPass.cs index ed3d8777a..9df9d4e00 100644 --- a/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonSetToonParamPass.cs +++ b/Assets/NiloToonURP/Runtime/RendererFeatures/Passes/NiloToonSetToonParamPass.cs @@ -177,7 +177,7 @@ namespace NiloToon.NiloToonURP NiloToonRendererFeatureSettings allSettings; // private field and public access - bool isDeferredRendering; + public bool isDeferredRendering { get; private set; } PropertyInfo actualRenderingMode_PropertyInfo; PropertyInfo useDepthPriming_PropertyInfo; Func actualRenderingMode_Getter; @@ -1292,4 +1292,4 @@ namespace NiloToon.NiloToonURP } #endif } -} \ No newline at end of file +} diff --git a/Assets/NiloToonURP/Runtime/Utility/NiloToonRenderingUtils.cs b/Assets/NiloToonURP/Runtime/Utility/NiloToonRenderingUtils.cs index de46676f8..4e7677dfc 100644 --- a/Assets/NiloToonURP/Runtime/Utility/NiloToonRenderingUtils.cs +++ b/Assets/NiloToonURP/Runtime/Utility/NiloToonRenderingUtils.cs @@ -1,6 +1,8 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; namespace NiloToon.NiloToonURP { @@ -48,5 +50,31 @@ namespace NiloToon.NiloToonURP return s_FullscreenMesh; } } + + public static void DrawRendererListOrRenderers( + ScriptableRenderContext context, + CommandBuffer cmd, + CullingResults cullResults, + ref DrawingSettings drawingSettings, + ref FilteringSettings filteringSettings) + { +#if UNITY_6000_0_OR_NEWER + var rendererListParams = new RendererListParams(cullResults, drawingSettings, filteringSettings); + var rendererList = context.CreateRendererList(ref rendererListParams); + cmd.DrawRendererList(rendererList); +#else + context.DrawRenderers(cullResults, ref drawingSettings, ref filteringSettings); +#endif + } + + public static void DrawRendererListOrRenderers( + ScriptableRenderContext context, + CommandBuffer cmd, + ref RenderingData renderingData, + ref DrawingSettings drawingSettings, + ref FilteringSettings filteringSettings) + { + DrawRendererListOrRenderers(context, cmd, renderingData.cullResults, ref drawingSettings, ref filteringSettings); + } } } diff --git a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo026-NightSoftBloom(NiloToonVolumePreset).asset b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo026-NightSoftBloom(NiloToonVolumePreset).asset index 62e541735..054ca6540 100644 --- a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo026-NightSoftBloom(NiloToonVolumePreset).asset +++ b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo026-NightSoftBloom(NiloToonVolumePreset).asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ece28191d975daa09e95357fa3906a5549421dde206cf8286b87bbf64d717e1 -size 29777 +oid sha256:5c1520b75cc21b6f857d71085d591cbd3d5283f033e80df87572d9b6fe916f77 +size 30969 diff --git a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo028-Concert005_StyleDark_ACES(NiloToonVolumePreset).asset b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo028-Concert005_StyleDark_ACES(NiloToonVolumePreset).asset index 06782613e..cbc7f2709 100644 --- a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo028-Concert005_StyleDark_ACES(NiloToonVolumePreset).asset +++ b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo028-Concert005_StyleDark_ACES(NiloToonVolumePreset).asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af757f50249d6c447ed1beda553cbffe5c31370ec00065bdf96a1a58812308fd -size 44450 +oid sha256:205885f8cef06b10b7941c5a3b9e4352043963fbf5e1bce01815ea1ae9476d6f +size 46361 diff --git a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo029-Concert006_StyleBright(NiloToonVolumePreset).asset b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo029-Concert006_StyleBright(NiloToonVolumePreset).asset index b70ce8e59..c3a40580c 100644 --- a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo029-Concert006_StyleBright(NiloToonVolumePreset).asset +++ b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo029-Concert006_StyleBright(NiloToonVolumePreset).asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c587e658fce38aeb87c483a16d3f2b399be4020fee9aca1f0572ecc99d45169f -size 20914 +oid sha256:030529ce5097e1f134f3ab2743f6c4fd68227a900f20e422280483397a05a2f4 +size 21747 diff --git a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo030-Concert007_StyleBright_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo030-Concert007_StyleBright_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset index d88acd305..e8348a2c3 100644 --- a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo030-Concert007_StyleBright_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset +++ b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo030-Concert007_StyleBright_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d708cb15315f8c1917185b7b71605adbda9456f1119e8595ce65e421bbae84b3 -size 51716 +oid sha256:6c76af8b8ae647cec960cee538c73fa8d690e211a965bdbaaf1101a08f732eda +size 53983 diff --git a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo031-Concert008_StyleDark_ACES_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo031-Concert008_StyleDark_ACES_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset index ffe1d3b4b..1319a0bfb 100644 --- a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo031-Concert008_StyleDark_ACES_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset +++ b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo031-Concert008_StyleDark_ACES_AutoLightDir_MotionBlur(NiloToonVolumePreset).asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a6454b73ed51a8d48ee6882767491ffd9cf8525fc66c28624c7108a356b9373 -size 51598 +oid sha256:fa6afe7add31537c5e99e018580780dfcc00aaad348613da93f35b9636cd9772 +size 53849 diff --git a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo033-Idol_SafeBright(NiloToonVolumePreset).asset b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo033-Idol_SafeBright(NiloToonVolumePreset).asset index 7ca17a943..74688fbdd 100644 --- a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo033-Idol_SafeBright(NiloToonVolumePreset).asset +++ b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo033-Idol_SafeBright(NiloToonVolumePreset).asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0da4390c67e11d6b9b9bf1a6ac08ab2d3afa546fd4d5ea7f006fee505a54f31f -size 22036 +oid sha256:3b4845fd85b8a5c2b81a1be28c79b0f06fe48ec2834ae4bb6d24a970459ca7e5 +size 22910 diff --git a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo035-ConcertDarkShadowHighContrast.asset b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo035-ConcertDarkShadowHighContrast.asset index 5cf85eb9a..d79ade549 100644 --- a/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo035-ConcertDarkShadowHighContrast.asset +++ b/Assets/NiloToonURP/Runtime/VolumePresetPicker/VolumeProfilePresets/Nilo035-ConcertDarkShadowHighContrast.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eae1a6359bd1bc4292635d2103e49147366c6c2972a1d7738aa850d262724c6e -size 16977 +oid sha256:265456ae813574ccd22c5e0f171797aa5ae4817c0cb0ad71c40c935dd9957e6e +size 17646 diff --git a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloAllUtilIncludes.hlsl b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloAllUtilIncludes.hlsl index f4a1de161..51da7ffa3 100644 --- a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloAllUtilIncludes.hlsl +++ b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloAllUtilIncludes.hlsl @@ -28,4 +28,5 @@ #include "NiloDitherFadeoutClipUtil.hlsl" #include "NiloShadows.hlsl" #include "NiloGlitter.hlsl" - +#include "NiloGenericRimLight3DUtil.hlsl" +#include "NiloFurUtil.hlsl" diff --git a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloFurUtil.hlsl b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloFurUtil.hlsl new file mode 100644 index 000000000..baa663388 --- /dev/null +++ b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloFurUtil.hlsl @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// Pure fur utility functions — no struct dependencies. +// Adapted from lilToon's fur implementation (lil_common_vert_fur.hlsl, lil_common_frag.hlsl). + +#pragma once + +//--------------------------------------------------------------------- +// Barycentric interpolation helper +//--------------------------------------------------------------------- +// Interpolate a value across 3 triangle vertices using barycentric weights. +// factor.x = weight for vertex A, factor.y = weight for B, factor.z = weight for C. +// Sum of factor components should be 1.0. +float NiloLerp3(float a, float b, float c, float3 f) { return a * f.x + b * f.y + c * f.z; } +float2 NiloLerp3(float2 a, float2 b, float2 c, float3 f) { return a * f.x + b * f.y + c * f.z; } +float3 NiloLerp3(float3 a, float3 b, float3 c, float3 f) { return a * f.x + b * f.y + c * f.z; } +float4 NiloLerp3(float4 a, float4 b, float4 c, float3 f) { return a * f.x + b * f.y + c * f.z; } +half NiloLerp3(half a, half b, half c, float3 f) { return a * f.x + b * f.y + c * f.z; } +half2 NiloLerp3(half2 a, half2 b, half2 c, float3 f) { return a * f.x + b * f.y + c * f.z; } +half3 NiloLerp3(half3 a, half3 b, half3 c, float3 f) { return a * f.x + b * f.y + c * f.z; } +half4 NiloLerp3(half4 a, half4 b, half4 c, float3 f) { return a * f.x + b * f.y + c * f.z; } + +//--------------------------------------------------------------------- +// Normal blending helper +// Matches lilToon lilBlendNormal(). +//--------------------------------------------------------------------- +float3 NiloBlendNormal(float3 dstNormal, float3 srcNormal) +{ + return float3(dstNormal.xy + srcNormal.xy, dstNormal.z * srcNormal.z); +} + +//--------------------------------------------------------------------- +// Compute fur extrusion vector in world space +// Adapted from lilToon lil_common_vert_fur.hlsl lines 166-200 +//--------------------------------------------------------------------- +// furVectorTS: tangent-space fur direction (xyz) — from _NiloFurVector.xyz +// furLength: world-space fur length — from _NiloFurLength +// furCutoutLength: depth-prepass length scale — from _NiloFurCutoutLength or 1 +// normalOS: object-space normal +// tangentOS: object-space tangent (xyz + w sign) +// gravity: gravity amount (0 = none, 1 = full) +// vertexColor: vertex color RGB (optional blend source) +// vc2fur: toggle for vertex color -> fur direction blend +// furVectorTexTS: tangent-space vector texture sample +// useFurVectorTex: toggle for vector texture blend +float3 NiloComputeFurVectorWS( + float3 furVectorTS, + float furLength, + float furCutoutLength, + float3 normalOS, + float4 tangentOS, + float gravity, + float3 vertexColor, + float vc2fur, + float3 furVectorTexTS, + float useFurVectorTex) +{ + // Build TBN in object space (same as lilToon) + float3 bitangentOS = normalize(cross(normalOS, tangentOS.xyz)) * (tangentOS.w * length(normalOS)); + float3x3 tbnOS = float3x3(tangentOS.xyz, bitangentOS, normalOS); + + // Start with base direction (ensure nonzero Z to avoid degenerate direction) + float3 furDir = furVectorTS + float3(0, 0, 0.001); + + // Optionally blend with vertex color (lilToon's _VertexColor2FurVector approach) + if (vc2fur > 0.5) + { + furDir = NiloBlendNormal(furDir, vertexColor); + } + + // Optional vector texture follows lilToon: blend in tangent space before length/gravity. + if (useFurVectorTex > 0.5) + { + furDir = NiloBlendNormal(furDir, furVectorTexTS); + } + + // Transform direction from tangent space to object space, then scale by length. + furDir = mul(normalize(furDir), tbnOS); + furDir *= furLength * furCutoutLength; + + // Transform to world space (direction only, no translation) + furDir = TransformObjectToWorldDir(furDir, false); + + // Apply gravity: pull down in world Y + float len = length(furDir); + furDir.y -= gravity * len; + + return furDir; +} + +//--------------------------------------------------------------------- +// Fur alpha — noise-based cutout per shell layer +// Adapted from lilToon's OVERRIDE_FUR / LIL_FUR_LAYER_ALPHA +//--------------------------------------------------------------------- +// furLayer: 0 = root (base mesh), 1 = tip (geometry shader sets this) +// rootOffset: shifts the cutout threshold toward roots (negative value, range [-1, 0]) +// furNoise: noise texture sample [0,1] +// furMask: mask texture sample [0,1] (1 = full fur, 0 = no fur) +// Color pass alpha — transparent mode (matches lilToon FurTwoPass COLOR pass, LIL_RENDER == 2). +// Smooth cubic falloff from root to tip. Alpha blending creates the soft fuzzy look. +// See lil_common_frag.hlsl lines 416-420 (LIL_FUR_LAYER_ALPHA transparent variant). +float NiloFurAlpha(float furLayer, float rootOffset, float furNoise, float furMask) +{ + float furLayerShift = furLayer - furLayer * rootOffset + rootOffset; + float furLayerAbs = abs(furLayerShift); + float furAlpha = saturate(furNoise - furLayerShift * furLayerAbs * furLayerAbs); + furAlpha *= furMask; + return furAlpha; +} + +// Depth prepass alpha — cutout mode for Nilo's full-toon fur prepass. +// Matches lilToon's FurTwoPass LIL_FUR_PRE path: +// - OVERRIDE_FUR computes the fourth-power + 0.25 alpha. +// - lil_pass_forward_fur.hlsl then hardens it with saturate(alpha * 5 - 2) +// before discarding zero alpha so the prepass writes only the cutout core. +// The separate color pass keeps NiloFurAlpha() smooth for the soft outer shell. +float NiloFurAlphaCutout(float furLayer, float rootOffset, float furNoise, float furMask) +{ + float furLayerShift = furLayer - furLayer * rootOffset + rootOffset; + float furLayerAbs = abs(furLayerShift); + float furAlpha = saturate(furNoise - furLayerShift * furLayerAbs * furLayerAbs * furLayerAbs + 0.25); + furAlpha *= furMask; + furAlpha = saturate(furAlpha * 5.0 - 2.0); + return furAlpha; +} + +//--------------------------------------------------------------------- +// Fur root ambient occlusion +// Adapted from lilToon's LIL_FUR_LAYER_AO +//--------------------------------------------------------------------- +// color: input lit color +// furLayer: 0 = root, 1 = tip +// furAO: AO intensity (0 = none, 1 = full darkening at roots) +half3 NiloApplyFurAO(half3 color, float furLayer, float furAO, float furLength) +{ + // lilToon formula: color *= saturate(1 - noise + noise * furLayer) * ao * 1.25 + 1 - ao + // Simplified: at root (furLayer=0), darkening = (1 - ao). At tip (furLayer=1), no darkening. + // Scale AO by fur length: when fur is very short (< 0.01), AO fades out to avoid + // visible dark lines on the surface that look like artifacts instead of depth. + float lengthScale = saturate(furLength / 0.015); // full AO at length >= 0.015, fades below + float scaledAO = furAO * lengthScale; + float aoFactor = lerp(1.0 - scaledAO, 1.0, furLayer); + return color * aoFactor; +} + +//--------------------------------------------------------------------- +// Fur rim fresnel — adds rim glow on outer shell edges +//--------------------------------------------------------------------- +// furLayer: 0 = root, 1 = tip +// normalWS: world-space normal +// viewDirWS: world-space view direction (pointing toward camera) +// rimColor: rim highlight color (RGB) +// fresnelPower: fresnel exponent +// antiLight: how much to reduce rim in lit areas (0 = no reduction) +// invLightingGray: grayscale inverse lighting, matching lilToon's fd.invLighting +half3 NiloFurRim(float furLayer, float3 normalWS, float3 viewDirWS, half4 rimColor, float fresnelPower, float antiLight, half invLightingGray) +{ + float fresnel = pow(saturate(1.0 - abs(dot(normalize(normalWS), viewDirWS))), fresnelPower); + float rimMask = furLayer * fresnel; + half3 rim = rimColor.rgb * rimMask * lerp(1.0, invLightingGray, antiLight); + return rim; +} diff --git a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloFurUtil.hlsl.meta b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloFurUtil.hlsl.meta new file mode 100644 index 000000000..9d2a51ecc --- /dev/null +++ b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloFurUtil.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 98b7828dbaf4fdb42b8f9eab6e61060e +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloGenericRimLight3DUtil.hlsl b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloGenericRimLight3DUtil.hlsl new file mode 100644 index 000000000..700c91e31 --- /dev/null +++ b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloGenericRimLight3DUtil.hlsl @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// For more information, visit -> https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample + +// #pragma once is a safe guard best practice in almost every .hlsl, +// doing this can make sure your .hlsl's user can include this .hlsl anywhere anytime without producing any multi include conflict +#pragma once + +half3 BlendNiloGenericRimLight3DColor(half3 dstCol, half3 srcCol, half srcA, uint blendMode) +{ + half3 add = dstCol + srcCol; + half3 mul = dstCol * srcCol; + half3 outCol = dstCol; + + if (blendMode == 0) outCol = srcCol; + else if (blendMode == 1) outCol = add; + else if (blendMode == 2) outCol = max(add - mul, dstCol); + else if (blendMode == 3) outCol = mul; + + return lerp(dstCol, outCol, srcA); +} + +half NiloGenericRimLight3DTooningScale(half value, half border, half blur) +{ + half borderMin = saturate(border - blur * 0.5); + half borderMax = saturate(border + blur * 0.5); + half denominator = max(0.0001, saturate(borderMax - borderMin + fwidth(value))); + return saturate((value - borderMin) / denominator); +} + +float3 GetNiloGenericRimLight3DCameraForwardWS() +{ + return normalize(-float3(UNITY_MATRIX_I_V[0][2], UNITY_MATRIX_I_V[1][2], UNITY_MATRIX_I_V[2][2])); +} + +half3 ApplyNiloGenericRimLight3D( + half3 dstColor, + half3 albedo, + half facing, + half3 normalWS_NoNormalMap, + half3 normalWS, + half3 viewDirectionWS, + half3 lightDirectionWS, + half3 lightColor, + half finalShadowArea, + half inShadow25PercentMul, + half4 colorTex, + half4 color, + half4 indirColor, + half colorAlpha, + half mainStrength, + half enableLighting, + half shadowMask, + half backfaceMask, + uint blendMode, + half dirStrength, + half dirRange, + half border, + half blur, + half indirRange, + half indirBorder, + half indirBlur, + half normalStrength, + half fresnelPower, + half vrParallaxStrength) +{ + half3 rimNormalWS = normalize(lerp(normalWS_NoNormalMap, normalWS, normalStrength)); + #if defined(USING_STEREO_MATRICES) + half3 rimViewDirectionWS = normalize(lerp(GetNiloGenericRimLight3DCameraForwardWS(), viewDirectionWS, vrParallaxStrength)); + #else + half3 rimViewDirectionWS = normalize(viewDirectionWS); + #endif + + half rim = pow(saturate(1.0 - abs(dot(rimNormalWS, rimViewDirectionWS))), fresnelPower); + rim = facing < (backfaceMask - 1.0) ? 0.0 : rim; + + half lightNormalRaw = dot(lightDirectionWS, rimNormalWS) * 0.5 + 0.5; + half dirDenominator = max(0.0001, 1.0 + dirRange); + half indirDenominator = max(0.0001, 1.0 + indirRange); + half lightNormalDir = saturate((lightNormalRaw + dirRange) / dirDenominator); + half lightNormalIndir = saturate((1.0 - lightNormalRaw + indirRange) / indirDenominator); + + half rimDir = lerp(rim, rim * lightNormalDir, dirStrength); + half rimIndir = rim * lightNormalIndir * dirStrength; + + rimDir = NiloGenericRimLight3DTooningScale(rimDir, border, blur); + rimIndir = NiloGenericRimLight3DTooningScale(rimIndir, indirBorder, indirBlur); + + half rimShadow = saturate(finalShadowArea * inShadow25PercentMul); + rimDir = lerp(rimDir, rimDir * rimShadow, shadowMask); + rimIndir = lerp(rimIndir, rimIndir * rimShadow, shadowMask); + + half4 rimColor = color * colorTex; + half4 rimIndirColor = indirColor * colorTex; + rimColor.a *= colorAlpha; + + rimColor.rgb = lerp(rimColor.rgb, rimColor.rgb * albedo, mainStrength); + + half3 rimLightMul = 1.0 - enableLighting + lightColor * enableLighting; + + dstColor = BlendNiloGenericRimLight3DColor(dstColor, rimColor.rgb * rimLightMul, rimDir * rimColor.a, blendMode); + dstColor = BlendNiloGenericRimLight3DColor(dstColor, rimIndirColor.rgb * rimLightMul, rimIndir * rimIndirColor.a, blendMode); + + return dstColor; +} diff --git a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloGenericRimLight3DUtil.hlsl.meta b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloGenericRimLight3DUtil.hlsl.meta new file mode 100644 index 000000000..8bd2f7a7c --- /dev/null +++ b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloGenericRimLight3DUtil.hlsl.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8c6d02e0f7de4c7a9d9443df2955a7d1 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloUVCalculateUtil.hlsl b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloUVCalculateUtil.hlsl index 233db9f84..f98bedc86 100644 --- a/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloUVCalculateUtil.hlsl +++ b/Assets/NiloToonURP/ShaderLibrary/NiloUtilityHLSL/NiloUVCalculateUtil.hlsl @@ -79,6 +79,25 @@ float2 CalcUV(float2 uv, float4 tilingOffset, float4 centerPivotScalePos, float return outuv; } +// Stereo-aware "head direction" for matcap UV stability under VR. +// Problem: in stereo perspective rendering, viewDirectionWS is per-eye (each eye's camera position), +// so matcap UV differs between eyes -> "swimming matcap" visual bug. +// Fix: in stereo perspective, use the midpoint of the two eye positions (HMD center) as the +// virtual camera position. This makes matcap UV consistent across both eyes. +// Non-stereo / orthographic: returns the fallback unchanged (URP's GetWorldSpaceNormalizeViewDir +// already handles these cases correctly). +half3 GetMatCapHeadDirectionWS(float3 positionWS, half3 fallbackViewDirectionWS) +{ +#if defined(USING_STEREO_MATRICES) + if (IsPerspectiveProjection()) + { + float3 midEye = (unity_StereoWorldSpaceCameraPos[0] + unity_StereoWorldSpaceCameraPos[1]) * 0.5; + return half3(normalize(midEye - positionWS)); + } +#endif + return fallbackViewDirectionWS; +} + // An improved method when compared to a simple "view space normal remap as uv", // it can reduce uv bad distortion when object is near the edge of the screen // https://twitter.com/bgolus/status/1487224443688554497 diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter.shader b/Assets/NiloToonURP/Shaders/NiloToonCharacter.shader index a6bfdf184..ccf01db67 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacter.shader +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter.shader @@ -367,6 +367,19 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Advanced] _BaseMapBrightness(" Brightness", Range(0,10)) = 1 + [Advanced] + [Title( HSV Gamma)] + _BaseMapHue(" Hue", Range(-0.5,0.5)) = 0 + [Advanced] + _BaseMapSaturation(" Saturation", Range(0,2)) = 1 + [Advanced] + _BaseMapValue(" Value", Range(0,2)) = 1 + [Advanced] + _BaseMapGamma(" Gamma", Range(0.01,2)) = 1 + [Advanced][SubToggle(,_BASEMAP_HSVG_MASK)]_UseBaseMapHSVGMask(" Use HSVG Mask?", Float) = 0 + [ShowIf(_UseBaseMapHSVGMask, Equal, 1)] + [Advanced] + [NoScaleOffset]_BaseMapHSVGMaskTex(" HSVG Mask", 2D) = "white" {} [Title(Built in RP Color (VRM))] [Tooltip(Enable this option if you want UniVRM Blend Shape Proxy...Blend Shape Clip...Material List...Color control still works in this shader.)] @@ -541,7 +554,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(. Front . Renders the front face of your geometry and culls the back face. This is the default setting.)] [Tooltip(. Back . Renders the back face of your geometry and culls the front face.)] [Tooltip(. Both . Renders both faces of the geometry, this is good for flat objects with single face polygon, like cloth and hair, where you might want both sides visible.)] - [SubEnum(_RenderFaceGroup,Front,2,Back,1,Both,0)]_Cull(" Lit pass", Float) = 2.0 + [SubEnum(_RenderFaceGroup,Front,2,Back,1,Both,0)]_Cull(" Lit pass", Float) = 0.0 [Advanced] [Tooltip(Use this dropdown to determine which sides of the outline geometry to render.)] @@ -937,6 +950,35 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(If you are seeing a wierd depth tex shadow on the neck, try adjust this value.)] [Advanced][Sub(_DepthTextureRimLightAndShadowGroup)]_FaceAreaCameraDepthTextureZWriteOffset("DepthTex ZWrite Offset", Range(0,0.1)) = 0.04 // minimum required is 0.04. (0.03 is still too small, mouth area may show unwanted shadow when viewed by side camera angle) + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // RimLight 3D + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + [Main(_GenericRimLight3DGroup,_GENERIC_RIMLIGHT3D)]_UseGenericRimLight3D("RimLight 3D", Float) = 0 + + [Title(_GenericRimLight3DGroup, Rim Light)] + [Tex(_GenericRimLight3DGroup,_GenericRimLight3DColor)]_GenericRimLight3DColorTex("Color / Mask", 2D) = "white" {} + [HideInInspector][HDR]_GenericRimLight3DColor("Color", Color) = (0.66,0.5,0.48,1) + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DAlpha("Alpha", Range(0,1)) = 1 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DMainStrength("Main Color Power", Range(0,1)) = 0 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DEnableLighting("Enable Lighting", Range(0,1)) = 1 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DShadowMask("Shadow Mask", Range(0,1)) = 0.5 + [SubToggle(_GenericRimLight3DGroup,_)]_GenericRimLight3DBackfaceMask("Backface Mask", Float) = 1 + [SubEnum(_GenericRimLight3DGroup,Normal,0,Add,1,Screen,2,Multiply,3)]_GenericRimLight3DBlendMode("Blending Mode", Float) = 1 + [Title(_GenericRimLight3DGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DDirStrength("Light direction strength", Range(0,1)) = 0 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DDirRange(" Direct light width", Range(-1,1)) = 0 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DBorder(" Border", Range(0,1)) = 0.5 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DBlur(" Blur", Range(0,1)) = 0.65 + [Title(_GenericRimLight3DGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DIndirRange(" Indirect light width", Range(-1,1)) = 0 + [HDR][Sub(_GenericRimLight3DGroup)]_GenericRimLight3DIndirColor(" Color", Color) = (1,1,1,1) + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DIndirBorder(" Border", Range(0,1)) = 0.5 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DIndirBlur(" Blur", Range(0,1)) = 0.1 + [Title(_GenericRimLight3DGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DNormalStrength("Normal Map Strength", Range(0,1)) = 1 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DFresnelPower("Fresnel Power", Range(0.01,50)) = 3.5 + [Sub(_GenericRimLight3DGroup)]_GenericRimLight3DVRParallaxStrength("VR Parallax Strength", Range(0,1)) = 1 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Shadow Color ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -944,39 +986,61 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(You can read the document pdf for solution if ugly random hue color artifact appears in shadow area)] [Main(_ShadowColorGroup,_)]_EnableShadowColor("Shadow Color", Float) = 1 + [Title(_ShadowColorGroup, Shadow Mode)] + [Tooltip(Default mode uses NiloToon shadow color settings.)] + [Tooltip(lilToon mode uses lilToon style shadow color settings to reproduce lilToon materials. Auto Convert selects this mode for lilToon sources, but either mode can be selected manually.)] + [KWEnum(_ShadowColorGroup,Default,_,lilToon,_SHADOW_MODE_LILTOON)]_ShadowColorMode("Mode", Float) = 0 + [Helpbox(Calculate the light independent shadow color from BaseMap, similar to using color adjustment layer in Photoshop to find out the shadow color.)] [Helpbox(Shadow color will only be displayed in shadow region.)] [Title(_ShadowColorGroup, Shadow Color Style)] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)][HDR]_SelfShadowTintColor("Tint Color", Color) = (1,1,1) + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_SelfShadowAreaHSVStrength("HSV Stregnth", Range(0,1)) = 1 [Helpbox(HSV requires texture compression equals High or None for Saturation Boost to work nicely.)] [Helpbox(If shadow color artifact appears, try to use a better texture compression or lower Saturation Boost)] // in this section, default values were set by the author's art experience, you can edit it freely if these don't work for your project + [ShowIf(_ShadowColorMode, Equal, 0)] [ShowIf(_SelfShadowAreaHSVStrength,Greater,0)] [Sub(_ShadowColorGroup)]_SelfShadowAreaHueOffset(" (H) Hue Offset", Range(-1,1)) = 0 + [ShowIf(_ShadowColorMode, Equal, 0)] [ShowIf(_SelfShadowAreaHSVStrength,Greater,0)] [Sub(_ShadowColorGroup)]_SelfShadowAreaSaturationBoost(" (S) Saturation Boost", Range(0,1)) = 0.2 // the default value is 0.5 in version <= NiloToon 0.16.7. Now it is 0.2 as a safer default to reduce the default hue artifact + [ShowIf(_ShadowColorMode, Equal, 0)] [ShowIf(_SelfShadowAreaHSVStrength,Greater,0)] [Sub(_ShadowColorGroup)]_SelfShadowAreaValueMul(" (V) Value Multiply", Range(0,1)) = 0.7 - + + [Tooltip(lilToon _ShadowMainStrength equivalent. In shadow area, multiply the shadow color by albedo once more to boost contrast.)] + [Tooltip(Produces an albedo squared effect. Dark albedo pixels become much darker, while light albedo pixels stay almost the same.)] + [Tooltip(Value 0 means off. Value 1 means full extra multiply.)] + [Tooltip(Triggered by any shadow source including NdotL self shadow, URP shadow map, NiloToon self shadow map, NiloToon depth diff shadow, and occlusion map. Independent from HSV settings.)] + [ShowIf(_ShadowColorMode, Equal, 0)] + [Sub(_ShadowColorGroup)]_SelfShadowAlbedoMulStrength("Contrast", Range(0,1)) = 0 + [Header(....................................................................................................................................................................................)] [AdvancedHeaderProperty] [Title(_ShadowColorGroup, Lit To Shadow Transition Area Style)] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_LitToShadowTransitionAreaIntensity("Intensity", Range(0,32)) = 1 [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [ShowIf(_LitToShadowTransitionAreaIntensity,Greater,0)] [Sub(_ShadowColorGroup)][HDR]_LitToShadowTransitionAreaTintColor(" Tint Color", Color) = (1,1,1) [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [ShowIf(_LitToShadowTransitionAreaIntensity,Greater,0)] [Sub(_ShadowColorGroup)]_LitToShadowTransitionAreaHueOffset(" (H) Hue Offset", Range(-1,1)) = 0.01 [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [ShowIf(_LitToShadowTransitionAreaIntensity,Greater,0)] [Sub(_ShadowColorGroup)]_LitToShadowTransitionAreaSaturationBoost(" (S) Saturation Boost", Range(0,1)) = 0.5 [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [ShowIf(_LitToShadowTransitionAreaIntensity,Greater,0)] [Sub(_ShadowColorGroup)]_LitToShadowTransitionAreaValueMul(" (V) Value Multiply", Range(0,1)) = 1 @@ -985,6 +1049,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Title(_ShadowColorGroup, Skin and Face Override)] [Tooltip(Select all materials of a character, then pick a Color Preset that looks good on your model.)] [AdvancedHeaderProperty] + [ShowIf(_ShadowColorMode, Equal, 0)] [Preset(_ShadowColorGroup,NiloToonCharacter_SkinFaceShadowColor_LWGUI_ShaderPropertyPreset)] _SkinFaceShadowColorPreset ("Color Preset", float) = 0 [Title(_ShadowColorGroup, . Skin Override)] @@ -993,12 +1058,16 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(. When this is 1, will use default settings, and use Skin Shadow Tint Color as shadow color.)] [Tooltip(. When this is 0, will not override skin shadow color.)] [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_OverrideBySkinShadowTintColor(" Strength", Range(0,1)) = 1 [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_SkinShadowTintColor(" Shadow Color", Color) = (1,0.8,0.8) // TODO: if we want to unify face & skin shadow color = try (1,0.856,0.856) [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_SkinShadowBrightness(" Brightness", Range(0,1)) = 1 [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_SkinShadowTintColor2(" Custom Tint", Color) = (1,1,1) [Title(_ShadowColorGroup, . Face Override)] @@ -1007,18 +1076,23 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(. When this is 1, will use default settings, and use Skin Shadow Tint Color as shadow color.)] [Tooltip(. When this is 0, will not override skin shadow color.)] [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_OverrideByFaceShadowTintColor(" Strength", Range(0,1)) = 1 [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_FaceShadowTintColor(" Shadow Color", Color) = (1,0.9,0.9) // TODO: if we want to unify face & skin shadow color = try (1,0.856,0.856) [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_FaceShadowBrightness(" Brightness", Range(0,1)) = 1 [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_FaceShadowTintColor2(" Custom Tint", Color) = (1,1,1) [Hidden] [Advanced] [Title(_ShadowColorGroup, Low Saturation Fallback Color)] [Tooltip(Alpha is intensity, default is OFF.)] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)][HDR]_LowSaturationFallbackColor("Low Saturation Fallback Color", Color) = (0.3764706,0.4141177,0.5019608,0) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1030,10 +1104,12 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Header(Shadow Color Map)] [Tooltip(If you dont like the shadow color of the above section,)] [Tooltip(you can modify the shadow color by a Shadow Color Map.)] + [ShowIf(_ShadowColorMode, Equal, 0)] [SubToggle(_ShadowColorGroup,_OVERRIDE_SHADOWCOLOR_BY_TEXTURE)]_UseOverrideShadowColorByTexture("Enable?", Float) = 0 [Advanced] [Title(_ShadowColorGroup, . Strength)] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_OverrideShadowColorByTexIntensity(" Intensity", Range(0,1)) = 1 [Advanced] @@ -1041,27 +1117,143 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(. Replace, In this mode, Shadow Color Map defines the final shadow color, overriding the BaseMap. Draw the desired shadow color incorporating BaseMap information directly onto this map.)] [Tooltip()] [Tooltip(. Multiply, In this mode, BaseMap is multiplied by Shadow Color Map, resulting the final shadow color. You draw only the shadow Tint Color in Shadow Color Map without any BaseMap information.)] + [ShowIf(_ShadowColorMode, Equal, 0)] [SubEnum(_ShadowColorGroup,Replace,0,Multiply,1)]_OverrideShadowColorByTexMode(" Mode", Float) = 0 [Advanced] [Title(_ShadowColorGroup, . Shadow Color Map)] [Tooltip(rgb is shadow color information, a is mask.)] + [ShowIf(_ShadowColorMode, Equal, 0)] [Tex(_ShadowColorGroup,_OverrideShadowColorTexTintColor)][NoScaleOffset]_OverrideShadowColorTex("Shadow Color Map", 2D) = "white" {} [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [HideInInspector][HDR]_OverrideShadowColorTexTintColor("", Color) = (1,1,1,1) [Advanced] [Tooltip(alpha of Shadow Color Map is a mask, but you can ignore the alpha by setting this to 1.)] + [ShowIf(_ShadowColorMode, Equal, 0)] [Sub(_ShadowColorGroup)]_OverrideShadowColorTexIgnoreAlphaChannel(" Ignore Alpha", Range(0,1)) = 0 [Advanced] [Title(_ShadowColorGroup, . Mask)] [Tooltip(white is apply override, black is do nothing.)] + [ShowIf(_ShadowColorMode, Equal, 0)] [Tex(_ShadowColorGroup,_OverrideShadowColorMaskMapChannelMask)][NoScaleOffset]_OverrideShadowColorMaskMap("Mask Map", 2D) = "white" {} [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [HideInInspector]_OverrideShadowColorMaskMapChannelMask("", Vector) = (0,1,0,0) // use G as default value because if input is rgb grayscale texture, g is 1 bit better [Advanced] + [ShowIf(_ShadowColorMode, Equal, 0)] [SubToggle(_ShadowColorGroup, _)]_OverrideShadowColorMaskMapInvertColor(" Invert?", Float) = 0 + [Header(....................................................................................................................................................................................)] + [Title(_ShadowColorGroup, lilToon Shadow Mask)] + [ShowIf(_ShadowColorMode, Equal, 1)] + [SubEnum(_ShadowColorGroup,Strength,0,Flat,1,SDF,2)]_lilShadowMaskType("Mask Type", Float) = 0 + [AdvancedHeaderProperty] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Tex(_ShadowColorGroup,_lilShadowStrength)][NoScaleOffset]_lilShadowStrengthMask("Mask & Strength", 2D) = "white" {} + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [HideInInspector]_lilShadowStrength("Strength", Range(0,1)) = 1 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowStrengthMaskLOD(" LOD", Range(0,1)) = 0 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [ShowIf(_lilShadowMaskType, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowFlatBorder(" Border", Range(-2,2)) = 1 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [ShowIf(_lilShadowMaskType, Greater, 0)] + [Sub(_ShadowColorGroup)]_lilShadowFlatBlur(" Blur / Blend Y Direction", Range(0.001,2)) = 1 + + [Header(....................................................................................................................................................................................)] + [Title(_ShadowColorGroup, lilToon Shadow Colors)] + [ShowIf(_ShadowColorMode, Equal, 1)] + [SubEnum(_ShadowColorGroup,Normal,0,LUT,1)]_lilShadowColorType("Color Type", Float) = 0 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Tex(_ShadowColorGroup,_lilShadowColor)][NoScaleOffset]_lilShadowColorTex("1st Color", 2D) = "black" {} + [HideInInspector]_lilShadowColor("1st Color", Color) = (0.82,0.76,0.85,1) + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowBorder(" Border", Range(0,1)) = 0.5 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowBlur(" Blur", Range(0,1)) = 0.1 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowNormalStrength(" Normal Map Strength", Range(0,1)) = 1 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowReceive(" Receive Shadow", Range(0,1)) = 0 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Tex(_ShadowColorGroup,_lilShadow2ndColor)][NoScaleOffset]_lilShadow2ndColorTex("2nd Color", 2D) = "black" {} + [HideInInspector]_lilShadow2ndColor("2nd Color", Color) = (0.68,0.66,0.79,1) + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow2ndBorder(" Border", Range(0,1)) = 0.15 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow2ndBlur(" Blur", Range(0,1)) = 0.1 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow2ndNormalStrength(" Normal Map Strength", Range(0,1)) = 1 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow2ndReceive(" Receive Shadow", Range(0,1)) = 0 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Tex(_ShadowColorGroup,_lilShadow3rdColor)][NoScaleOffset]_lilShadow3rdColorTex("3rd Color", 2D) = "black" {} + [HideInInspector]_lilShadow3rdColor("3rd Color", Color) = (0,0,0,0) + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow3rdBorder(" Border", Range(0,1)) = 0.25 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow3rdBlur(" Blur", Range(0,1)) = 0.1 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow3rdNormalStrength(" Normal Map Strength", Range(0,1)) = 1 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadow3rdReceive(" Receive Shadow", Range(0,1)) = 0 + + [Header(....................................................................................................................................................................................)] + [Title(_ShadowColorGroup, lilToon Shadow Common)] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowBorderColor("Border Color", Color) = (1,0.1,0,1) + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowBorderRange("Border Range", Range(0,1)) = 0.08 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowMainStrength("Contrast", Range(0,1)) = 0 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowEnvStrength("Environment strength on shadow color", Range(0,1)) = 0 + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilAAStrength("AA Shading", Range(0,1)) = 1 + + [Header(....................................................................................................................................................................................)] + [Title(_ShadowColorGroup, lilToon Shadow Maps)] + [AdvancedHeaderProperty] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Tex(_ShadowColorGroup)][NoScaleOffset]_lilShadowBlurMask("Blur Mask", 2D) = "white" {} + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowBlurMaskLOD(" LOD", Range(0,1)) = 0 + [AdvancedHeaderProperty] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Tex(_ShadowColorGroup)][NoScaleOffset]_lilShadowBorderMask("AO Map", 2D) = "white" {} + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowBorderMaskLOD(" LOD", Range(0,1)) = 0 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [SubToggle(_ShadowColorGroup, _)]_lilShadowPostAO(" Ignore border properties", Float) = 0 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowAO1Min(" 1st Min", Range(-0.01,1.01)) = 0 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowAO1Max(" 1st Max", Range(-0.01,1.01)) = 1 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowAO2Min(" 2nd Min", Range(-0.01,1.01)) = 0 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowAO2Max(" 2nd Max", Range(-0.01,1.01)) = 1 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowAO3Min(" 3rd Min", Range(-0.01,1.01)) = 0 + [Advanced] + [ShowIf(_ShadowColorMode, Equal, 1)] + [Sub(_ShadowColorGroup)]_lilShadowAO3Max(" 3rd Max", Range(-0.01,1.01)) = 1 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Lighting Style ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1076,18 +1268,39 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Helpbox(Controls the shape,softness,intensity of local NdotL shadow (not shadowmap))] [Helpbox()] [Helpbox(If the default values does not fit your target style, you can try another Preset)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Preset(_LightingStyleGroup,NiloToonCharacter_LightingStyleDirectionalLight_LWGUI_ShaderPropertyPreset)] _LightingStyleDirectionalLightRenderFacePreset ("Preset", float) = 0 [Tooltip(Offsets Main light NdotL mid point.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleGroup)]_CelShadeMidPoint("Mid Point", Range(-1,1)) = 0 [Tooltip(Controls the blending range(softness) between Lit and Shadow area.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleGroup)]_CelShadeSoftness("Softness", Range(0.001,1)) = 0.05 // avoid 0 [Title(_LightingStyleGroup,Main Light Shadow remove)] [Tooltip(Increase this a bit can produce fake SSS, or fake indirect light.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleGroup)]_MainLightIgnoreCelShade("Remove Shadow", Range(0,1)) = 0 [Title(_LightingStyleGroup,Main Light Shading Normal)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleGroup)]_MainLightSkinDiffuseNormalMapStrength("NormalMap strength (Skin)", Range(0,1)) = 1 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleGroup)]_MainLightNonSkinDiffuseNormalMapStrength("NormalMap strength (Non-Skin)", Range(0,1)) = 1 [Title(_LightingStyleGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] @@ -1123,11 +1336,24 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Helpbox(Override Lighting Style for Face.)] [Title(_LightingStyleFaceOverrideGroup, Main light Override for IsFace area)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubToggle(_LightingStyleFaceOverrideGroup,_)]_OverrideCelShadeParamForFaceArea("Override?", Float) = 1 // in this section, default values were set by the author's art experience, you can edit it freely if these don't work for your project + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleFaceOverrideGroup)]_CelShadeMidPointForFaceArea(" Mid Point", Range(-1,1)) = -0.3 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleFaceOverrideGroup)]_CelShadeSoftnessForFaceArea(" Softness", Range(0.001,1)) = 0.15 // avoid 0 [Tooltip(Increase this a bit can produce fake SSS, or fake indirect light.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_LightingStyleFaceOverrideGroup)]_MainLightIgnoreCelShadeForFaceArea(" Remove shadow", Range(0,1)) = 0.0 // default 0 to make face and body brightness in shadow similar [Title(_LightingStyleFaceOverrideGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] @@ -2558,6 +2784,78 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(Select the render faces that you want to show this layer.)] [SubEnum(_BaseMapStackingLayer10Group,Both,0,Front,2,Back,1)]_BaseMapStackingLayer10ApplytoFaces("Show in which faces?", Float) = 0 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + [Title(Generic MatCap)] + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + [ShowIf(_UIDisplayMode, GEqual, 100)] + [Tooltip(Useful for replacing material visual to any target matcap texture)] + [Main(_GenericMatCap1Group,_GENERIC_MATCAP1)]_UseGenericMatCap1("MatCap1", Float) = 0 + + [Title(_GenericMatCap1Group, MatCap Map)] + [Tex(_GenericMatCap1Group,_GenericMatCap1Color)]_GenericMatCap1Map("Map", 2D) = "white" {} + [HideInInspector][HDR]_GenericMatCap1Color("Color", Color) = (1,1,1,1) + + [Title(_GenericMatCap1Group, Intensity and Blend)] + [Sub(_GenericMatCap1Group)]_GenericMatCap1Blend("Blend", Range(0,1)) = 1 + [Sub(_GenericMatCap1Group)]_GenericMatCap1MainStrength("Main Color Power", Range(0,1)) = 0 + [Sub(_GenericMatCap1Group)]_GenericMatCap1NormalStrength("Normal Map Strength", Range(0,1)) = 1 + [SubEnum(_GenericMatCap1Group,Normal,0,Add,1,Screen,2,Multiply,3)]_GenericMatCap1BlendMode("Blend Mode", Float) = 1 + + [Title(_GenericMatCap1Group, UV)] + [Sub(_GenericMatCap1Group)]_GenericMatCap1BlendUV1("Blend UV1 (XY)", Vector) = (0,0,0,0) + [SubToggle(_GenericMatCap1Group,_)]_GenericMatCap1ZRotCancel("Z-axis rotation cancellation", Float) = 1 + [SubToggle(_GenericMatCap1Group,_)]_GenericMatCap1Perspective("Fix Perspective", Float) = 1 + [Advanced][Sub(_GenericMatCap1Group)]_GenericMatCap1VRParallaxStrength("VR Parallax Strength", Range(0,1)) = 1 + + [Title(_GenericMatCap1Group, Mask)] + [Tex(_GenericMatCap1Group)]_GenericMatCap1Mask("Mask", 2D) = "white" {} + [Sub(_GenericMatCap1Group)]_GenericMatCap1EnableLighting("Enable Lighting", Range(0,1)) = 1 + [Sub(_GenericMatCap1Group)]_GenericMatCap1ShadowMask("Shadow Mask", Range(0,1)) = 0 + [SubToggle(_GenericMatCap1Group,_)]_GenericMatCap1BackfaceMask("Backface Mask", Float) = 0 + [Advanced][Sub(_GenericMatCap1Group)]_GenericMatCap1Lod("Blur", Range(0,10)) = 0 + [SubToggle(_GenericMatCap1Group,_)]_GenericMatCap1ApplyTransparency("Apply Transparency", Float) = 1 + + [Title(_GenericMatCap1Group, Custom Normal)] + [SubToggle(_GenericMatCap1Group,_GENERIC_MATCAP1_CUSTOM_NORMAL)]_UseGenericMatCap1CustomNormal("Custom normal map", Float) = 0 + [ShowIf(_UseGenericMatCap1CustomNormal, Equal, 1)][Tex(_GenericMatCap1Group)]_GenericMatCap1BumpMap("Normal Map", 2D) = "bump" {} + [ShowIf(_UseGenericMatCap1CustomNormal, Equal, 1)][Sub(_GenericMatCap1Group)]_GenericMatCap1BumpScale("Scale", Range(-10,10)) = 1 + + [Main(_GenericMatCap2Group,_GENERIC_MATCAP2)]_UseGenericMatCap2("MatCap2", Float) = 0 + + [Title(_GenericMatCap2Group, MatCap Map)] + [Tex(_GenericMatCap2Group,_GenericMatCap2Color)]_GenericMatCap2Map("Map", 2D) = "white" {} + [HideInInspector][HDR]_GenericMatCap2Color("Color", Color) = (1,1,1,1) + + [Title(_GenericMatCap2Group, Intensity and Blend)] + [Sub(_GenericMatCap2Group)]_GenericMatCap2Blend("Blend", Range(0,1)) = 1 + [Sub(_GenericMatCap2Group)]_GenericMatCap2MainStrength("Main Color Power", Range(0,1)) = 0 + [Sub(_GenericMatCap2Group)]_GenericMatCap2NormalStrength("Normal Map Strength", Range(0,1)) = 1 + [SubEnum(_GenericMatCap2Group,Normal,0,Add,1,Screen,2,Multiply,3)]_GenericMatCap2BlendMode("Blend Mode", Float) = 1 + + [Title(_GenericMatCap2Group, UV)] + [Sub(_GenericMatCap2Group)]_GenericMatCap2BlendUV1("Blend UV1 (XY)", Vector) = (0,0,0,0) + [SubToggle(_GenericMatCap2Group,_)]_GenericMatCap2ZRotCancel("Z-axis rotation cancellation", Float) = 1 + [SubToggle(_GenericMatCap2Group,_)]_GenericMatCap2Perspective("Fix Perspective", Float) = 1 + [Advanced][Sub(_GenericMatCap2Group)]_GenericMatCap2VRParallaxStrength("VR Parallax Strength", Range(0,1)) = 1 + + [Title(_GenericMatCap2Group, Mask)] + [Tex(_GenericMatCap2Group)]_GenericMatCap2Mask("Mask", 2D) = "white" {} + [Sub(_GenericMatCap2Group)]_GenericMatCap2EnableLighting("Enable Lighting", Range(0,1)) = 1 + [Sub(_GenericMatCap2Group)]_GenericMatCap2ShadowMask("Shadow Mask", Range(0,1)) = 0 + [SubToggle(_GenericMatCap2Group,_)]_GenericMatCap2BackfaceMask("Backface Mask", Float) = 0 + [Advanced][Sub(_GenericMatCap2Group)]_GenericMatCap2Lod("Blur", Range(0,10)) = 0 + [SubToggle(_GenericMatCap2Group,_)]_GenericMatCap2ApplyTransparency("Apply Transparency", Float) = 1 + + [Title(_GenericMatCap2Group, Custom Normal)] + [SubToggle(_GenericMatCap2Group,_GENERIC_MATCAP2_CUSTOM_NORMAL)]_UseGenericMatCap2CustomNormal("Custom normal map", Float) = 0 + [ShowIf(_UseGenericMatCap2CustomNormal, Equal, 1)][Tex(_GenericMatCap2Group)]_GenericMatCap2BumpMap("Normal Map", 2D) = "bump" {} + [ShowIf(_UseGenericMatCap2CustomNormal, Equal, 1)][Sub(_GenericMatCap2Group)]_GenericMatCap2BumpScale("Scale", Range(-10,10)) = 1 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2569,8 +2867,6 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MatCap (Color Replace) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [ShowIf(_UIDisplayMode, GEqual, 100)] - [Tooltip(Useful for replacing material visual to any target matcap texture)] [Main(_MatCapAlphaBlendGroup,_MATCAP_BLEND)]_UseMatCapAlphaBlend("MatCap (Color Replace)", Float) = 0 [Title(_MatCapAlphaBlendGroup,Preset)] @@ -2756,6 +3052,10 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [ShowIf(_UIDisplayMode, GEqual, 300)] [Tooltip(Similar to UTS2 Shading Grade Map.)] [Tooltip(Offset Lighting Style _CelShadeMidPoint by a texture.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Main(_ShadingGradeMapGroup,_SHADING_GRADEMAP)]_UseShadingGradeMap("Shading Grade Map", Float) = 0 [Title(_ShadingGradeMapGroup,Define)] @@ -2764,19 +3064,44 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(. Darker is less shadow)] [Tooltip(. Brighter is more shadow)] [Tooltip(Default is linearGrey.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Tex(_ShadingGradeMapGroup,_ShadingGradeMapChannelMask)][NoScaleOffset]_ShadingGradeMap("Shading Grade Map ", 2D) = "linearGrey" {} + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] [HideInInspector]_ShadingGradeMapChannelMask("", Vector) = (0,1,0,0) // default accept g channel + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubToggle(_ShadingGradeMapGroup, _)]_ShadingGradeMapInvertColor(" Invert?", Float) = 0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [MinMaxSlider(_ShadingGradeMapGroup,_ShadingGradeMapRemapStart,_ShadingGradeMapRemapEnd)]_ShadingGradeMapRemapMinMaxSlider(" Remap", Range(0.0,1.0)) = 1.0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] [HideInInspector]_ShadingGradeMapRemapStart("", Range(0.0,1.0)) = 0.0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] [HideInInspector]_ShadingGradeMapRemapEnd("", Range(0.0,1.0)) = 1.0 [Title(_ShadingGradeMapGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] [Title(_ShadingGradeMapGroup,Apply)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_ShadingGradeMapGroup)]_ShadingGradeMapStrength("Strength", Range(0.0, 1.0)) = 1.0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_ShadingGradeMapGroup)]_ShadingGradeMapApplyRange("Apply Range", Range(0.0,4.0)) = 1.0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_ShadingGradeMapGroup)]_ShadingGradeMapMidPointOffset("Mid-Point Offset", Range(-1,1)) = 0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2933,12 +3258,20 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(User can provide a gradient texture to define artist controlled shadow result of 0 to 90 degrees light rotation.)] [Tooltip(Only effective if IsFace is on.)] [Tooltip(Only correct if character script FaceForwardDirection and FaceUpDirection are both correctly set up.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Main(_FaceShadowGradientMapGroup,_FACE_SHADOW_GRADIENTMAP)]_UseFaceShadowGradientMap("Face Shadow Gradient Map (SDF)", Float) = 0 [Title(_FaceShadowGradientMapGroup, Preset)] [Tooltip(For Default preset, Gradient Map is expected to assign FaceShadowGradientMap textures included in the NiloToonURP package.)] [Tooltip()] [Tooltip(For Genshin Impact preset, Gradient Map is expected to assign Genshin Impact FaceLightmap textures, which is not included in the NiloToonURP package.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Preset(_FaceShadowGradientMapGroup, NiloToonCharacter_FaceShadowGradientMapPreset_LWGUI_ShaderPropertyPreset)] _FaceShadowGradientMapPreset ("Preset", float) = 0 [Title(_FaceShadowGradientMapGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] @@ -2954,64 +3287,128 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Tooltip(Default is R channel because R8 format texture is expected.)] [Tooltip(It is expected the nose is at the center of the texture,)] [Tooltip(if it is not, you need to edit Face mid line uv.x to match the nose position on the texture.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Tex(_FaceShadowGradientMapGroup,_FaceShadowGradientMapChannel)][NoScaleOffset]_FaceShadowGradientMap("Gradient Map", 2D) = "gray" {} + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] [HideInInspector]_FaceShadowGradientMapChannel("", Vector) = (1,0,0,0) + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubEnum(_FaceShadowGradientMapGroup,UV0,0,UV1,1,UV2,2,UV3,3)]_FaceShadowGradientMapUVIndex(" UV", Float) = 0 [Tooltip(Shader will assume Gradient Map face is centered at the middle of the texture.)] [Tooltip(If it is not, you need to edit this value to match the center of the face.)] [Tooltip(For example, if the face is placed at the left side of the texture, set this number to around 0.25, where this value matches the uv x position of the nose.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_FaceShadowGradientMapGroup)]_FaceShadowGradientMapFaceMidPoint(" Face mid line uv.x", Range(0,1)) = 0.5 [Tooltip(Enable to invert the sampled value in shader.)] [Tooltip(In most cases, it should not be turned on unless the texture color is inverted already.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubToggle(_FaceShadowGradientMapGroup, _)]_FaceShadowGradientMapInvertColor(" Invert Color?", Float) = 0 [Tooltip(Enable to flip the whole Gradient Map horizontally along Face mid line uv.x.)] [Tooltip(Usually, if you see bright color at the right side of the face texture, disable this toggle.)] [Tooltip(Usually, if you see bright color at the left side of the face texture, enable this toggle.)] [Tooltip(But it all depends on how the uv is, so you should rotate the main light to see if enabling this is good or not.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubToggle(_FaceShadowGradientMapGroup, _)]_FaceShadowGradientMapUVxInvert(" Mirror L/R?", Float) = 1 [Title(_FaceShadowGradientMapGroup,UV Scale(XY) Pos(ZW))] [Tooltip(A more intuitive way to fit the map on the face(edit UV) compared to the UV Tiling Offset method below.)] [Tooltip(The Scale is using texture center as pivot.)] [Tooltip(The Pos is having an opposite direction compared to Offset, which should be more intuitive when editing.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_FaceShadowGradientMapGroup)]_FaceShadowGradientMapUVCenterPivotScalePos("", Vector) = (1,1,0,0) [Title(_FaceShadowGradientMapGroup,UV Tiling(XY) Offset(ZW))] [Tooltip(A more simple way to edit UV.)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_FaceShadowGradientMapGroup)]_FaceShadowGradientMapUVScaleOffset("", Vector) = (1,1,0,0) [Title(_FaceShadowGradientMapGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] [Title(_FaceShadowGradientMapGroup, Intensity)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_FaceShadowGradientMapGroup)]_FaceShadowGradientIntensity("Intensity", Range(0,1)) = 1 [Title(_FaceShadowGradientMapGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] [Title(_FaceShadowGradientMapGroup, Style)] [Tooltip(A higher value will delay the appear of shadow, usually it is 0 to 0.1)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_FaceShadowGradientMapGroup)]_FaceShadowGradientOffset("Offset", Range(-1,1)) = 0.1 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_FaceShadowGradientMapGroup)]_FaceShadowGradientResultSoftness("Softness", Range(0,1)) = 0.005 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [MinMaxSlider(_FaceShadowGradientMapGroup,_FaceShadowGradientThresholdMin,_FaceShadowGradientThresholdMax)]_FaceShadowGradientThresholdMinMax("Clamp", Range(0.0,1.0)) = 1.0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] [HideInInspector]_FaceShadowGradientThresholdMin("", Range(0.0,1.0)) = 0.0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] [HideInInspector]_FaceShadowGradientThresholdMax("", Range(0.0,1.0)) = 1.0 [Title(_FaceShadowGradientMapGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] [Title(_FaceShadowGradientMapGroup, Remove default shadow)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Sub(_FaceShadowGradientMapGroup)]_IgnoreDefaultMainLightFaceShadow("Remove default Shadow", Range(0,1)) = 1 [Title(_FaceShadowGradientMapGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] [Title(_FaceShadowGradientMapGroup, Mask)] [Tooltip((Use 1 channel) (White is full shadow, Black is hide shadow) (Default white))] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip()] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [Tex(_FaceShadowGradientMapGroup,_FaceShadowGradientMaskMapChannel)][NoScaleOffset]_FaceShadowGradientMaskMap("Mask Map ", 2D) = "white" {} + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] [HideInInspector]_FaceShadowGradientMaskMapChannel("", Vector) = (0,1,0,0) // use G as default value because if input is rgb grayscale texture, g is 1 bit better + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubEnum(_FaceShadowGradientMapGroup,UV0,0,UV1,1,UV2,2,UV3,3)]_FaceShadowGradientMaskMapUVIndex(" UV", Float) = 0 + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubToggle(_FaceShadowGradientMapGroup, _)]_FaceShadowGradientMaskMapInvertColor(" Invert?", Float) = 0 [Title(_FaceShadowGradientMapGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] [Title(_FaceShadowGradientMapGroup, Debug)] + [ActiveIf(_ShadowColorMode, Equal, 0)] + [ActiveIf(Or, _EnableShadowColor, Equal, 0)] + [Tooltip(Ignored when lilToon Shadow Color is enabled. lilToon controls the shadow area.)] [SubToggle(_FaceShadowGradientMapGroup, _)]_DebugFaceShadowGradientMap("Debug?", Float) = 0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -3439,9 +3836,18 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Title(_EnvironmentReflectionGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] + [Title(_EnvironmentReflectionGroup, Override Cubemap)] + [SubToggle(_EnvironmentReflectionGroup, _ENVIRONMENTREFLECTIONS_OVERRIDE_CUBEMAP)]_EnvironmentReflectionOverrideCubemapOn("Override Cubemap", Float) = 0 + [ActiveIf(_EnvironmentReflectionOverrideCubemapOn, Equal, 1)] + [Tooltip(For correct roughness, set the cubemap Convolution Type to Specular in its import settings.)] + [Sub(_EnvironmentReflectionGroup)][NoScaleOffset]_EnvironmentReflectionOverrideCubemap(" Cubemap", Cube) = "" {} + + [Title(_EnvironmentReflectionGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] + [Title(_EnvironmentReflectionGroup,Color and Brightness)] [Sub(_EnvironmentReflectionGroup)]_EnvironmentReflectionBrightness("Brightness", Range(0,128)) = 1 [Sub(_EnvironmentReflectionGroup)][HDR]_EnvironmentReflectionColor("Color", Color) = (1,1,1) + [Sub(_EnvironmentReflectionGroup)][NoScaleOffset]_EnvironmentReflectionColorMaskMap("Color / Mask Map", 2D) = "white" {} [Sub(_EnvironmentReflectionGroup)]_EnvironmentReflectionTintAlbedo("Tint Albedo", Range(0,1)) = 1 [Title(_EnvironmentReflectionGroup, ........................................................................................................................................................................................................................................................................................................................................................................)] @@ -3478,6 +3884,44 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Title(_EnvironmentReflectionGroup, Front and Back Face)] [SubEnum(_EnvironmentReflectionGroup,Both,0,Front,2,Back,1)]_EnvironmentReflectionApplytoFaces("Show in which faces?", Float) = 0 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Generic Reflection + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + [Main(_GenericReflectionGroup,_GENERIC_REFLECTION)]_UseGenericReflection("Generic Reflection", Float) = 0 + + [Title(_GenericReflectionGroup, Smoothness)] + [Sub(_GenericReflectionGroup)]_GenericReflectionSmoothness("Smoothness", Range(0,1)) = 1 + [Tex(_GenericReflectionGroup)]_GenericReflectionSmoothnessMap("Smoothness", 2D) = "white" {} + [Sub(_GenericReflectionGroup)]_GenericReflectionGSAAStrength("GSAA", Range(0,1)) = 0 + + [Title(_GenericReflectionGroup, Specular)] + [SubToggle(_GenericReflectionGroup,_)]_GenericReflectionApplySpecular("Apply Specular", Float) = 1 + [SubToggle(_GenericReflectionGroup,_)]_GenericReflectionApplySpecularFA("Multi Light Specular", Float) = 1 + [SubToggle(_GenericReflectionGroup,_)]_GenericReflectionSpecularToon("Specular Toon", Float) = 1 + [Sub(_GenericReflectionGroup)]_GenericReflectionSpecularNormalStrength("Specular Normal Strength", Range(0,1)) = 1 + [Sub(_GenericReflectionGroup)]_GenericReflectionSpecularBorder("Specular Border", Range(0,1)) = 0.5 + [Sub(_GenericReflectionGroup)]_GenericReflectionSpecularBlur("Specular Blur", Range(0,1)) = 0 + + [Title(_GenericReflectionGroup, Cubemap)] + [SubToggle(_GenericReflectionGroup,_)]_GenericReflectionApplyReflection("Apply Reflection", Float) = 0 + [Sub(_GenericReflectionGroup)][NoScaleOffset]_GenericReflectionCubemap("Cubemap", Cube) = "black" {} + [Sub(_GenericReflectionGroup)][HDR]_GenericReflectionCubeColor("Cubemap Color", Color) = (0,0,0,1) + [SubToggle(_GenericReflectionGroup,_)]_GenericReflectionCubeOverride("Override Cubemap", Float) = 0 + [Sub(_GenericReflectionGroup)]_GenericReflectionCubeEnableLighting("Enable Lighting", Range(0,1)) = 1 + + [Title(_GenericReflectionGroup, Color and Mask)] + [Tex(_GenericReflectionGroup,_GenericReflectionColor)]_GenericReflectionColorMaskMap("Color / Mask", 2D) = "white" {} + [HideInInspector][HDR]_GenericReflectionColor("Color", Color) = (1,1,1,1) + [Sub(_GenericReflectionGroup)]_GenericReflectionBlend("Blend", Range(0,1)) = 1 + [SubEnum(_GenericReflectionGroup,Normal,0,Add,1,Screen,2,Multiply,3)]_GenericReflectionBlendMode("Blend Mode", Float) = 1 + [SubToggle(_GenericReflectionGroup,_)]_GenericReflectionApplyTransparency("Apply Transparency", Float) = 1 + + [Title(_GenericReflectionGroup, lilToon BRDF)] + [Sub(_GenericReflectionGroup)]_GenericReflectionReflectance("Reflectance", Range(0,1)) = 0.04 + [Tex(_GenericReflectionGroup)]_GenericReflectionMetallicMap("Metallic Map", 2D) = "white" {} + [Sub(_GenericReflectionGroup)]_GenericReflectionMetallic("Metallic", Range(0,1)) = 0 + [Sub(_GenericReflectionGroup)]_GenericReflectionNormalStrength("Normal Strength", Range(0,1)) = 1 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Kajiya-Kay Specular (hair) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -3492,6 +3936,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [Title(_KAJIYAKAY_SPECULAR, Color)] [Sub(_KAJIYAKAY_SPECULAR)]_HairStrandSpecularOverallIntensity("Intensity", Float) = 1 [Sub(_KAJIYAKAY_SPECULAR)]_HairStrandSpecularMixWithBaseMapColor("Multiply BaseMap", Range(0,1)) = 0.5 + [Sub(_KAJIYAKAY_SPECULAR)]_HairStrandSpecularShowInShadowArea("ShowInShadowArea", Range(0,1)) = 0.1 [Title(_KAJIYAKAY_SPECULAR, Color Tint by texture)] [SubToggle(_KAJIYAKAY_SPECULAR,_KAJIYAKAY_SPECULAR_TEX_TINT)]_UseHairStrandSpecularTintMap("Enable?", Float) = 0 @@ -3628,6 +4073,75 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" [HideInInspector]_EmissionMaskMapRemapStart("", Range(0.0,1.0)) = 0.0 [HideInInspector]_EmissionMaskMapRemapEnd("", Range(0.0,1.0)) = 1.0 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + [Title(Fur)] + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + [PassSwitch(NiloToonFurDepthPrepass,NiloToonFur,NiloToonFurPrepassBufferDepth,NiloToonFurPrepassBufferAlpha)] + [Main(_FurGroup, _NILOTOON_FUR)]_EnableFur("Fur (Standalone Only)", Float) = 0 + + [Preset(_FurGroup, NiloToonCharacter_FurPreset_LWGUI_ShaderPropertyPreset)] _FurPreset ("Preset", float) = 0 + [Tooltip(Global fur strength multiplier. Scales fur length. 0 hides fur, 1 is full. Not affected by preset.)] + [Sub(_FurGroup)]_NiloFurStrength("Strength", Range(0,2)) = 1 + + [Title(_FurGroup, ................................................................................................................................................................................................................)] + [Tooltip(Optional normal map to add per pixel variation to fur direction. Right slider is scale.)] + [Tex(_FurGroup, _NiloFurVectorScale)][NoScaleOffset]_NiloFurVectorTex("Normal Map", 2D) = "bump" {} + [HideInInspector]_NiloFurVectorScale("Normal Map Scale", Range(-10,10)) = 1 + [Tooltip(Per vertex fur length mask. White is full length, black is zero length.)] + [Tex(_FurGroup)][NoScaleOffset]_NiloFurLengthMask("Length Mask", 2D) = "white" {} + + [Tooltip(XYZ is tangent space fur direction.)] + [Sub(_FurGroup)]_NiloFurVector("Vector", Vector) = (0.0, 0.0, 1.0, 1.0) + [Tooltip(Fur strand length in world space units.)] + [Sub(_FurGroup)]_NiloFurLength("Length", Float) = 0.02 + [Tooltip(Controls the length of visible fur strands via alpha cutout. Lower values mean shorter visible fur.)] + [Sub(_FurGroup)]_NiloFurCutoutLength("Length (Cutout)", Float) = 0.8 + [Tooltip(Blend vertex color RGB into fur direction. Enable if vertex color encodes fur flow.)] + [SubToggle(_FurGroup,_)]_VertexColor2FurVector("VertexColor -> Vector", Float) = 0 + [Tooltip(How much gravity pulls fur downward. 0 is no gravity, 1 is full gravity.)] + [Sub(_FurGroup)]_NiloFurGravity("Gravity", Range(0,1)) = 0.25 + [Tooltip(Adds randomness to fur strand directions per triangle. 0 is uniform, higher is more random.)] + [Sub(_FurGroup)]_NiloFurRandomize("Randomize", Float) = 0.0 + [Tooltip(Culling mode for fur shell passes only. Body culling continues to use the Lit pass _Cull setting.)] + [SubEnum(_FurGroup,Off,0,Front,1,Back,2)]_NiloFurCull("Fur Cull", Float) = 0.0 + + [Title(_FurGroup, ................................................................................................................................................................................................................)] + [Tooltip(Tileable noise texture that defines fur strand shapes.)] + [Tex(_FurGroup)][NoScaleOffset]_NiloFurNoiseTex("Noise", 2D) = "white" {} + [Tooltip(UV tiling for fur noise texture. Higher values mean smaller, denser noise pattern.)] + [Sub(_FurGroup)]_NiloFurNoiseTiling("Noise Tiling", Vector) = (1,1,0,0) + [Tooltip(Mask texture that controls where fur appears. White is full fur, black is no fur.)] + [Tex(_FurGroup)][NoScaleOffset]_NiloFurMask("Alpha Mask", 2D) = "white" {} + [Tooltip(Adds occlusion at fur root, producing more shadow through NiloToon lighting.)] + [Sub(_FurGroup)]_NiloFurOcclusionShadowAO("AO (occlusion shadow)", Range(0,1)) = 0.0 + [Tooltip(Directly darkens fur color at root, same as lilToon fur AO.)] + [Sub(_FurGroup)]_NiloFurColorDarkenAO("AO (color darken)", Range(0,1)) = 0.0 + + [Title(_FurGroup, ................................................................................................................................................................................................................)] + [Tooltip(Number of fur shell layers per triangle. More layers means denser fur but higher GPU cost.)] + [Tooltip(Limited to 1 or 2 due to D3D11 geometry shader output size limit.)] + [Sub(_FurGroup)]_NiloFurLayerNum("Layer Counts", Range(1,2)) = 2 + [Tooltip(Shifts the alpha cutout threshold toward roots. 0 is default, negative values reveal more of the root.)] + [Sub(_FurGroup)]_NiloFurRootOffset("Root Width", Range(-1,0)) = 0.0 + + [Title(_FurGroup, ................................................................................................................................................................................................................)] + [Title(_FurGroup, Rim Light)] + [Tooltip(Color and intensity of the fur rim fresnel effect.)] + [Sub(_FurGroup)]_NiloFurRimColor("Color", Color) = (0,0,0,1) + [Tooltip(Fresnel power for fur rim effect. Higher values make the rim thinner.)] + [Sub(_FurGroup)]_NiloFurRimFresnelPower("Fresnel Power", Range(0.01,50)) = 3.0 + [Tooltip(How much to reduce fur rim in lit areas. 0 is no reduction, 1 is full reduction.)] + [Sub(_FurGroup)]_NiloFurRimAntiLight("Anti Light", Range(0,1)) = 0.5 + + [Title(_FurGroup, ................................................................................................................................................................................................................)] + [Title(_FurGroup, Masking)] + [Tooltip(Show fur on face and skin areas. Default off because fur on face and skin usually looks wrong.)] + [SubToggle(_FurGroup,_)]_NiloFurShowOnSkinFace("Show on Skin/Face", Float) = 0 + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4148,6 +4662,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" #pragma shader_feature_local_fragment _BASEMAP_STACKING_LAYER8 #pragma shader_feature_local_fragment _BASEMAP_STACKING_LAYER9 #pragma shader_feature_local_fragment _BASEMAP_STACKING_LAYER10 + #pragma shader_feature_local_fragment _BASEMAP_HSVG_MASK // can be strip by user in NiloToonAllInOneRendererFeature's stripping setting - NiloToonShaderStrippingSettingSO #pragma multi_compile _ _NILOTOON_FORCE_MINIMUM_SHADER @@ -4280,6 +4795,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" #pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_TEX_TINT // added by NiloToon #pragma shader_feature_local_fragment _NILOGLITTER #pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS // URP ComplexLit.shader use _ENVIRONMENTREFLECTIONS_OFF to save a keyword, here we use an inverted keyword since it is default off + #pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OVERRIDE_CUBEMAP //#pragma shader_feature_local_fragment _SPECULAR_SETUP // ignored by NiloToon // ------------------------------------- @@ -4298,6 +4814,12 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" #pragma shader_feature_local_fragment _MATCAP_BLEND #pragma shader_feature_local_fragment _MATCAP_ADD #pragma shader_feature_local_fragment _MATCAP_OCCLUSION + #pragma shader_feature_local_fragment _GENERIC_MATCAP1 + #pragma shader_feature_local_fragment _GENERIC_MATCAP2 + #pragma shader_feature_local _GENERIC_MATCAP1_CUSTOM_NORMAL + #pragma shader_feature_local _GENERIC_MATCAP2_CUSTOM_NORMAL + #pragma shader_feature_local_fragment _GENERIC_RIMLIGHT3D + #pragma shader_feature_local_fragment _GENERIC_REFLECTION #pragma shader_feature_local_fragment _RAMP_LIGHTING #pragma shader_feature_local_fragment _RAMP_LIGHTING_SAMPLE_UVY_TEX @@ -4315,6 +4837,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" #pragma shader_feature_local_fragment _SCREENSPACE_OUTLINE_V2 #pragma shader_feature_local_fragment _OVERRIDE_SHADOWCOLOR_BY_TEXTURE + #pragma shader_feature_local_fragment _SHADOW_MODE_LILTOON #pragma shader_feature_local_fragment _OVERRIDE_OUTLINECOLOR_BY_TEXTURE // we still need this if ForwardLit pass want to produce outline color @@ -4327,6 +4850,8 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" #pragma shader_feature_local_fragment _FACE_SHADOW_GRADIENTMAP #pragma shader_feature_local_fragment _FACE_3D_RIMLIGHT_AND_SHADOW + #pragma shader_feature_local _NILOTOON_FUR + // ------------------------------------- // NiloToon keywords (multi_compile) // ------------------------------------- @@ -4583,10 +5108,15 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" #pragma shader_feature_local _ZOFFSETMAP #pragma shader_feature_local_fragment _MATCAP_BLEND + #pragma shader_feature_local_fragment _GENERIC_RIMLIGHT3D #pragma shader_feature_local_fragment _SHADING_GRADEMAP // needs to affect outline color + #pragma shader_feature_local_fragment _SHADOW_MODE_LILTOON + #pragma shader_feature_local_fragment _OVERRIDE_OUTLINECOLOR_BY_TEXTURE + + #pragma shader_feature_local _NILOTOON_FUR // ------------------------------------- // Material keywords (NiloToon specific multi_compile) @@ -5147,10 +5677,16 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" ColorMask R // URP13.1.8 or later changed from 0 to R, we will follow it Cull[_Cull] - // Let user fully control the 2nd-8th bit of stencil buffer per material, + // Keep user stencil out of DepthOnly so _CameraDepthTexture still contains the real hair depth. + // In the common eyebrow-over-hair setup, eyebrow writes stencil and hair reads it in color pass. + // If the same stencil also cuts hair in depth passes, the eyebrow area becomes a hole in hair depth: + // nearby hair pixels can pick up an artificial depth edge and show unwanted RimLight 2D, + // while face pixels under the eyebrow no longer see hair as the occluder, so hair Shadow 2D disappears. + /* + // Let user fully control the 2nd-8th bit of stencil buffer per material, // but leaving the 1st bit for NiloToon to write "Character + Classic Outline" area // https://docs.unity3d.com/Manual/SL-Stencil.html - Stencil + Stencil { Ref [_StencilRef] // user fully control ReadMask 127 // 01111111 (only allow 2nd-8th bit for user fully control) @@ -5158,6 +5694,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" Comp [_StencilComp] // user fully control Pass [_StencilPass] // user fully control } + */ HLSLPROGRAM @@ -5263,10 +5800,16 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" //ColorMask R // we NEED to write PackNormalOctRectEncode()'s result rg color data into _CameraNormalTexture color buffer, so don't write ColorMask R - // Let user fully control the 2nd-8th bit of stencil buffer per material, + // Keep user stencil out of DepthNormalsOnly so camera depth/normal prepass data still matches the real hair geometry. + // In the common eyebrow-over-hair setup, eyebrow writes stencil and hair reads it in color pass. + // If the same stencil also cuts hair in depth/normal passes, the eyebrow area becomes a hole in hair depth: + // nearby hair pixels can pick up an artificial depth edge and show unwanted RimLight 2D, + // while face pixels under the eyebrow no longer see hair as the occluder, so hair Shadow 2D disappears. + /* + // Let user fully control the 2nd-8th bit of stencil buffer per material, // but leaving the 1st bit for NiloToon to write "Character + Classic Outline" area // https://docs.unity3d.com/Manual/SL-Stencil.html - Stencil + Stencil { Ref [_StencilRef] // user fully control ReadMask 127 // 01111111 (only allow 2nd-8th bit for user fully control) @@ -5274,6 +5817,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" Comp [_StencilComp] // user fully control Pass [_StencilPass] // user fully control } + */ HLSLPROGRAM @@ -5373,10 +5917,15 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" Cull [_Cull] // NiloToon added: _Cull doesn't exist in the offical ComplexLit.shader - // Let user fully control the 2nd-8th bit of stencil buffer per material, + // Keep user stencil out of MotionVectors so temporal consumers see motion for the real hair geometry. + // In the common eyebrow-over-hair setup, eyebrow is only composited over hair in color pass. + // If stencil also removes hair from motion data while depth still contains hair, TAA, motion blur, + // and upscalers can reproject from missing/incorrect motion vectors around the eyebrow area. + /* + // Let user fully control the 2nd-8th bit of stencil buffer per material, // but leaving the 1st bit for NiloToon to write "Character + Classic Outline" area // https://docs.unity3d.com/Manual/SL-Stencil.html - Stencil + Stencil { Ref [_StencilRef] // user fully control ReadMask 127 // 01111111 (only allow 2nd-8th bit for user fully control) @@ -5384,6 +5933,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" Comp [_StencilComp] // user fully control Pass [_StencilPass] // user fully control } + */ HLSLPROGRAM //#pragma shader_feature_local _ALPHATEST_ON // already declared in shared HLSL section @@ -5507,10 +6057,14 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" //ColorMask 0 // we NEED to draw rgba data into color buffer, so don't write ColorMask 0! Cull [_Cull] - // Let user fully control the 2nd-8th bit of stencil buffer per material, + // Keep user stencil out of NiloToonPrepassBuffer so NiloToon data buffers match the real hair geometry. + // This pass relies on _CameraDepthTexture and feeds character-area/prepass-driven effects. + // If eyebrow stencil cuts hair here, those effects see a data hole even though hair depth still exists. + /* + // Let user fully control the 2nd-8th bit of stencil buffer per material, // but leaving the 1st bit for NiloToon to write "Character + Classic Outline" area // https://docs.unity3d.com/Manual/SL-Stencil.html - Stencil + Stencil { Ref [_StencilRef] // user fully control ReadMask 127 // 01111111 (only allow 2nd-8th bit for user fully control) @@ -5518,6 +6072,7 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" Comp [_StencilComp] // user fully control Pass [_StencilPass] // user fully control } + */ HLSLPROGRAM @@ -5559,6 +6114,248 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character" ENDHLSL } + + // [Fur Prepass Buffer Depth (Standalone Only)] + // Renders fur shell geometry into _NiloToonPrepassBufferRT with cutout alpha (ZWrite On). + Pass + { + Name "FurPrepassBufferDepth" + Tags { "LightMode" = "NiloToonFurPrepassBufferDepth" } + + ZWrite On + ZTest LEqual + Cull [_NiloFurCull] + + HLSLPROGRAM + + #pragma target 4.0 + #pragma vertex VertexShaderAllWork + #pragma require geometry + #pragma geometry FurShellGeom + #pragma fragment FurNiloToonPrepassBufferColorOutput + + #pragma shader_feature_local _NILOTOON_FUR + #pragma shader_feature_local _NILOTOON_FUR_VECTORTEX + #pragma shader_feature_local_vertex _OUTLINEWIDTHMAP + #pragma shader_feature_local _ISFACE + #pragma shader_feature_local _FACE_MASK_ON + #pragma multi_compile_local_fragment _ _NILOTOON_DITHER_FADEOUT + + #define NiloToonFurPrepassBufferPass 1 + #define NiloToonFurPrepassBufferDepthPass 1 + + #include "NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl" + #include "NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl" + + ENDHLSL + } + + // [Fur Prepass Buffer Alpha (Standalone Only)] + // Renders soft outer fur shells into _NiloToonPrepassBufferRT with alpha blending. + Pass + { + Name "FurPrepassBufferAlpha" + Tags { "LightMode" = "NiloToonFurPrepassBufferAlpha" } + + Blend SrcAlpha OneMinusSrcAlpha + ZWrite Off + ZTest LEqual + Cull [_NiloFurCull] + + HLSLPROGRAM + + #pragma target 4.0 + #pragma vertex VertexShaderAllWork + #pragma require geometry + #pragma geometry FurShellGeom + #pragma fragment FurNiloToonPrepassBufferColorOutput + + #pragma shader_feature_local _NILOTOON_FUR + #pragma shader_feature_local _NILOTOON_FUR_VECTORTEX + #pragma shader_feature_local_vertex _OUTLINEWIDTHMAP + #pragma shader_feature_local _ISFACE + #pragma shader_feature_local _FACE_MASK_ON + #pragma multi_compile_local_fragment _ _NILOTOON_DITHER_FADEOUT + + #define NiloToonFurPrepassBufferPass 1 + + #include "NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl" + #include "NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl" + + ENDHLSL + } + + // [Fur Depth Pre-pass (Standalone Only)] + // lilToon FurTwoPass depth/color prepass equivalent. + Pass + { + Name "FurDepthPrepass" + Tags { "LightMode" = "NiloToonFurDepthPrepass" } + + Blend One Zero, One OneMinusSrcAlpha + ZWrite On + Cull [_NiloFurCull] + ZTest [_ZTest] + AlphaToMask On + + HLSLPROGRAM + + #pragma target 4.0 + #pragma vertex VertexShaderAllWork + #pragma require geometry + #pragma geometry FurShellGeom + #pragma fragment FragmentShaderAllWork + + #pragma shader_feature_local _NILOTOON_FUR + #pragma shader_feature_local _NILOTOON_FUR_VECTORTEX + #pragma shader_feature_local _NORMALMAP + #pragma shader_feature_local_fragment _RECEIVE_URP_SHADOW + #pragma shader_feature_local _ISFACE + #pragma shader_feature_local _FACE_MASK_ON + #pragma shader_feature_local_fragment _SKIN_MASK_ON + #pragma shader_feature_local_fragment _RAMP_LIGHTING + #pragma shader_feature_local_fragment _RAMP_LIGHTING_SAMPLE_UVY_TEX + #pragma shader_feature_local_fragment _SHADING_GRADEMAP + #pragma shader_feature_local_fragment _OVERRIDE_SHADOWCOLOR_BY_TEXTURE + #pragma shader_feature_local_fragment _SHADOW_MODE_LILTOON + #pragma shader_feature_local_fragment _NILOTOON_SELFSHADOW_INTENSITY_MAP + #pragma shader_feature_local_fragment _FACE_SHADOW_GRADIENTMAP + + #pragma multi_compile_fragment _ _NILOTOON_RECEIVE_URP_SHADOWMAPPING + #pragma multi_compile_fragment _ _NILOTOON_RECEIVE_SELF_SHADOW + #pragma multi_compile_local_fragment _ _NILOTOON_DITHER_FADEOUT + #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN + #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS + #if UNITY_VERSION >= 60010000 + #pragma dynamic_branch _ FOG_LINEAR FOG_EXP FOG_EXP2 + #else + #pragma multi_compile_fog + #endif + + #define NiloToonFurPass 1 + #define NiloToonFurDepthPrepassPass 1 + + #include "NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl" + #include "NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl" + + ENDHLSL + } + + // [Fur Color Pass (Standalone Only)] + // Renders fur shells with full toon lighting and alpha blending. + Pass + { + Name "Fur" + Tags { "LightMode" = "NiloToonFur" } + + Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha + ZWrite Off + Cull [_NiloFurCull] + ColorMask [_ColorMask] + ZTest [_ZTest] + + HLSLPROGRAM + + #pragma target 4.0 + #pragma vertex VertexShaderAllWork + #pragma require geometry + #pragma geometry FurShellGeom + #pragma fragment FragmentShaderAllWork + + #pragma shader_feature_local _NILOTOON_FUR + #pragma shader_feature_local _NILOTOON_FUR_VECTORTEX + + #pragma shader_feature_local _NORMALMAP + #pragma shader_feature_local _PARALLAXMAP + #pragma shader_feature_local_fragment _RECEIVE_URP_SHADOW + #pragma shader_feature_local _DETAIL + #pragma shader_feature_local_fragment _EMISSION + #pragma shader_feature_local_fragment _EMISSION_ANIM_TINT_RAMPMAP + #pragma shader_feature_local_fragment _SMOOTHNESSMAP + #pragma shader_feature_local_fragment _OCCLUSIONMAP + #pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS + #pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_TEX_TINT + #pragma shader_feature_local_fragment _NILOGLITTER + #pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS + + #pragma shader_feature_local _ISFACE + #pragma shader_feature_local _FACE_MASK_ON + #pragma shader_feature_local_fragment _SKIN_MASK_ON + #pragma shader_feature_local _ZOFFSETMAP + #pragma shader_feature_local_fragment _MATCAP_BLEND + #pragma shader_feature_local_fragment _MATCAP_ADD + #pragma shader_feature_local_fragment _MATCAP_OCCLUSION + #pragma shader_feature_local_fragment _GENERIC_MATCAP1 + #pragma shader_feature_local_fragment _GENERIC_MATCAP2 + #pragma shader_feature_local _GENERIC_MATCAP1_CUSTOM_NORMAL + #pragma shader_feature_local _GENERIC_MATCAP2_CUSTOM_NORMAL + #pragma shader_feature_local_fragment _GENERIC_RIMLIGHT3D + #pragma shader_feature_local_fragment _RAMP_LIGHTING + #pragma shader_feature_local_fragment _RAMP_LIGHTING_SAMPLE_UVY_TEX + #pragma shader_feature_local_fragment _RAMP_SPECULAR + #pragma shader_feature_local_fragment _RAMP_SPECULAR_SAMPLE_UVY_TEX + #pragma shader_feature_local_fragment _SHADING_GRADEMAP + #pragma shader_feature_local _DYNAMIC_EYE + #pragma shader_feature_local _KAJIYAKAY_SPECULAR + #pragma shader_feature_local_fragment _KAJIYAKAY_SPECULAR_TEX_TINT + #pragma shader_feature_local_fragment _SCREENSPACE_OUTLINE + #pragma shader_feature_local_fragment _SCREENSPACE_OUTLINE_V2 + #pragma shader_feature_local_fragment _OVERRIDE_SHADOWCOLOR_BY_TEXTURE + #pragma shader_feature_local_fragment _SHADOW_MODE_LILTOON + #pragma shader_feature_local_fragment _OVERRIDE_OUTLINECOLOR_BY_TEXTURE + #pragma shader_feature_local_fragment _DEPTHTEX_RIMLIGHT_SHADOW_WIDTHMAP + #pragma shader_feature_local_fragment _DEPTHTEX_RIMLIGHT_OPACITY_MASKMAP + #pragma shader_feature_local_fragment _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS + #pragma shader_feature_local_fragment _NILOTOON_SELFSHADOW_INTENSITY_MAP + #pragma shader_feature_local_fragment _FACE_SHADOW_GRADIENTMAP + #pragma shader_feature_local_fragment _FACE_3D_RIMLIGHT_AND_SHADOW + + #pragma multi_compile_fragment _ _NILOTOON_RECEIVE_URP_SHADOWMAPPING + #pragma multi_compile_fragment _ _NILOTOON_RECEIVE_SELF_SHADOW + #pragma multi_compile_local_fragment _ _NILOTOON_DITHER_FADEOUT + #pragma multi_compile_local_fragment _ _NILOTOON_PERCHARACTER_BASEMAP_OVERRIDE + #pragma multi_compile_fragment _ _NILOTOON_GLOBAL_ENABLE_SCREENSPACE_OUTLINE + #pragma multi_compile _ _NILOTOON_DEBUG_SHADING + + #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN + #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS + #pragma multi_compile _ _LIGHT_LAYERS + #if UNITY_VERSION >= 60010000 + #pragma multi_compile _ _CLUSTER_LIGHT_LOOP + #elif UNITY_VERSION >= 202220 + #pragma multi_compile _ _FORWARD_PLUS + #endif + #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS + #pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING + #pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION + #if UNITY_VERSION >= 60010000 + #pragma multi_compile_fragment _ _REFLECTION_PROBE_ATLAS + #endif + #ifndef SHADER_API_MOBILE + #define _SHADOWS_SOFT 1 + #endif + #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3 + #pragma multi_compile_fragment _ _LIGHT_COOKIES + #if UNITY_VERSION >= 202220 + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl" + #endif + #if UNITY_VERSION >= 60010000 + #pragma dynamic_branch _ FOG_LINEAR FOG_EXP FOG_EXP2 + #else + #pragma multi_compile_fog + #endif + #if UNITY_VERSION >= 60000011 + #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ProbeVolumeVariants.hlsl" + #endif + + #define NiloToonFurPass 1 + + #include "NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl" + #include "NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl" + + ENDHLSL + } } ////////////////////////////////////////////////////// diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader deleted file mode 100644 index c46f7c509..000000000 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader +++ /dev/null @@ -1,821 +0,0 @@ -// NiloToon Character Fur Shader -// Single-material fur shader with Base + Fur Shell rendering -// Requires NiloToonFurRendererFeature to be added to URP Renderer -// -// Usage: -// 1. Add NiloToonFurRendererFeature to your URP Renderer Asset -// 2. Apply this shader to your mesh material (single material slot) - -Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur" -{ - Properties - { - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Base Color - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Base Color)] - [Space(5)] - [MainTexture] _BaseMap("Base Map", 2D) = "white" {} - [HDR][MainColor] _BaseColor("Base Color", Color) = (1,1,1,1) - _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Normal Map - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Normal Map)] - [Space(5)] - [Toggle(_NORMALMAP)] _UseNormalMap("Enable Normal Map", Float) = 0 - [Normal] _BumpMap("Normal Map", 2D) = "bump" {} - _BumpScale("Normal Scale", Range(0, 2)) = 1.0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Fur Settings - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Fur Shape)] - [Space(5)] - _FurNoiseMask("Fur Noise Mask", 2D) = "white" {} - _FurMask("Fur Mask (where fur appears)", 2D) = "white" {} - _FurLengthMask("Fur Length Mask", 2D) = "white" {} - _FurVector("Fur Direction (XYZ) + Length (W)", Vector) = (0, 0, 1, 0.02) - [Normal] _FurVectorTex("Fur Direction Map (Normal)", 2D) = "bump" {} - _FurVectorScale("Fur Direction Scale", Range(-10, 10)) = 1.0 - _FurGravity("Fur Gravity", Range(0, 1)) = 0.25 - _FurRandomize("Fur Randomize", Range(0, 1)) = 0.1 - _FurAO("Fur Ambient Occlusion", Range(0, 1)) = 0.5 - - [Header(Shell Layers)] - [Space(5)] - [IntRange] _FurLayerNum("Fur Layer Count", Range(1, 3)) = 2 - _FurRootOffset("Fur Root Offset", Range(-1, 0)) = 0 - - [Header(Fur Rim Light)] - [Space(5)] - [HDR] _FurRimColor("Fur Rim Color", Color) = (1, 1, 1, 1) - _FurRimFresnelPower("Fur Rim Fresnel Power", Range(0.01, 50)) = 3.0 - _FurRimAntiLight("Fur Rim Anti-Light", Range(0, 1)) = 0.5 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Toon Shading (NiloToon Style) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Cel Shading)] - [Space(5)] - _CelShadeMidPoint("Cel Shade Mid Point", Range(-1, 1)) = 0 - _CelShadeSoftness("Cel Shade Softness", Range(0, 1)) = 0.1 - - [Header(Shadow Color)] - [Space(5)] - [Toggle(_SHADOW_COLOR)] _EnableShadowColor("Enable Shadow Color", Float) = 0 - [HDR] _ShadowColor("Shadow Tint Color", Color) = (1, 1, 1, 1) - _ShadowBrightness("Shadow Brightness", Range(0, 2)) = 1.0 - - [Header(HSV Adjustment in Shadow)] - [Space(5)] - _ShadowHueShift("Shadow Hue Shift", Range(-0.5, 0.5)) = 0 - _ShadowSaturationBoost("Shadow Saturation Boost", Range(0, 2)) = 1.0 - _ShadowValueMultiplier("Shadow Value Multiplier", Range(0, 2)) = 1.0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // MatCap - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(MatCap Additive)] - [Space(5)] - [Toggle(_MATCAP_ADD)] _UseMatCapAdd("Enable MatCap (Add)", Float) = 0 - _MatCapAddMap("MatCap Add Map", 2D) = "black" {} - [HDR] _MatCapAddColor("MatCap Add Color", Color) = (1, 1, 1, 1) - _MatCapAddIntensity("MatCap Add Intensity", Range(0, 5)) = 1.0 - _MatCapAddMask("MatCap Add Mask", 2D) = "white" {} - - [Header(MatCap Multiply)] - [Space(5)] - [Toggle(_MATCAP_MUL)] _UseMatCapMul("Enable MatCap (Multiply)", Float) = 0 - _MatCapMulMap("MatCap Multiply Map", 2D) = "white" {} - _MatCapMulIntensity("MatCap Multiply Intensity", Range(0, 2)) = 1.0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Rim Light (General) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Rim Light)] - [Space(5)] - [Toggle(_RIMLIGHT)] _UseRimLight("Enable Rim Light", Float) = 0 - [HDR] _RimLightColor("Rim Light Color", Color) = (1, 1, 1, 1) - _RimLightPower("Rim Light Power", Range(0.01, 20)) = 5.0 - _RimLightIntensity("Rim Light Intensity", Range(0, 5)) = 1.0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Emission - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Emission)] - [Space(5)] - [Toggle(_EMISSION)] _UseEmission("Enable Emission", Float) = 0 - _EmissionMap("Emission Map", 2D) = "white" {} - [HDR] _EmissionColor("Emission Color", Color) = (0, 0, 0, 1) - _EmissionIntensity("Emission Intensity", Range(0, 10)) = 1.0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Occlusion - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Occlusion)] - [Space(5)] - [Toggle(_OCCLUSIONMAP)] _UseOcclusion("Enable Occlusion Map", Float) = 0 - _OcclusionMap("Occlusion Map", 2D) = "white" {} - _OcclusionStrength("Occlusion Strength", Range(0, 1)) = 1.0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Outline - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Outline)] - [Space(5)] - _OutlineWidth("Outline Width", Range(0, 10)) = 1.0 - [HDR] _OutlineColor("Outline Color", Color) = (0, 0, 0, 1) - _OutlineWidthMask("Outline Width Mask", 2D) = "white" {} - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Rendering Options - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [Header(Rendering Options)] - [Space(5)] - [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull Mode", Float) = 2 - [Enum(UnityEngine.Rendering.CullMode)] _FurCull("Fur Cull Mode", Float) = 0 - [Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Float) = 1 - _FurZWrite("Fur ZWrite", Float) = 0 - [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Dissolve (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _DissolveAmount("_DissolveAmount", Range(0,1)) = 0 - [HideInInspector] _DissolveMode("_DissolveMode", Integer) = 0 - [HideInInspector] _DissolveThresholdMap("_DissolveThresholdMap", 2D) = "linearGrey" {} - [HideInInspector] _DissolveThresholdMapTilingX("_DissolveThresholdMapTilingX", Float) = 1 - [HideInInspector] _DissolveThresholdMapTilingY("_DissolveThresholdMapTilingY", Float) = 1 - [HideInInspector] _DissolveNoiseStrength("_DissolveNoiseStrength", Float) = 1 - [HideInInspector] _DissolveBorderRange("_DissolveBorderRange", Float) = 0.02 - [HideInInspector] _DissolveBorderTintColor("_DissolveBorderTintColor", Color) = (1, 3, 6, 1) - [HideInInspector] _AllowPerCharacterDissolve("_AllowPerCharacterDissolve", Float) = 1 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Per-Character Color Controls (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _PerCharacterBaseColorMultiply("_PerCharacterBaseColorMultiply", Float) = 1 - [HideInInspector] _PerCharacterBaseColorTint("_PerCharacterBaseColorTint", Color) = (1, 1, 1, 1) - [HideInInspector] _PerCharEffectTintColor("_PerCharEffectTintColor", Color) = (1, 1, 1, 1) - [HideInInspector] _PerCharEffectAddColor("_PerCharEffectAddColor", Color) = (0, 0, 0, 0) - [HideInInspector] _PerCharEffectDesaturatePercentage("_PerCharEffectDesaturatePercentage", Range(0,1)) = 0 - [HideInInspector] _PerCharEffectLerpColor("_PerCharEffectLerpColor", Color) = (1, 1, 0, 0) - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Per-Character Rim Light (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _UsePerCharacterRimLightIntensity("_UsePerCharacterRimLightIntensity", Float) = 0 - [HideInInspector] _PerCharacterRimLightIntensity("_PerCharacterRimLightIntensity", Float) = 2 - [HideInInspector] _PerCharacterRimLightColor("_PerCharacterRimLightColor", Color) = (1, 1, 1, 1) - [HideInInspector] _PerCharacterRimLightSharpnessPower("_PerCharacterRimLightSharpnessPower", Float) = 4 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // BaseMap Override (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _PerCharacterBaseMapOverrideAmount("_PerCharacterBaseMapOverrideAmount", Range(0,1)) = 0 - [HideInInspector] _PerCharacterBaseMapOverrideTintColor("_PerCharacterBaseMapOverrideTintColor", Color) = (1, 1, 1, 1) - [HideInInspector] _PerCharacterBaseMapOverrideMap("_PerCharacterBaseMapOverrideMap", 2D) = "white" {} - [HideInInspector] _PerCharacterBaseMapOverrideBlendMode("_PerCharacterBaseMapOverrideBlendMode", Float) = 0 - [HideInInspector] _PerCharacterBaseMapOverrideUVOption("_PerCharacterBaseMapOverrideUVOption", Float) = 0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Character Area Color Fill (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _ShouldRenderCharacterAreaColorFill("_ShouldRenderCharacterAreaColorFill", Float) = 0 - [HideInInspector] _CharacterAreaColorFillColor("_CharacterAreaColorFillColor", Color) = (1, 1, 1, 1) - [HideInInspector] _CharacterAreaColorFillTexture("_CharacterAreaColorFillTexture", 2D) = "white" {} - [HideInInspector] _CharacterAreaColorFillUVOption("_CharacterAreaColorFillUVOption", Float) = 0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Dither Opacity (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _DitherOpacity("_DitherOpacity", Range(0,1)) = 1 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Dither Fadeout (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _DitherFadeoutAmount("_DitherFadeoutAmount", Range(0,1)) = 0 - [HideInInspector] _DitherFadeoutNormalScaleFix("_DitherFadeoutNormalScaleFix", Float) = 1 - [HideInInspector] _AllowPerCharacterDitherFadeout("_AllowPerCharacterDitherFadeout", Float) = 1 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Perspective Removal (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _PerspectiveRemovalAmount("_PerspectiveRemovalAmount", Range(0,1)) = 0 - [HideInInspector] _PerspectiveRemovalRadius("_PerspectiveRemovalRadius", Float) = 5 - [HideInInspector] _PerspectiveRemovalStartHeight("_PerspectiveRemovalStartHeight", Float) = 1 - [HideInInspector] _PerspectiveRemovalEndHeight("_PerspectiveRemovalEndHeight", Float) = 0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // ZOffset (NiloToonPerCharacterRenderController) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _PerCharacterZOffset("_PerCharacterZOffset", Float) = 0 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Character Bound (for dissolve) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - [HideInInspector] _CharacterBoundRadius("_CharacterBoundRadius", Float) = 2.5 - - // Hidden - [HideInInspector] _Surface("__surface", Float) = 0.0 - [HideInInspector] _Blend("__blend", Float) = 0.0 - [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0 - } - - SubShader - { - Tags - { - "RenderType" = "Opaque" - "RenderPipeline" = "UniversalPipeline" - "UniversalMaterialType" = "Lit" - "IgnoreProjector" = "True" - "Queue" = "Geometry" - } - LOD 300 - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 0: ForwardLit - Base Surface (Full NiloToon Style) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "ForwardLit" - Tags { "LightMode" = "UniversalForward" } - - Cull [_Cull] - ZWrite On - ZTest LEqual - Blend One Zero - - HLSLPROGRAM - #pragma target 4.5 - - // Shader Features - #pragma shader_feature_local _NORMALMAP - #pragma shader_feature_local _SHADOW_COLOR - #pragma shader_feature_local _MATCAP_ADD - #pragma shader_feature_local _MATCAP_MUL - #pragma shader_feature_local _RIMLIGHT - #pragma shader_feature_local _EMISSION - #pragma shader_feature_local _OCCLUSIONMAP - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - // URP Keywords - #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN - #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS - #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS - #pragma multi_compile_fragment _ _SHADOWS_SOFT - #pragma multi_compile_fog - - // GPU Instancing - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - - #pragma vertex vert - #pragma fragment frag - - #define NILOTOON_FUR_BASE_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - ENDHLSL - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 1: Fur Shell Pass (Geometry Shader) - Standard single target - // Rendered by NiloToonFurRendererFeature via "NiloToonFurShell" LightMode - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "FurShell" - Tags { "LightMode" = "NiloToonFurShell" } - - Cull [_FurCull] - ZWrite [_FurZWrite] - ZTest LEqual - Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha - - HLSLPROGRAM - #pragma target 4.5 - #pragma require geometry - - // Shader Features - #pragma shader_feature_local _NORMALMAP - #pragma shader_feature_local _SHADOW_COLOR - #pragma shader_feature_local _MATCAP_ADD - #pragma shader_feature_local _MATCAP_MUL - #pragma shader_feature_local _RIMLIGHT - #pragma shader_feature_local _EMISSION - #pragma shader_feature_local _OCCLUSIONMAP - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - // URP Keywords - #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN - #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS - #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS - #pragma multi_compile_fragment _ _SHADOWS_SOFT - #pragma multi_compile_fog - - // GPU Instancing - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - - #pragma vertex vert_fur - #pragma geometry geom_fur - #pragma fragment frag_fur - - #define NILOTOON_FUR_SHELL_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - ENDHLSL - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 1.5: Fur Shell Mask Pass (Geometry Shader) - // Renders fur shells to mask buffer only (white where fur is rendered) - // Used for fur area detection in post-processing - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "FurShellMask" - Tags { "LightMode" = "NiloToonFurShellMask" } - - Cull [_FurCull] - ZWrite On // Write depth to prevent outline from rendering over fur - ZTest LEqual // Standard depth test - Blend One Zero // Just overwrite - - HLSLPROGRAM - #pragma target 4.5 - #pragma require geometry - - // Dissolve support - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - // GPU Instancing - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - - #pragma vertex vert_fur - #pragma geometry geom_fur - #pragma fragment frag_fur_mask - - #define NILOTOON_FUR_SHELL_PASS - #define NILOTOON_FUR_MASK_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - ENDHLSL - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 2: Outline (NiloToon Style) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "Outline" - Tags { "LightMode" = "NiloToonOutline" } - - Cull Front - ZWrite [_ZWrite] - ZTest [_ZTest] - - HLSLPROGRAM - #pragma target 4.5 - - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - #pragma multi_compile_fog - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - #pragma vertex vert_outline - #pragma fragment frag_outline - - #define NILOTOON_FUR_OUTLINE_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - - Varyings vert_outline(Attributes input) - { - Varyings output = (Varyings)0; - UNITY_SETUP_INSTANCE_ID(input); - UNITY_TRANSFER_INSTANCE_ID(input, output); - UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - - float outlineWidth = _OutlineWidth * 0.001; - float outlineMask = SAMPLE_TEXTURE2D_LOD(_OutlineWidthMask, sampler_OutlineWidthMask, input.uv, 0).r; - outlineWidth *= outlineMask; - - // FOV-aware outline width - float fovFactor = unity_OrthoParams.w > 0.5 ? 1.0 : (2.0 * abs(UNITY_MATRIX_P[1][1])); - outlineWidth *= fovFactor; - - float3 posOS = input.positionOS.xyz + input.normalOS * outlineWidth; - output.positionWS = TransformObjectToWorld(posOS); - output.positionCS = TransformObjectToHClip(posOS); - output.uv = input.uv; - - // Apply Perspective Removal to outline - output.positionCS = NiloDoPerspectiveRemoval( - output.positionCS, - output.positionWS, - _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], - _PerspectiveRemovalRadius, - _PerspectiveRemovalAmount, - _PerspectiveRemovalStartHeight, - _PerspectiveRemovalEndHeight - ); - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - output.fogFactor = ComputeFogFactor(output.positionCS.z); - - return output; - } - - half4 frag_outline(Varyings input) : SV_Target - { - // Apply Dither Fadeout to outline (FIRST) - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve to outline - #if _NILOTOON_DISSOLVE - half3 dummyColor = half3(1, 1, 1); - ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); - #endif - - half4 color = _OutlineColor; - color.rgb = MixFog(color.rgb, input.fogFactor); - return color; - } - ENDHLSL - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 3: ShadowCaster - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "ShadowCaster" - Tags { "LightMode" = "ShadowCaster" } - - ZWrite On - ZTest LEqual - ColorMask 0 - Cull [_Cull] - - HLSLPROGRAM - #pragma target 4.5 - - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - #pragma vertex ShadowPassVertex - #pragma fragment ShadowPassFragment - - #define NILOTOON_FUR_SHADOW_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - - float3 _LightDirection; - float3 _LightPosition; - - float4 GetShadowPositionHClip(Attributes input) - { - float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); - float3 normalWS = TransformObjectToWorldNormal(input.normalOS); - - #if _CASTING_PUNCTUAL_LIGHT_SHADOW - float3 lightDirectionWS = normalize(_LightPosition - positionWS); - #else - float3 lightDirectionWS = _LightDirection; - #endif - - float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS)); - - #if UNITY_REVERSED_Z - positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE); - #else - positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE); - #endif - - return positionCS; - } - - Varyings ShadowPassVertex(Attributes input) - { - Varyings output = (Varyings)0; - UNITY_SETUP_INSTANCE_ID(input); - UNITY_TRANSFER_INSTANCE_ID(input, output); - - output.uv = input.uv; - output.positionWS = TransformObjectToWorld(input.positionOS.xyz); - output.positionCS = GetShadowPositionHClip(input); - - // Apply Perspective Removal to shadow casting - output.positionCS = NiloDoPerspectiveRemoval( - output.positionCS, - output.positionWS, - _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], - _PerspectiveRemovalRadius, - _PerspectiveRemovalAmount, - _PerspectiveRemovalStartHeight, - _PerspectiveRemovalEndHeight - ); - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - return output; - } - - half4 ShadowPassFragment(Varyings input) : SV_TARGET - { - half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; - clip(alpha - _Cutoff); - - // Apply dither fadeout to shadow casting (must come before dissolve) - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve to shadow casting - #if _NILOTOON_DISSOLVE - half3 dummyColor = half3(1, 1, 1); - ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); - #endif - - return 0; - } - ENDHLSL - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 4: DepthOnly - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "DepthOnly" - Tags { "LightMode" = "DepthOnly" } - - ZWrite On - ColorMask R - Cull [_Cull] - - HLSLPROGRAM - #pragma target 4.5 - - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - #pragma vertex DepthOnlyVertex - #pragma fragment DepthOnlyFragment - - #define NILOTOON_FUR_DEPTH_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - - Varyings DepthOnlyVertex(Attributes input) - { - Varyings output = (Varyings)0; - UNITY_SETUP_INSTANCE_ID(input); - UNITY_TRANSFER_INSTANCE_ID(input, output); - - output.uv = input.uv; - output.positionWS = TransformObjectToWorld(input.positionOS.xyz); - output.positionCS = TransformObjectToHClip(input.positionOS.xyz); - - // Apply Perspective Removal to depth - output.positionCS = NiloDoPerspectiveRemoval( - output.positionCS, - output.positionWS, - _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], - _PerspectiveRemovalRadius, - _PerspectiveRemovalAmount, - _PerspectiveRemovalStartHeight, - _PerspectiveRemovalEndHeight - ); - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - return output; - } - - half DepthOnlyFragment(Varyings input) : SV_TARGET - { - half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; - clip(alpha - _Cutoff); - - // Apply dither fadeout to depth (must come before dissolve) - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve to depth - #if _NILOTOON_DISSOLVE - half3 dummyColor = half3(1, 1, 1); - ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); - #endif - - return input.positionCS.z; - } - ENDHLSL - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 5: DepthNormals - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "DepthNormals" - Tags { "LightMode" = "DepthNormals" } - - ZWrite On - Cull [_Cull] - - HLSLPROGRAM - #pragma target 4.5 - - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - #pragma vertex DepthNormalsVertex - #pragma fragment DepthNormalsFragment - - #define NILOTOON_FUR_DEPTHNORMALS_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - - Varyings DepthNormalsVertex(Attributes input) - { - Varyings output = (Varyings)0; - UNITY_SETUP_INSTANCE_ID(input); - UNITY_TRANSFER_INSTANCE_ID(input, output); - - output.uv = input.uv; - output.positionWS = TransformObjectToWorld(input.positionOS.xyz); - output.positionCS = TransformObjectToHClip(input.positionOS.xyz); - output.normalWS = TransformObjectToWorldNormal(input.normalOS); - - // Apply Perspective Removal to depth normals - output.positionCS = NiloDoPerspectiveRemoval( - output.positionCS, - output.positionWS, - _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], - _PerspectiveRemovalRadius, - _PerspectiveRemovalAmount, - _PerspectiveRemovalStartHeight, - _PerspectiveRemovalEndHeight - ); - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - return output; - } - - float4 DepthNormalsFragment(Varyings input) : SV_TARGET - { - half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; - clip(alpha - _Cutoff); - - // Apply dither fadeout to depth normals (must come before dissolve) - // This is critical for HBAO/SSAO - without this, AO will render on dithered areas - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve to depth normals - #if _NILOTOON_DISSOLVE - half3 dummyColor = half3(1, 1, 1); - ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); - #endif - - return float4(normalize(input.normalWS) * 0.5 + 0.5, 0); - } - ENDHLSL - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Pass 6: NiloToonPrepassBuffer (Base mesh only) - // For NiloToon Bloom / Tonemapping character area detection - base mesh - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Pass - { - Name "NiloToonPrepassBuffer" - Tags { "LightMode" = "NiloToonPrepassBuffer" } - - ZWrite On - ZTest LEqual - Cull [_Cull] - - HLSLPROGRAM - #pragma target 4.5 - - #pragma multi_compile_instancing - #pragma instancing_options renderinglayer - #pragma multi_compile_local _ _NILOTOON_DISSOLVE - #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT - - #pragma vertex PrepassBufferVertexBase - #pragma fragment PrepassBufferFragmentBase - - #define NILOTOON_FUR_PREPASSBUFFER_PASS - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" - #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" - - Varyings PrepassBufferVertexBase(Attributes input) - { - Varyings output = (Varyings)0; - UNITY_SETUP_INSTANCE_ID(input); - UNITY_TRANSFER_INSTANCE_ID(input, output); - UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - - output.uv = input.uv; - output.positionWS = TransformObjectToWorld(input.positionOS.xyz); - output.positionCS = TransformObjectToHClip(input.positionOS.xyz); - - // Apply Perspective Removal to prepass buffer - output.positionCS = NiloDoPerspectiveRemoval( - output.positionCS, - output.positionWS, - _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], - _PerspectiveRemovalRadius, - _PerspectiveRemovalAmount, - _PerspectiveRemovalStartHeight, - _PerspectiveRemovalEndHeight - ); - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - output.furLayer = -1; // Base mesh marker - return output; - } - - float4 PrepassBufferFragmentBase(Varyings input) : SV_TARGET - { - UNITY_SETUP_INSTANCE_ID(input); - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - - // Base mesh alpha clip - half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; - clip(alpha - _Cutoff); - - // Apply dither fadeout to prepass buffer (must come before dissolve) - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve to prepass buffer - #if _NILOTOON_DISSOLVE - half3 dummyColor = half3(1, 1, 1); - ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); - #endif - - // Output: character visible area = 1 - return float4(0, 1, 0, 1); - } - ENDHLSL - } - - // Note: Fur shell prepass is handled via MRT in the FurShellMRT pass - // When WriteToPrepassBuffer is enabled, FurShellMRT outputs to both: - // - SV_Target0: Main color buffer - // - SV_Target1: PrepassBuffer (character mask with jagged fur silhouette) - } - - FallBack "Universal Render Pipeline/Lit" - CustomEditor "NiloToonURP.ShaderGUI.NiloToonCharacterFurShaderGUI" -} diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader.meta deleted file mode 100644 index c84b1ca2a..000000000 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: d65d4a470e01cd947a07483a9bf34206 -ShaderImporter: - externalObjects: {} - defaultTextures: [] - nonModifiableTextures: [] - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl deleted file mode 100644 index c1b8a755d..000000000 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl +++ /dev/null @@ -1,608 +0,0 @@ -// NiloToon Character Fur - Fragment Shader -// Full-featured NiloToon style cel shading + Fur specific effects - -#ifndef NILOTOON_CHARACTER_FUR_FRAGMENT_INCLUDED -#define NILOTOON_CHARACTER_FUR_FRAGMENT_INCLUDED - -//------------------------------------------------------------------------------------------------------------------------------ -// Get Normal from Normal Map -//------------------------------------------------------------------------------------------------------------------------------ -half3 GetNormalFromMap(float2 uv, float3 normalWS, float4 tangentWS) -{ - #if defined(_NORMALMAP) - half4 normalMap = SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, uv); - half3 normalTS = UnpackNormalWithScale(normalMap, _BumpScale); - - float3 bitangent = cross(normalWS, tangentWS.xyz) * tangentWS.w; - float3x3 TBN = float3x3(tangentWS.xyz, bitangent, normalWS); - - return normalize(mul(normalTS, TBN)); - #else - return normalize(normalWS); - #endif -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Apply Dissolve (NiloToon Style) -//------------------------------------------------------------------------------------------------------------------------------ -void ApplyDissolve(inout half3 color, float2 uv, float3 positionWS, float4 positionCS) -{ -#if _NILOTOON_DISSOLVE - // Matching to NiloToonPerCharacterRenderController.cs's enum DissolveMode - #define DISSOLVEMODE_UV1 1 - #define DISSOLVEMODE_UV2 2 - #define DISSOLVEMODE_WorldSpaceNoise 3 - #define DISSOLVEMODE_WorldSpaceVerticalUpward 4 - #define DISSOLVEMODE_WorldSpaceVerticalDownward 5 - #define DISSOLVEMODE_ScreenSpaceNoise 6 - #define DISSOLVEMODE_ScreenSpaceVerticalUpward 7 - #define DISSOLVEMODE_ScreenSpaceVerticalDownward 8 - - half finalDissolveAmount = _DissolveAmount * _AllowPerCharacterDissolve; - if(finalDissolveAmount <= 0) return; - - float noiseStrength = _DissolveNoiseStrength * 0.1; - float2 uvTiling = float2(_DissolveThresholdMapTilingX, _DissolveThresholdMapTilingY); - - half dissolveMapThresholdMapValue = 0; - - // UV1 - sample .g channel (matching NiloToonCharacter) - if(_DissolveMode == DISSOLVEMODE_UV1) - { - float2 dissolveUV = uv * uvTiling; - dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; - } - // WorldSpaceNoise - 3-axis multiplication (matching NiloToonCharacter) - else if(_DissolveMode == DISSOLVEMODE_WorldSpaceNoise) - { - float2 dissolveUV; - - dissolveUV = positionWS.xz * uvTiling; - dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; - - dissolveUV = positionWS.xy * uvTiling; - dissolveMapThresholdMapValue *= SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; - - dissolveUV = positionWS.yz * uvTiling; - dissolveMapThresholdMapValue *= SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; - } - // WorldSpaceVerticalUpward - use character bound data from global arrays - else if(_DissolveMode == DISSOLVEMODE_WorldSpaceVerticalUpward) - { - float2 dissolveUV = positionWS.xz * uvTiling; - float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength; - // Calculate character bound from center pos and radius (same as NiloToonCharacter) - float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; - float characterBoundBottom = characterBoundCenterPosWS.y - _CharacterBoundRadius; - float characterBoundTop = characterBoundCenterPosWS.y + _CharacterBoundRadius; - dissolveMapThresholdMapValue = invLerpClamp(characterBoundBottom, characterBoundTop, positionWS.y + noise); - } - // WorldSpaceVerticalDownward - use character bound data from global arrays - else if(_DissolveMode == DISSOLVEMODE_WorldSpaceVerticalDownward) - { - float2 dissolveUV = positionWS.xz * uvTiling; - float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength; - // Calculate character bound from center pos and radius (same as NiloToonCharacter) - float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; - float characterBoundBottom = characterBoundCenterPosWS.y - _CharacterBoundRadius; - float characterBoundTop = characterBoundCenterPosWS.y + _CharacterBoundRadius; - dissolveMapThresholdMapValue = invLerpClamp(characterBoundTop, characterBoundBottom, positionWS.y + noise); - } - // ScreenSpaceNoise - use character bound 2D rect UV (matching NiloToonCharacter) - else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceNoise) - { - // Calculate character bound 2D rect UV using Calc3DSphereTo2DUV (same as NiloToonCharacter) - float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; - float2 characterBound2DRectUV01 = Calc3DSphereTo2DUV(positionWS, characterBoundCenterPosWS, _CharacterBoundRadius); - - // since the default bounding sphere is 2.5m, when compared to world space, it should have 2.5x Tiling - float2 dissolveUV = characterBound2DRectUV01 * uvTiling * 2.5; - dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; - } - // ScreenSpaceVerticalUpward - else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceVerticalUpward) - { - // Calculate character bound 2D rect UV using Calc3DSphereTo2DUV (same as NiloToonCharacter) - float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; - float2 characterBound2DRectUV01 = Calc3DSphereTo2DUV(positionWS, characterBoundCenterPosWS, _CharacterBoundRadius); - - // since the default bounding sphere is 2.5m, when compared to world space, it should have 2.5x Tiling - float2 dissolveUV = characterBound2DRectUV01 * uvTiling * 2.5; - float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength; - dissolveMapThresholdMapValue = saturate(characterBound2DRectUV01.y + noise); - } - // ScreenSpaceVerticalDownward - else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceVerticalDownward) - { - // Calculate character bound 2D rect UV using Calc3DSphereTo2DUV (same as NiloToonCharacter) - float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; - float2 characterBound2DRectUV01 = Calc3DSphereTo2DUV(positionWS, characterBoundCenterPosWS, _CharacterBoundRadius); - - // since the default bounding sphere is 2.5m, when compared to world space, it should have 2.5x Tiling - float2 dissolveUV = characterBound2DRectUV01 * uvTiling * 2.5; - float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength; - dissolveMapThresholdMapValue = saturate((1 - characterBound2DRectUV01.y) + noise); - } - - half dissolve = dissolveMapThresholdMapValue - finalDissolveAmount; - - // Clip threshold - clip(dissolve - 0.0001); - - // HDR color tint to "near threshold area" - color = lerp(color, _DissolveBorderTintColor.rgb, smoothstep(finalDissolveAmount + _DissolveBorderRange, finalDissolveAmount, dissolveMapThresholdMapValue)); -#endif -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Apply Per-Character Color Controls (Tint, Add, Desaturation, Lerp) -//------------------------------------------------------------------------------------------------------------------------------ -half3 ApplyPerCharacterColorControls(half3 color) -{ - // Base Color Multiply & Tint - color *= _PerCharacterBaseColorMultiply; - color *= _PerCharacterBaseColorTint.rgb; - - // Per-Character Tint & Add Color (set by NiloToonPerCharacterRenderController) - // Matching NiloToonCharacter_Shared.hlsl: color.rgb = color.rgb * _PerCharEffectTintColor + _PerCharEffectAddColor; - color.rgb = color.rgb * _PerCharEffectTintColor + _PerCharEffectAddColor; - - // Desaturation (matching NiloToonCharacter_Shared.hlsl line 4099) - color = lerp(color, Luminance(color), _PerCharEffectDesaturatePercentage); - - // Replace by Color / Lerp Color (matching NiloToonCharacter_Shared.hlsl line 4105) - // Uses alpha channel of _PerCharEffectLerpColor as the lerp amount - color.rgb = lerp(color.rgb, _PerCharEffectLerpColor.rgb, _PerCharEffectLerpColor.a); - - return color; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Apply BaseMap Override (matching NiloToonPerCharacterRenderController) -// Based on ApplyPostLightingPerCharacterBaseMapOverride from NiloToonCharacter_Shared.hlsl -//------------------------------------------------------------------------------------------------------------------------------ -half3 ApplyBaseMapOverride(half3 baseColor, float2 uv, float3 positionWS, float4 positionCS) -{ - // Sample texture with tiling/offset - float2 overrideUV = uv * _PerCharacterBaseMapOverrideMap_ST.xy + _PerCharacterBaseMapOverrideMap_ST.zw; - half4 texValue = SAMPLE_TEXTURE2D(_PerCharacterBaseMapOverrideMap, sampler_PerCharacterBaseMapOverrideMap, overrideUV); - - // Apply tint color - texValue.rgb *= _PerCharacterBaseMapOverrideTintColor; - - // KEY FIX: Multiply alpha by Amount (0-1 range) - // When Amount is 0, alpha becomes 0, making BlendColor() return baseColor unchanged - texValue.a *= _PerCharacterBaseMapOverrideAmount; - - // Create RGBA versions for BlendColor function - half4 originalColorRGBA = half4(baseColor.r, baseColor.g, baseColor.b, 1); - half4 resultColorRGBA = BlendColor(originalColorRGBA, texValue, _PerCharacterBaseMapOverrideBlendMode); - - // Return only RGB (don't modify alpha) - return resultColorRGBA.rgb; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Apply Character Area Color Fill -// Based on NiloToonCharacterAreaColorFillFragmentFunction from NiloToonCharacter.shader -//------------------------------------------------------------------------------------------------------------------------------ -half3 ApplyCharacterAreaColorFill(half3 color, float2 uv, float3 positionWS, float4 positionCS) -{ - // Sample texture with tiling/offset - float2 fillUV = uv * _CharacterAreaColorFillTexture_ST.xy + _CharacterAreaColorFillTexture_ST.zw; - half4 fillTexSample = SAMPLE_TEXTURE2D(_CharacterAreaColorFillTexture, sampler_CharacterAreaColorFillTexture, fillUV); - - // Apply color tint - half4 resultColor = _CharacterAreaColorFillColor * fillTexSample; - - // KEY FIX: Multiply alpha by _ShouldRenderCharacterAreaColorFill (acts as enabled flag) - // When disabled (0), alpha becomes 0, so the color addition has no effect - // Note: Original shader also multiplies by renderArea, but we don't have prepass buffer in fur shader, - // so we'll just use the enabled flag - resultColor.a *= _ShouldRenderCharacterAreaColorFill; - - // Add the color based on alpha (when disabled, alpha is 0 so nothing is added) - color += resultColor.rgb * resultColor.a; - - return color; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Apply Dither Opacity (screen-space dithering for transparency) -//------------------------------------------------------------------------------------------------------------------------------ -void ApplyDitherOpacity(float4 positionCS, half opacity) -{ - if (opacity >= 1.0) return; - - // 4x4 Bayer matrix for dithering - const float4x4 thresholdMatrix = float4x4( - 1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0, - 13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0, - 4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0, - 16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0 - ); - - int2 pixelPos = int2(positionCS.xy) % 4; - float threshold = thresholdMatrix[pixelPos.x][pixelPos.y]; - - clip(opacity - threshold); -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Apply All Effects (MatCap, Rim, Emission) -//------------------------------------------------------------------------------------------------------------------------------ -half3 ApplyEffects( - half3 color, - float2 uv, - float3 normalWS, - float3 viewDirWS, - half3 lightColor, - half furLayer -) -{ - // MatCap UV - float2 matCapUV = GetMatCapUV(normalWS, viewDirWS); - - // MatCap Additive - #if defined(_MATCAP_ADD) - half matCapAddMask = SAMPLE_TEXTURE2D(_MatCapAddMask, sampler_MatCapAddMask, uv).r; - half3 matCapAdd = SAMPLE_TEXTURE2D(_MatCapAddMap, sampler_MatCapAddMap, matCapUV).rgb; - matCapAdd *= _MatCapAddColor.rgb * _MatCapAddIntensity * matCapAddMask; - color += matCapAdd; - #endif - - // MatCap Multiply - #if defined(_MATCAP_MUL) - half3 matCapMul = SAMPLE_TEXTURE2D(_MatCapMulMap, sampler_MatCapMulMap, matCapUV).rgb; - color *= lerp(half3(1, 1, 1), matCapMul, _MatCapMulIntensity); - #endif - - // Rim Light (General) - not applied to fur shells to avoid double rim - #if defined(_RIMLIGHT) - if (furLayer < 0) // Only for base pass - { - half NdotV = saturate(dot(normalWS, viewDirWS)); - half rimPower = _RimLightPower; - half rimIntensity = _RimLightIntensity; - half3 rimColor = _RimLightColor.rgb; - - // Apply per-character rim light override if enabled - if (_UsePerCharacterRimLightIntensity > 0.5) - { - rimPower = _PerCharacterRimLightSharpnessPower; - rimIntensity = _PerCharacterRimLightIntensity; - rimColor = _PerCharacterRimLightColor.rgb; - } - - half rim = pow(1.0 - NdotV, rimPower); - color += rim * rimColor * rimIntensity * lightColor; - } - #endif - - // Emission - #if defined(_EMISSION) - half3 emission = SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, uv).rgb; - emission *= _EmissionColor.rgb * _EmissionIntensity; - color += emission; - #endif - - return color; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Base Pass Fragment Shader -//------------------------------------------------------------------------------------------------------------------------------ -#if defined(NILOTOON_FUR_BASE_PASS) -half4 frag(Varyings input) : SV_Target -{ - UNITY_SETUP_INSTANCE_ID(input); - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - - // Sample base texture - half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); - half4 color = baseMap * _BaseColor; - - // Alpha cutoff - clip(color.a - _Cutoff); - - // Apply Dither Fadeout (FIRST - affects visibility) - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve (after dither fadeout) - // This will clip pixels and apply border glow - #if _NILOTOON_DISSOLVE - ApplyDissolve(color.rgb, input.uv, input.positionWS, input.positionCS); - #endif - - // Get normal (with normal map if enabled) - float3 normalWS = GetNormalFromMap(input.uv, input.normalWS, input.tangentWS); - - // Get view direction - float3 viewDirWS = GetWorldSpaceViewDirSafe(input.positionWS); - - // Get main light with NiloToon override support - Light mainLight = GetMainLightWithNiloToonOverride(); - - // Try to get shadow attenuation if shadow coord is valid - half shadowAttenuation = 1.0; - #if defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN) - shadowAttenuation = MainLightRealtimeShadow(input.shadowCoord); - #endif - mainLight.shadowAttenuation = shadowAttenuation; - - // Occlusion - half occlusion = 1.0; - #if defined(_OCCLUSIONMAP) - occlusion = lerp(1.0, SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, input.uv).r, _OcclusionStrength); - #endif - - // Apply BaseMap Override (before shading) - color.rgb = ApplyBaseMapOverride(color.rgb, input.uv, input.positionWS, input.positionCS); - - // Apply NiloToon cel shading - color.rgb = ApplyNiloToonCelShading( - color.rgb, - mainLight.color, - mainLight.direction, - normalWS, - viewDirWS, - shadowAttenuation, - occlusion - ); - - // Apply additional effects - color.rgb = ApplyEffects(color.rgb, input.uv, normalWS, viewDirWS, mainLight.color, input.furLayer); - - // Apply per-character color controls - color.rgb = ApplyPerCharacterColorControls(color.rgb); - - // Apply character area color fill - color.rgb = ApplyCharacterAreaColorFill(color.rgb, input.uv, input.positionWS, input.positionCS); - - // Apply dither opacity - ApplyDitherOpacity(input.positionCS, _DitherOpacity); - - // Apply fog - color.rgb = MixFog(color.rgb, input.fogFactor); - - return color; -} -#endif - -//------------------------------------------------------------------------------------------------------------------------------ -// Fur Shell Pass Fragment Shader -//------------------------------------------------------------------------------------------------------------------------------ -#if defined(NILOTOON_FUR_SHELL_PASS) - -// MRT output structure for simultaneous color + prepass buffer rendering -struct FurMRTOutput -{ - half4 color : SV_Target0; // Main color buffer - half4 prepass : SV_Target1; // PrepassBuffer (character mask) -}; - -// Internal function to compute fur color (shared between standard and MRT versions) -half4 ComputeFurColor(Varyings input, out half furAlpha) -{ - UNITY_SETUP_INSTANCE_ID(input); - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - - // Sample base texture - half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv); - half4 color = baseMap * _BaseColor; - - // Get main light with NiloToon override support - Light mainLight = GetMainLightWithNiloToonOverride(); - half3 lightColor = mainLight.color; - half3 lightDir = mainLight.direction; - - // Sample fur noise mask for alpha (default white = full fur) - float2 furNoiseUV = input.uv * _FurNoiseMask_ST.xy + _FurNoiseMask_ST.zw; - half furNoise = SAMPLE_TEXTURE2D(_FurNoiseMask, sampler_FurNoiseMask, furNoiseUV).r; - - // Sample fur mask (where fur appears, default white = everywhere) - float2 furMaskUV = input.uv * _FurMask_ST.xy + _FurMask_ST.zw; - half furMask = SAMPLE_TEXTURE2D(_FurMask, sampler_FurMask, furMaskUV).r; - - // furLayer: 0 = root/base, 1 = tip - half furLayer = saturate(input.furLayer); - - // Calculate fur alpha using lilToon-style non-linear curve - // This creates natural-looking fur tips instead of obvious hair cards - - // furLayerShift with root offset adjustment (lilToon style) - // _FurRootOffset range is -1 to 0: -1 = hide roots completely, 0 = show all - half furLayerShift = furLayer - furLayer * _FurRootOffset + _FurRootOffset; - half furLayerAbs = abs(furLayerShift); - - // Non-linear alpha curve: creates sharp tip cutoff - // Using cubic falloff for natural-looking fur tips - furAlpha = saturate(furNoise - furLayerShift * furLayerAbs * furLayerAbs * furLayerAbs + 0.25); - - // Apply fur mask - furAlpha *= furMask; - - // Minimum alpha threshold - clip(furAlpha - 0.05); - - // Apply Dither Fadeout (FIRST - affects visibility) - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve (after dither fadeout) - // This will clip pixels and apply border glow - #if _NILOTOON_DISSOLVE - ApplyDissolve(color.rgb, input.uv, input.positionWS, input.positionCS); - #endif - - // Apply BaseMap Override (before shading) - color.rgb = ApplyBaseMapOverride(color.rgb, input.uv, input.positionWS, input.positionCS); - - // Get normal (with normal map if enabled) - float3 normalWS = GetNormalFromMap(input.uv, input.normalWS, input.tangentWS); - - // Get view direction - float3 viewDirWS = GetWorldSpaceViewDirSafe(input.positionWS); - - // Occlusion - half occlusion = 1.0; - #if defined(_OCCLUSIONMAP) - occlusion = lerp(1.0, SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, input.uv).r, _OcclusionStrength); - #endif - - // Cel shading - half NdotL = dot(normalWS, lightDir); - half halfLambert = NdotL * 0.5 + 0.5; - half celShadeResult = smoothstep( - _CelShadeMidPoint + 0.5 - _CelShadeSoftness, - _CelShadeMidPoint + 0.5 + _CelShadeSoftness, - halfLambert - ); - - celShadeResult *= occlusion; - - #if defined(_SHADOW_COLOR) - // Apply HSV adjustment to shadow - half3 shadowAlbedo = ApplyHSVChange( - color.rgb, - _ShadowHueShift, - _ShadowSaturationBoost, - _ShadowValueMultiplier - ); - shadowAlbedo *= _ShadowColor.rgb * _ShadowBrightness; - color.rgb = lerp(shadowAlbedo, color.rgb, celShadeResult); - #else - color.rgb = lerp(color.rgb * 0.5, color.rgb, celShadeResult); - #endif - - // Apply light color - color.rgb *= lightColor; - - // Apply fur ambient occlusion (lilToon style) - // Uses fwidth to reduce aliasing at layer boundaries - half furAOFactor = _FurAO * saturate(1.0 - fwidth(input.furLayer)); - color.rgb *= furLayer * furAOFactor * 2.0 + 1.0 - furAOFactor; - - // Apply fur rim lighting - half NdotV = abs(dot(normalWS, viewDirWS)); - half rimFresnel = pow(saturate(1.0 - NdotV), _FurRimFresnelPower); - half antiLightFactor = lerp(1.0, 1.0 - Grayscale(lightColor), _FurRimAntiLight); - half3 rimColor = furLayer * rimFresnel * antiLightFactor * _FurRimColor.rgb; - color.rgb += rimColor; - - // Apply additional effects (MatCap, Emission) - // MatCap UV - float2 matCapUV = GetMatCapUV(normalWS, viewDirWS); - - #if defined(_MATCAP_ADD) - half matCapAddMask = SAMPLE_TEXTURE2D(_MatCapAddMask, sampler_MatCapAddMask, input.uv).r; - half3 matCapAdd = SAMPLE_TEXTURE2D(_MatCapAddMap, sampler_MatCapAddMap, matCapUV).rgb; - matCapAdd *= _MatCapAddColor.rgb * _MatCapAddIntensity * matCapAddMask * (1.0 - furLayer * 0.5); - color.rgb += matCapAdd; - #endif - - #if defined(_MATCAP_MUL) - half3 matCapMul = SAMPLE_TEXTURE2D(_MatCapMulMap, sampler_MatCapMulMap, matCapUV).rgb; - color.rgb *= lerp(half3(1, 1, 1), matCapMul, _MatCapMulIntensity * (1.0 - furLayer * 0.5)); - #endif - - #if defined(_EMISSION) - half3 emission = SAMPLE_TEXTURE2D(_EmissionMap, sampler_EmissionMap, input.uv).rgb; - emission *= _EmissionColor.rgb * _EmissionIntensity * (1.0 - furLayer * 0.5); - color.rgb += emission; - #endif - - // Apply per-character color controls - color.rgb = ApplyPerCharacterColorControls(color.rgb); - - // Apply character area color fill - color.rgb = ApplyCharacterAreaColorFill(color.rgb, input.uv, input.positionWS, input.positionCS); - - // Apply dither opacity - ApplyDitherOpacity(input.positionCS, _DitherOpacity); - - // Apply fog - color.rgb = MixFog(color.rgb, input.fogFactor); - - // Final alpha - color.a = furAlpha; - - return color; -} - -// Standard single render target version -half4 frag_fur(Varyings input) : SV_Target -{ - half furAlpha; - return ComputeFurColor(input, furAlpha); -} - -// MRT version: outputs to both color buffer and Fur Mask buffer simultaneously -// This creates the jagged mask effect where only actual rendered fur pixels are marked -FurMRTOutput frag_fur_mrt(Varyings input) -{ - FurMRTOutput output; - - half furAlpha; - output.color = ComputeFurColor(input, furAlpha); - - // Write to Fur Mask Buffer (_NiloToonFurMaskTex): - // Write white (1,1,1,1) where fur pixels are rendered - // This creates a mask that shows exactly where fur is visible - output.prepass = half4(1, 1, 1, 1); - - return output; -} - -// Mask-only version: outputs to PrepassBuffer format -// R: face (not used by fur), G: character area (fur adds here), B: fur area only -// Used for two-pass approach (more compatible than MRT) -half4 frag_fur_mask(Varyings input) : SV_Target -{ - UNITY_SETUP_INSTANCE_ID(input); - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - - // Sample fur noise mask for alpha (default white = full fur) - float2 furNoiseUV = input.uv * _FurNoiseMask_ST.xy + _FurNoiseMask_ST.zw; - half furNoise = SAMPLE_TEXTURE2D(_FurNoiseMask, sampler_FurNoiseMask, furNoiseUV).r; - - // Sample fur mask (where fur appears, default white = everywhere) - float2 furMaskUV = input.uv * _FurMask_ST.xy + _FurMask_ST.zw; - half furMask = SAMPLE_TEXTURE2D(_FurMask, sampler_FurMask, furMaskUV).r; - - // furLayer: 0 = root/base, 1 = tip - half furLayer = saturate(input.furLayer); - - // Calculate fur alpha using lilToon-style non-linear curve - half furLayerShift = furLayer - furLayer * _FurRootOffset + _FurRootOffset; - half furLayerAbs = abs(furLayerShift); - half furAlpha = saturate(furNoise - furLayerShift * furLayerAbs * furLayerAbs * furLayerAbs + 0.25); - - // Apply fur mask - furAlpha *= furMask; - - // Clip pixels that don't pass threshold (same as main fur rendering) - clip(furAlpha - 0.05); - - // Apply Dither Fadeout (mask pass must also respect dither fadeout) - #if _NILOTOON_DITHER_FADEOUT - NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); - #endif - - // Apply dissolve clipping (mask pass must also respect dissolve) - #if _NILOTOON_DISSOLVE - half3 dummyColor = half3(1, 1, 1); - ApplyDissolve(dummyColor, input.uv, input.positionWS, float4(0, 0, 0, 1)); - #endif - - // Output to PrepassBuffer format: - // G channel = character visible area (unified mask for face, body, and fur) - // All character areas use G channel for consistent masking - return half4(0, 1, 0, 0); -} -#endif - -#endif // NILOTOON_CHARACTER_FUR_FRAGMENT_INCLUDED diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl deleted file mode 100644 index 08896fa78..000000000 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl +++ /dev/null @@ -1,192 +0,0 @@ -// NiloToon Character Fur - Geometry Shader -// Shell-based fur generation (based on lilToon implementation) - -#ifndef NILOTOON_CHARACTER_FUR_GEOMETRY_INCLUDED -#define NILOTOON_CHARACTER_FUR_GEOMETRY_INCLUDED - -//------------------------------------------------------------------------------------------------------------------------------ -// Barycentric Interpolation Helper -//------------------------------------------------------------------------------------------------------------------------------ -float LerpBary(float a, float b, float c, float3 factor) { return a * factor.x + b * factor.y + c * factor.z; } -float2 LerpBary(float2 a, float2 b, float2 c, float3 factor) { return a * factor.x + b * factor.y + c * factor.z; } -float3 LerpBary(float3 a, float3 b, float3 c, float3 factor) { return a * factor.x + b * factor.y + c * factor.z; } -float4 LerpBary(float4 a, float4 b, float4 c, float3 factor) { return a * factor.x + b * factor.y + c * factor.z; } - -//------------------------------------------------------------------------------------------------------------------------------ -// Append Single Fur Shell (Base + Tip) -//------------------------------------------------------------------------------------------------------------------------------ -void AppendFurShell( - inout TriangleStream outStream, - V2G input[3], - float3 furVectors[3], - float3 factor, - float layerProgress // 0 = base, 1 = outer -) -{ - Varyings output = (Varyings)0; - - UNITY_TRANSFER_INSTANCE_ID(input[0], output); - UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(input[0], output); - - // Interpolate base attributes - output.uv = LerpBary(input[0].uv, input[1].uv, input[2].uv, factor); - output.normalWS = normalize(LerpBary(input[0].normalWS, input[1].normalWS, input[2].normalWS, factor)); - output.tangentWS = LerpBary(input[0].tangentWS, input[1].tangentWS, input[2].tangentWS, factor); - output.tangentWS.xyz = normalize(output.tangentWS.xyz); - output.fogFactor = LerpBary(input[0].fogFactor, input[1].fogFactor, input[2].fogFactor, factor); - - // Base position (furLayer = 0) - float3 basePositionWS = LerpBary(input[0].positionWS, input[1].positionWS, input[2].positionWS, factor); - - output.positionWS = basePositionWS; - float4 basePositionCS_BeforePerspective = TransformWorldToHClip(basePositionWS); - output.furLayer = 0; - - // Apply Perspective Removal to base - float4 basePositionCS_AfterPerspective = NiloDoPerspectiveRemoval( - basePositionCS_BeforePerspective, - basePositionWS, - _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], - _PerspectiveRemovalRadius, - _PerspectiveRemovalAmount, - _PerspectiveRemovalStartHeight, - _PerspectiveRemovalEndHeight - ); - - output.positionCS = basePositionCS_AfterPerspective; - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - outStream.Append(output); - - // Tip position (furLayer = 1) - // CRITICAL FIX: Transform fur vector to clip space using the SAME perspective removal parameters as base - - // Get the interpolated fur vector in world space - float3 mixedFurVector = LerpBary(furVectors[0], furVectors[1], furVectors[2], factor); - - // Calculate tip in world space (for lighting and shading) - float3 tipPositionWS = basePositionWS + mixedFurVector; - output.positionWS = tipPositionWS; - - // Transform fur vector to clip space by transforming both endpoints - // IMPORTANT: Don't apply perspective removal to tip separately! - // Instead, transform the fur vector in clip space relative to the base - - // Convert the fur vector direction to clip space - // We approximate this by transforming a point at base + furVector - float4 furVectorEndCS_BeforePerspective = TransformWorldToHClip(tipPositionWS); - - // Calculate the fur vector in clip space BEFORE perspective removal - float4 furVectorCS_BeforePerspective = furVectorEndCS_BeforePerspective - basePositionCS_BeforePerspective; - - // Apply the same perspective removal transformation to the fur vector as we did to the base - // This maintains the correct relative offset in perspective-removed space - // The key insight: we want to preserve the fur direction/length relative to the base's transformation - - // Transform the fur vector's XY component using the base's perspective removal scale - // Perspective removal formula: newXY = lerp(originalXY, originalXY * w / centerPosVSz, amount) - // For the fur vector, we need to apply the same scale change - - float3 centerPosWS = _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID]; - float centerPosVSz = mul(UNITY_MATRIX_V, float4(centerPosWS,1)).z; - - // Calculate perspective removal amount for base position - float perspectiveRemovalAreaSphere = saturate(_PerspectiveRemovalRadius - distance(basePositionWS, centerPosWS) / _PerspectiveRemovalRadius); - float perspectiveRemovalAreaWorldHeight = saturate(invLerp(_PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight, basePositionWS.y)); - float perspectiveRemovalFinalAmount = _PerspectiveRemovalAmount * perspectiveRemovalAreaSphere * perspectiveRemovalAreaWorldHeight; - - // Apply perspective removal scale to fur vector - // The scale factor is: lerp(1, w / centerPosVSz, amount) - float basePerspectiveScale = lerp(1.0, abs(basePositionCS_BeforePerspective.w) * rcp(abs(centerPosVSz)), perspectiveRemovalFinalAmount); - - // Scale the fur vector's XY by the same factor - float2 furVectorCS_XY = furVectorCS_BeforePerspective.xy * basePerspectiveScale; - - // Construct the final tip position in clip space - output.positionCS = basePositionCS_AfterPerspective; - output.positionCS.xy += furVectorCS_XY; - output.positionCS.z = furVectorEndCS_BeforePerspective.z; // Keep original Z depth for tip - output.positionCS.w = furVectorEndCS_BeforePerspective.w; // Keep original W for tip - - output.furLayer = layerProgress; - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - outStream.Append(output); -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Geometry Shader - Shell Generation -// Based on lilToon's fur geometry shader -//------------------------------------------------------------------------------------------------------------------------------ -[maxvertexcount(40)] -void geom_fur(triangle V2G input[3], inout TriangleStream outStream) -{ - UNITY_SETUP_INSTANCE_ID(input[0]); - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input[0]); - - // Get fur vectors for each vertex - float3 furVectors[3]; - furVectors[0] = input[0].furVector; - furVectors[1] = input[1].furVector; - furVectors[2] = input[2].furVector; - - // Apply procedural randomization using vertex IDs (from lilToon) - uint3 n0 = (input[0].vertexID * 3 + input[1].vertexID * 1 + input[2].vertexID * 1) * uint3(1597334677U, 3812015801U, 2912667907U); - uint3 n1 = (input[0].vertexID * 1 + input[1].vertexID * 3 + input[2].vertexID * 1) * uint3(1597334677U, 3812015801U, 2912667907U); - uint3 n2 = (input[0].vertexID * 1 + input[1].vertexID * 1 + input[2].vertexID * 3) * uint3(1597334677U, 3812015801U, 2912667907U); - - float3 noise0 = normalize(float3(n0) * (2.0 / float(0xffffffffU)) - 1.0); - float3 noise1 = normalize(float3(n1) * (2.0 / float(0xffffffffU)) - 1.0); - float3 noise2 = normalize(float3(n2) * (2.0 / float(0xffffffffU)) - 1.0); - - furVectors[0] += noise0 * _FurVector.w * _FurRandomize; - furVectors[1] += noise1 * _FurVector.w * _FurRandomize; - furVectors[2] += noise2 * _FurVector.w * _FurRandomize; - - // Generate shells based on layer count - // Layer pattern from lilToon: spreads shells across triangle vertices - - if (_FurLayerNum >= 1) - { - // 3 shells at each vertex - AppendFurShell(outStream, input, furVectors, float3(1.0, 0.0, 0.0), 1.0); - AppendFurShell(outStream, input, furVectors, float3(0.0, 1.0, 0.0), 1.0); - AppendFurShell(outStream, input, furVectors, float3(0.0, 0.0, 1.0), 1.0); - } - - if (_FurLayerNum >= 2) - { - // 3 more shells at edge midpoints - AppendFurShell(outStream, input, furVectors, float3(0.0, 0.5, 0.5), 1.0); - AppendFurShell(outStream, input, furVectors, float3(0.5, 0.0, 0.5), 1.0); - AppendFurShell(outStream, input, furVectors, float3(0.5, 0.5, 0.0), 1.0); - } - - if (_FurLayerNum >= 3) - { - // 6 more shells for dense fur - AppendFurShell(outStream, input, furVectors, float3(1.0/6.0, 4.0/6.0, 1.0/6.0), 1.0); - AppendFurShell(outStream, input, furVectors, float3(0.0, 0.5, 0.5), 0.8); - AppendFurShell(outStream, input, furVectors, float3(1.0/6.0, 1.0/6.0, 4.0/6.0), 1.0); - AppendFurShell(outStream, input, furVectors, float3(0.5, 0.0, 0.5), 0.8); - AppendFurShell(outStream, input, furVectors, float3(4.0/6.0, 1.0/6.0, 1.0/6.0), 1.0); - AppendFurShell(outStream, input, furVectors, float3(0.5, 0.5, 0.0), 0.8); - } - - // Final shell at first vertex to close the strip - AppendFurShell(outStream, input, furVectors, float3(1.0, 0.0, 0.0), 1.0); - - outStream.RestartStrip(); -} - -#endif // NILOTOON_CHARACTER_FUR_GEOMETRY_INCLUDED diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl deleted file mode 100644 index 4c10c3220..000000000 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl +++ /dev/null @@ -1,555 +0,0 @@ -// NiloToon Character Fur - Shared Definitions -// Full-featured structs, CBUFFER, and common functions - -#ifndef NILOTOON_CHARACTER_FUR_SHARED_INCLUDED -#define NILOTOON_CHARACTER_FUR_SHARED_INCLUDED - -#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" -#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" -#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" - -// Include NiloToon utility functions (order matters - InvLerpRemapUtil must come before PerspectiveRemovalUtil) -#include "../../ShaderLibrary/NiloUtilityHLSL/NiloInvLerpRemapUtil.hlsl" -#include "../../ShaderLibrary/NiloUtilityHLSL/NiloBlendEquationUtil.hlsl" -#include "../../ShaderLibrary/NiloUtilityHLSL/NiloDitherFadeoutClipUtil.hlsl" -#include "../../ShaderLibrary/NiloUtilityHLSL/NiloPerspectiveRemovalUtil.hlsl" -#include "../../ShaderLibrary/NiloUtilityHLSL/NiloUVCalculateUtil.hlsl" - -//------------------------------------------------------------------------------------------------------------------------------ -// NiloToon Global Light Override Variables (from NiloToonCharacterMainLightOverrider) -//------------------------------------------------------------------------------------------------------------------------------ -half4 _GlobalUserOverriddenFinalMainLightDirWSParam; // xyz: direction, w: 1 if enabled -half4 _GlobalUserOverriddenFinalMainLightColorParam; // rgb: color, w: 1 if enabled - -//------------------------------------------------------------------------------------------------------------------------------ -// Helper function for view direction (compatible with all URP versions) -//------------------------------------------------------------------------------------------------------------------------------ -float3 GetWorldSpaceViewDirSafe(float3 positionWS) -{ - return normalize(_WorldSpaceCameraPos.xyz - positionWS); -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Helper function for shadow coord (compatible with all URP versions) -//------------------------------------------------------------------------------------------------------------------------------ -float4 GetShadowCoordSafe(VertexPositionInputs vertexInput) -{ - #if defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT) - return ComputeScreenPos(vertexInput.positionCS); - #else - return TransformWorldToShadowCoord(vertexInput.positionWS); - #endif -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Get Main Light with NiloToon Override Support -//------------------------------------------------------------------------------------------------------------------------------ -Light GetMainLightWithNiloToonOverride() -{ - Light mainLight = GetMainLight(); - - // Apply NiloToon MainLightOverrider if enabled - if (_GlobalUserOverriddenFinalMainLightDirWSParam.w > 0.5) - { - mainLight.direction = _GlobalUserOverriddenFinalMainLightDirWSParam.xyz; - } - if (_GlobalUserOverriddenFinalMainLightColorParam.w > 0.5) - { - mainLight.color = _GlobalUserOverriddenFinalMainLightColorParam.rgb; - } - - return mainLight; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// CBUFFER for SRP Batcher -//------------------------------------------------------------------------------------------------------------------------------ -CBUFFER_START(UnityPerMaterial) - // Base - float4 _BaseMap_ST; - half4 _BaseColor; - half _Cutoff; - - // Normal Map - float4 _BumpMap_ST; - half _BumpScale; - - // Fur Shape - float4 _FurNoiseMask_ST; - float4 _FurMask_ST; - float4 _FurLengthMask_ST; - float4 _FurVector; - float4 _FurVectorTex_ST; - half _FurVectorScale; - half _FurGravity; - half _FurRandomize; - half _FurAO; - half _FurLayerNum; - half _FurRootOffset; - - // Fur Rim - half4 _FurRimColor; - half _FurRimFresnelPower; - half _FurRimAntiLight; - - // Cel Shading - half _CelShadeMidPoint; - half _CelShadeSoftness; - - // Shadow Color - half4 _ShadowColor; - half _ShadowBrightness; - half _ShadowHueShift; - half _ShadowSaturationBoost; - half _ShadowValueMultiplier; - - // MatCap Add - float4 _MatCapAddMap_ST; - half4 _MatCapAddColor; - half _MatCapAddIntensity; - float4 _MatCapAddMask_ST; - - // MatCap Multiply - float4 _MatCapMulMap_ST; - half _MatCapMulIntensity; - - // Rim Light - half4 _RimLightColor; - half _RimLightPower; - half _RimLightIntensity; - - // Emission - float4 _EmissionMap_ST; - half4 _EmissionColor; - half _EmissionIntensity; - - // Occlusion - float4 _OcclusionMap_ST; - half _OcclusionStrength; - - // Outline - half _OutlineWidth; - half4 _OutlineColor; - float4 _OutlineWidthMask_ST; - - // Rendering - half _Cull; - half _FurCull; - - // Dissolve - float _DissolveAmount; - float _DissolveMode; - float _DissolveThresholdMapTilingX; - float _DissolveThresholdMapTilingY; - float _DissolveNoiseStrength; - float _DissolveBorderRange; - half4 _DissolveBorderTintColor; - float _AllowPerCharacterDissolve; - - // Per-Character Color Controls - half _PerCharacterBaseColorMultiply; - half4 _PerCharacterBaseColorTint; - half3 _PerCharEffectTintColor; // Set by NiloToonPerCharacterRenderController - half3 _PerCharEffectAddColor; // Set by NiloToonPerCharacterRenderController - half _PerCharEffectDesaturatePercentage; - half4 _PerCharEffectLerpColor; - - // Per-Character Rim Light - half _UsePerCharacterRimLightIntensity; - half _PerCharacterRimLightIntensity; - half4 _PerCharacterRimLightColor; - half _PerCharacterRimLightSharpnessPower; - - // BaseMap Override - half _PerCharacterBaseMapOverrideAmount; - half4 _PerCharacterBaseMapOverrideTintColor; - float4 _PerCharacterBaseMapOverrideMap_ST; - half _PerCharacterBaseMapOverrideBlendMode; - half _PerCharacterBaseMapOverrideUVOption; - - // Character Area Color Fill - half _ShouldRenderCharacterAreaColorFill; - half4 _CharacterAreaColorFillColor; - float4 _CharacterAreaColorFillTexture_ST; - half _CharacterAreaColorFillUVOption; - - // Dither Opacity - half _DitherOpacity; - - // Dither Fadeout - half _DitherFadeoutAmount; - half _DitherFadeoutNormalScaleFix; - half _AllowPerCharacterDitherFadeout; - - // Perspective Removal - half _PerspectiveRemovalAmount; - half _PerspectiveRemovalRadius; - half _PerspectiveRemovalStartHeight; - half _PerspectiveRemovalEndHeight; - - // ZOffset - half _PerCharacterZOffset; - - // Character Bound (for dissolve) - float _CharacterBoundRadius; - - // Character ID (for accessing global arrays) - uint _CharacterID; -CBUFFER_END - -//------------------------------------------------------------------------------------------------------------------------------ -// NiloToon Global Per-Character Arrays -// For properties that change every frame, use global arrays instead of CBUFFER for performance -//------------------------------------------------------------------------------------------------------------------------------ -#ifndef MAX_CHARACTER_COUNT -#define MAX_CHARACTER_COUNT 256 -#endif - -float3 _NiloToonGlobalPerCharHeadBonePosWSArray[MAX_CHARACTER_COUNT]; -float3 _NiloToonGlobalPerCharFaceForwardDirWSArray[MAX_CHARACTER_COUNT]; -float3 _NiloToonGlobalPerCharFaceUpwardDirWSArray[MAX_CHARACTER_COUNT]; -float3 _NiloToonGlobalPerCharBoundCenterPosWSArray[MAX_CHARACTER_COUNT]; - -//------------------------------------------------------------------------------------------------------------------------------ -// Texture Declarations (all textures declared unconditionally to avoid compilation issues) -//------------------------------------------------------------------------------------------------------------------------------ -TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); -TEXTURE2D(_BumpMap); SAMPLER(sampler_BumpMap); - -// Fur textures -TEXTURE2D(_FurNoiseMask); SAMPLER(sampler_FurNoiseMask); -TEXTURE2D(_FurMask); SAMPLER(sampler_FurMask); -TEXTURE2D(_FurLengthMask); SAMPLER(sampler_FurLengthMask); -TEXTURE2D(_FurVectorTex); SAMPLER(sampler_FurVectorTex); - -// MatCap -TEXTURE2D(_MatCapAddMap); SAMPLER(sampler_MatCapAddMap); -TEXTURE2D(_MatCapAddMask); SAMPLER(sampler_MatCapAddMask); -TEXTURE2D(_MatCapMulMap); SAMPLER(sampler_MatCapMulMap); - -// Emission -TEXTURE2D(_EmissionMap); SAMPLER(sampler_EmissionMap); - -// Occlusion -TEXTURE2D(_OcclusionMap); SAMPLER(sampler_OcclusionMap); - -// Outline -TEXTURE2D(_OutlineWidthMask); SAMPLER(sampler_OutlineWidthMask); - -// Dissolve -#if _NILOTOON_DISSOLVE -TEXTURE2D(_DissolveThresholdMap); SAMPLER(sampler_DissolveThresholdMap); -#endif - -// BaseMap Override -TEXTURE2D(_PerCharacterBaseMapOverrideMap); SAMPLER(sampler_PerCharacterBaseMapOverrideMap); - -// Character Area Color Fill -TEXTURE2D(_CharacterAreaColorFillTexture); SAMPLER(sampler_CharacterAreaColorFillTexture); - -//------------------------------------------------------------------------------------------------------------------------------ -// Vertex Input Structure -//------------------------------------------------------------------------------------------------------------------------------ -struct Attributes -{ - float4 positionOS : POSITION; - float3 normalOS : NORMAL; - float4 tangentOS : TANGENT; - float2 uv : TEXCOORD0; - float2 uv2 : TEXCOORD1; - float4 color : COLOR; - uint vertexID : SV_VertexID; - UNITY_VERTEX_INPUT_INSTANCE_ID -}; - -//------------------------------------------------------------------------------------------------------------------------------ -// Vertex to Geometry Structure (for Fur Shell Pass) -//------------------------------------------------------------------------------------------------------------------------------ -struct V2G -{ - float2 uv : TEXCOORD0; - float3 positionWS : TEXCOORD1; - float3 normalWS : TEXCOORD2; - float4 tangentWS : TEXCOORD3; - float3 furVector : TEXCOORD4; - float fogFactor : TEXCOORD5; - uint vertexID : TEXCOORD6; - float4 color : COLOR; - UNITY_VERTEX_INPUT_INSTANCE_ID - UNITY_VERTEX_OUTPUT_STEREO -}; - -//------------------------------------------------------------------------------------------------------------------------------ -// Fragment Input Structure -//------------------------------------------------------------------------------------------------------------------------------ -struct Varyings -{ - float4 positionCS : SV_POSITION; - float2 uv : TEXCOORD0; - float3 positionWS : TEXCOORD1; - float3 normalWS : TEXCOORD2; - float4 tangentWS : TEXCOORD3; - float fogFactor : TEXCOORD4; - float furLayer : TEXCOORD5; // 0 = base, 1 = outer shell - float4 shadowCoord : TEXCOORD6; - UNITY_VERTEX_INPUT_INSTANCE_ID - UNITY_VERTEX_OUTPUT_STEREO -}; - -//------------------------------------------------------------------------------------------------------------------------------ -// Color Space Conversion (RGB <-> HSV) -//------------------------------------------------------------------------------------------------------------------------------ -float3 RGBToHSV(float3 rgb) -{ - float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - float4 p = lerp(float4(rgb.bg, K.wz), float4(rgb.gb, K.xy), step(rgb.b, rgb.g)); - float4 q = lerp(float4(p.xyw, rgb.r), float4(rgb.r, p.yzx), step(p.x, rgb.r)); - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); -} - -float3 HSVToRGB(float3 hsv) -{ - float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - float3 p = abs(frac(hsv.xxx + K.xyz) * 6.0 - K.www); - return hsv.z * lerp(K.xxx, saturate(p - K.xxx), hsv.y); -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Utility: Grayscale -//------------------------------------------------------------------------------------------------------------------------------ -half Grayscale(half3 color) -{ - return dot(color, half3(0.299, 0.587, 0.114)); -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Normal Map Unpacking -//------------------------------------------------------------------------------------------------------------------------------ -half3 UnpackNormalWithScale(half4 packedNormal, half scale) -{ - #if defined(UNITY_NO_DXT5nm) - half3 normal = packedNormal.xyz * 2.0 - 1.0; - #else - half3 normal; - normal.xy = packedNormal.ag * 2.0 - 1.0; - normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy))); - #endif - normal.xy *= scale; - return normalize(normal); -} - -//------------------------------------------------------------------------------------------------------------------------------ -// MatCap UV Calculation -//------------------------------------------------------------------------------------------------------------------------------ -float2 GetMatCapUV(float3 normalWS, float3 viewDirWS) -{ - float3 viewNormal = mul((float3x3)UNITY_MATRIX_V, normalWS); - return viewNormal.xy * 0.5 + 0.5; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Apply HSV Change to Color -//------------------------------------------------------------------------------------------------------------------------------ -half3 ApplyHSVChange(half3 color, half hueOffset, half saturationBoost, half valueMul) -{ - float3 hsv = RGBToHSV(color); - hsv.x = frac(hsv.x + hueOffset); - hsv.y = saturate(hsv.y * saturationBoost); - hsv.z = hsv.z * valueMul; - return HSVToRGB(hsv); -} - -//------------------------------------------------------------------------------------------------------------------------------ -// NiloToon Style Cel Shading (Full Version) -//------------------------------------------------------------------------------------------------------------------------------ -half3 ApplyNiloToonCelShading( - half3 baseColor, - half3 lightColor, - half3 lightDir, - half3 normalWS, - half3 viewDir, - half shadowAttenuation, - half occlusion -) -{ - // Calculate NdotL - half NdotL = dot(normalWS, lightDir); - - // Cel shading with configurable mid point and softness - half halfLambert = NdotL * 0.5 + 0.5; - half celShadeResult = smoothstep( - _CelShadeMidPoint + 0.5 - _CelShadeSoftness, - _CelShadeMidPoint + 0.5 + _CelShadeSoftness, - halfLambert - ); - - // Apply shadow map attenuation - celShadeResult *= shadowAttenuation; - - // Apply occlusion - celShadeResult *= occlusion; - - half3 finalColor = baseColor; - - #if defined(_SHADOW_COLOR) - // Apply HSV adjustment to shadow - half3 shadowAlbedo = ApplyHSVChange( - baseColor, - _ShadowHueShift, - _ShadowSaturationBoost, - _ShadowValueMultiplier - ); - - // Apply shadow tint and brightness - shadowAlbedo *= _ShadowColor.rgb * _ShadowBrightness; - - // Blend between shadow and lit based on cel shade result - finalColor = lerp(shadowAlbedo, baseColor, celShadeResult); - #else - // Simple brightness reduction in shadow - finalColor = lerp(baseColor * 0.5, baseColor, celShadeResult); - #endif - - // Apply light color - finalColor *= lightColor; - - return finalColor; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Fur Vector Calculation (from lilToon) -//------------------------------------------------------------------------------------------------------------------------------ -float3 CalculateFurVector(float3 normalOS, float4 tangentOS, float2 uv, float4 vertexColor, bool useVertexColor) -{ - // Build TBN matrix - float3 bitangentOS = normalize(cross(normalOS, tangentOS.xyz)) * (tangentOS.w * length(normalOS)); - float3x3 tbnOS = float3x3(tangentOS.xyz, bitangentOS, normalOS); - - // Start with base fur vector - float3 furVector = _FurVector.xyz + float3(0, 0, 0.001); - - // Optional: blend with vertex color - if (useVertexColor) - { - float3 vertexNormal = vertexColor.xyz * 2.0 - 1.0; - furVector = normalize(furVector + vertexNormal); - } - - // Transform to tangent space, then apply fur direction texture - #if defined(NILOTOON_FUR_SHELL_PASS) - float4 furDirTex = SAMPLE_TEXTURE2D_LOD(_FurVectorTex, sampler_FurVectorTex, uv * _FurVectorTex_ST.xy + _FurVectorTex_ST.zw, 0); - float3 furDirFromTex = UnpackNormalWithScale(furDirTex, _FurVectorScale); - furVector = normalize(furVector + furDirFromTex); - #endif - - // Transform to object space direction - furVector = mul(normalize(furVector), tbnOS); - furVector *= _FurVector.w; - - // Apply gravity - float furLength = length(furVector); - furVector.y -= _FurGravity * furLength; - - return furVector; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// Base Pass Vertex Shader -//------------------------------------------------------------------------------------------------------------------------------ -#if defined(NILOTOON_FUR_BASE_PASS) -Varyings vert(Attributes input) -{ - Varyings output = (Varyings)0; - - UNITY_SETUP_INSTANCE_ID(input); - UNITY_TRANSFER_INSTANCE_ID(input, output); - UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - - // Transform - VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); - VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS); - - output.positionCS = vertexInput.positionCS; - output.positionWS = vertexInput.positionWS; - output.normalWS = normalInput.normalWS; - output.tangentWS = float4(normalInput.tangentWS, input.tangentOS.w); - output.uv = TRANSFORM_TEX(input.uv, _BaseMap); - - // Apply Perspective Removal - output.positionCS = NiloDoPerspectiveRemoval( - output.positionCS, - output.positionWS, - _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], - _PerspectiveRemovalRadius, - _PerspectiveRemovalAmount, - _PerspectiveRemovalStartHeight, - _PerspectiveRemovalEndHeight - ); - - // Apply per-character Z offset - if (_PerCharacterZOffset != 0) - { - output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; - } - - // Shadow coord - output.shadowCoord = GetShadowCoordSafe(vertexInput); - - // Fog - output.fogFactor = ComputeFogFactor(vertexInput.positionCS.z); - - // Base pass has no fur layer - output.furLayer = -1.0; - - return output; -} -#endif - -//------------------------------------------------------------------------------------------------------------------------------ -// Fur Pass Vertex Shader (outputs to Geometry Shader) -//------------------------------------------------------------------------------------------------------------------------------ -#if defined(NILOTOON_FUR_SHELL_PASS) -V2G vert_fur(Attributes input) -{ - V2G output = (V2G)0; - - UNITY_SETUP_INSTANCE_ID(input); - UNITY_TRANSFER_INSTANCE_ID(input, output); - UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - - // Transform position and normal to world space - // IMPORTANT: Use GetVertexPositionInputs to match Base Pass transformation exactly - VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); - VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS); - - output.positionWS = vertexInput.positionWS; - output.normalWS = normalInput.normalWS; - output.tangentWS = float4(normalInput.tangentWS, input.tangentOS.w); - output.uv = TRANSFORM_TEX(input.uv, _BaseMap); - output.color = input.color; - output.vertexID = input.vertexID; - - // Calculate fur vector in world space - float3 furVectorOS = CalculateFurVector(input.normalOS, input.tangentOS, input.uv, input.color, false); - output.furVector = TransformObjectToWorldDir(furVectorOS, false); - - // Apply fur length mask - float furLengthMask = SAMPLE_TEXTURE2D_LOD(_FurLengthMask, sampler_FurLengthMask, input.uv * _FurLengthMask_ST.xy + _FurLengthMask_ST.zw, 0).r; - output.furVector *= furLengthMask; - - // Note: Perspective Removal and Z offset will be applied in geometry shader - // We don't apply them here in vertex shader for fur shells - // because geometry shader generates multiple shells and needs to apply - // the transformations consistently to all generated vertices - - // Fog - float4 posCS = TransformWorldToHClip(output.positionWS); - output.fogFactor = ComputeFogFactor(posCS.z); - - return output; -} -#endif - -#endif // NILOTOON_CHARACTER_FUR_SHARED_INCLUDED diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl new file mode 100644 index 000000000..943e7b1cf --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// Fur geometry shader for NiloToonCharacter — lilToon-style barycentric fur shell generation. +// Adapted from lilToon's lil_common_vert_fur.hlsl (AppendFur / geom functions). +// +// This file is included by the fur pass blocks in NiloToonCharacter.shader, +// AFTER NiloToonCharacter_Shared.hlsl (so Varyings struct and all helpers are available). + +#pragma once + +// NiloFurUtil.hlsl is already included via NiloAllUtilIncludes.hlsl -> Shared.hlsl. +// Do NOT include it again here — duplicate include causes "redefinition of NiloLerp3" +// because Unity may resolve relative vs absolute paths differently, bypassing #pragma once. + +//============================================================================= +// InterpolateVaryings — single source of truth for Varyings struct interpolation. +// +// ** MAINTENANCE NOTE ** +// When a field is added to or removed from the Varyings struct in +// NiloToonCharacter_Shared.hlsl, this function MUST be updated to match. +// A corresponding comment exists at the Varyings struct definition. +//============================================================================= +Varyings InterpolateVaryings(Varyings a, Varyings b, Varyings c, float3 f) +{ + Varyings r = (Varyings)0; + + // positionCS will be recomputed from interpolated positionWS by the caller + // r.positionCS is left as 0 here + + r.uv01 = NiloLerp3(a.uv01, b.uv01, c.uv01, f); + r.uv23 = NiloLerp3(a.uv23, b.uv23, c.uv23, f); + + r.positionWS_ZOffsetFinalSum = NiloLerp3(a.positionWS_ZOffsetFinalSum, b.positionWS_ZOffsetFinalSum, c.positionWS_ZOffsetFinalSum, f); + + r.SH_fogFactor = NiloLerp3(a.SH_fogFactor, b.SH_fogFactor, c.SH_fogFactor, f); + r.normalWS_averageShadowAttenuation = NiloLerp3(a.normalWS_averageShadowAttenuation, b.normalWS_averageShadowAttenuation, c.normalWS_averageShadowAttenuation, f); + + r.smoothedNormalWS = NiloLerp3(a.smoothedNormalWS, b.smoothedNormalWS, c.smoothedNormalWS, f); + +#if VaryingsHasViewDirTS + r.viewDirTS = NiloLerp3(a.viewDirTS, b.viewDirTS, c.viewDirTS, f); +#endif + +#if VaryingsHasTangentWS + r.tangentWS = NiloLerp3(a.tangentWS, b.tangentWS, c.tangentWS, f); +#endif + + r.color = NiloLerp3(a.color, b.color, c.color, f); + +#if _NILOTOON_DEBUG_SHADING + r.uv8 = NiloLerp3(a.uv8, b.uv8, c.uv8, f); +#endif + + // Fur-specific fields + r.furVector = NiloLerp3(a.furVector, b.furVector, c.furVector, f); + r.furLayer = 0; // caller sets this + r.furVertexID = a.furVertexID; // not consumed after geometry; keep the nointerpolation field initialized + + // GPU instancing / stereo +#if !NiloToonCharSelfShadowCasterPass + UNITY_TRANSFER_INSTANCE_ID(a, r); + UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(a, r); +#endif + + return r; +} + +void NiloApplyFurDepthPrepassZBias(inout float4 positionCS, float bias) +{ +#if UNITY_REVERSED_Z + positionCS.z -= bias; +#else + positionCS.z += bias; +#endif +} + +//============================================================================= +// AppendFurQuad — emit 2 vertices (base + tip) forming one fur quad edge. +// Adapted from lilToon's AppendFur() in lil_common_vert_fur.hlsl lines 256-371. +//============================================================================= +void AppendFurQuad( + inout TriangleStream outStream, + Varyings input[3], + float3 furVectors[3], + float3 factor) +{ + Varyings output = InterpolateVaryings(input[0], input[1], input[2], factor); + float3 posWS = output.positionWS_ZOffsetFinalSum.xyz; + + // Base vertex (furLayer = 0) — at original mesh surface + output.furLayer = 0; + output.positionCS = TransformWorldToHClip(posWS); +#if NiloToonFurDepthPrepassPass || NiloToonFurPrepassBufferDepthPass + NiloApplyFurDepthPrepassZBias(output.positionCS, 0.0000001); +#endif + outStream.Append(output); + + // Tip vertex (furLayer = 1) — displaced by fur vector + float3 mixVector = NiloLerp3(furVectors[0], furVectors[1], furVectors[2], factor); + posWS += mixVector; + output.positionWS_ZOffsetFinalSum.xyz = posWS; + output.furLayer = 1; + output.positionCS = TransformWorldToHClip(posWS); +#if NiloToonFurDepthPrepassPass || NiloToonFurPrepassBufferDepthPass + NiloApplyFurDepthPrepassZBias(output.positionCS, 0.000001); +#endif + outStream.Append(output); +} + +//============================================================================= +// FurShellGeom — geometry shader entry point. +// Receives one triangle, emits fur shell quads using lilToon's barycentric layout. +// Adapted from lilToon's geom() in lil_common_vert_fur.hlsl lines 375-503. +// +// D3D11 geometry shader limit: maxvertexcount × output_scalars ≤ 1024. +// NiloToon's Varyings struct is large (40-48 scalars depending on keywords) +// because fur reuses the full toon lighting pipeline (0% fragment duplication). +// This limits us to layer 1-2 (max 14 verts). 14 × 48 = 672, safely under 1024. +// (lilToon supports layer 3 because its v2f struct is much smaller.) +// +// maxvertexcount breakdown: +// LayerNum == 1: 3 AppendFurQuad calls × 2 verts = 6 + closing 2 = 8 +// LayerNum == 2: 6 AppendFurQuad calls × 2 verts = 12 + closing 2 = 14 +//============================================================================= +[maxvertexcount(14)] +void FurShellGeom(triangle Varyings input[3], inout TriangleStream outStream) +{ + // When _NILOTOON_FUR keyword is not enabled on this material, emit nothing. + // The renderer feature still enqueues the fur pass for all materials, + // but only materials with the keyword active should actually produce fur shells. +#if !_NILOTOON_FUR + return; +#endif + + // Per-vertex fur vectors (already computed in vertex shader) + float3 furVectors[3]; + furVectors[0] = input[0].furVector; + furVectors[1] = input[1].furVector; + furVectors[2] = input[2].furVector; + + // Per-vertex noise randomization using stable vertex ID hashing (from lilToon lines 461-469). + // Do not hash positionWS here: object rotation changes world positions and makes randomize flicker. + uint h0 = input[0].furVertexID; + uint h1 = input[1].furVertexID; + uint h2 = input[2].furVertexID; + + uint3 n0 = (h0 * 3u + h1 * 1u + h2 * 1u) * uint3(1597334677u, 3812015801u, 2912667907u); + uint3 n1 = (h0 * 1u + h1 * 3u + h2 * 1u) * uint3(1597334677u, 3812015801u, 2912667907u); + uint3 n2 = (h0 * 1u + h1 * 1u + h2 * 3u) * uint3(1597334677u, 3812015801u, 2912667907u); + + float3 noise0 = normalize(float3(n0) * (2.0 / float(0xFFFFFFFFu)) - 1.0); + float3 noise1 = normalize(float3(n1) * (2.0 / float(0xFFFFFFFFu)) - 1.0); + float3 noise2 = normalize(float3(n2) * (2.0 / float(0xFFFFFFFFu)) - 1.0); + + float randomizedFurLength = _NiloFurLength * _NiloFurStrength * _NiloFurRandomize; + furVectors[0] += noise0 * randomizedFurLength; + furVectors[1] += noise1 * randomizedFurLength; + furVectors[2] += noise2 * randomizedFurLength; + + // Per-vertex fur length mask (from lilToon lines 471-475) + // Sample in geometry shader via tex2Dlod (explicit mip 0) to scale fur length per-vertex + float2 uv0 = input[0].uv01.xy; + float2 uv1 = input[1].uv01.xy; + float2 uv2 = input[2].uv01.xy; + furVectors[0] *= SAMPLE_TEXTURE2D_LOD(_NiloFurLengthMask, sampler_linear_repeat, uv0, 0).r; + furVectors[1] *= SAMPLE_TEXTURE2D_LOD(_NiloFurLengthMask, sampler_linear_repeat, uv1, 0).r; + furVectors[2] *= SAMPLE_TEXTURE2D_LOD(_NiloFurLengthMask, sampler_linear_repeat, uv2, 0).r; + + // _FurCutoutLength is now applied in the vertex shader (only for depth prepass). + // Color pass gets full-length fur — the outer portion blends softly (lilToon FurTwoPass design). + + // Emit fur quads using lilToon's barycentric layout (lines 477-502). + // Layer count limited to 1-2 due to D3D11 geometry shader output limit + // (maxvertexcount × scalars_per_vertex ≤ 1024). NiloToon's full Varyings + // struct is too large for layer 3 (would need 26 verts × 39+ scalars > 1024). + float layerNum = _NiloFurLayerNum; + + if (layerNum < 1.5) // LayerNum == 1: vertices only (3 quads = 6 verts) + { + AppendFurQuad(outStream, input, furVectors, float3(1.0, 0.0, 0.0)); + AppendFurQuad(outStream, input, furVectors, float3(0.0, 1.0, 0.0)); + AppendFurQuad(outStream, input, furVectors, float3(0.0, 0.0, 1.0)); + } + else // LayerNum == 2: interleaved vertices + midpoints (6 quads = 12 verts) + { + // lilToon interleaves: vertex A, midpoint BC, vertex B, midpoint AC, vertex C, midpoint AB + // This creates a valid continuous triangle strip. + AppendFurQuad(outStream, input, furVectors, float3(1.0, 0.0, 0.0)); // vertex A + AppendFurQuad(outStream, input, furVectors, float3(0.0, 1.0, 1.0) / 2.0); // midpoint BC + AppendFurQuad(outStream, input, furVectors, float3(0.0, 1.0, 0.0)); // vertex B + AppendFurQuad(outStream, input, furVectors, float3(1.0, 0.0, 1.0) / 2.0); // midpoint AC + AppendFurQuad(outStream, input, furVectors, float3(0.0, 0.0, 1.0)); // vertex C + AppendFurQuad(outStream, input, furVectors, float3(1.0, 1.0, 0.0) / 2.0); // midpoint AB + } + + // Closing vertex + restart strip (matches lilToon line 502) + AppendFurQuad(outStream, input, furVectors, float3(1.0, 0.0, 0.0)); + outStream.RestartStrip(); +} diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl.meta new file mode 100644 index 000000000..537b458b8 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_FurGeom.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9abd11236fee43b4ab4b8629e2545d46 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Fragment.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Fragment.hlsl new file mode 100644 index 000000000..a4d1fb295 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Fragment.hlsl @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +#if NiloToonIsAnyFurPass && _NILOTOON_FUR +float ComputeNiloToonFurNoise(float2 uv) +{ + float2 furUV = uv * _NiloFurNoiseTiling.xy + _NiloFurNoiseTiling.zw; + return SAMPLE_TEXTURE2D(_NiloFurNoiseTex, sampler_linear_repeat, furUV).r; +} + +float ComputeNiloToonFurAlphaAndClip(float2 uv, float furLayer, float furNoise) +{ + float furMask = SAMPLE_TEXTURE2D(_NiloFurMask, sampler_linear_repeat, uv).r; + + #if NiloToonFurDepthPrepassPass || NiloToonFurPrepassBufferDepthPass + float furAlpha = NiloFurAlphaCutout(furLayer, _NiloFurRootOffset, furNoise, furMask); + if (furAlpha == 0) discard; + #else + float furAlpha = NiloFurAlpha(furLayer, _NiloFurRootOffset, furNoise, furMask); + clip(furAlpha - 0.001); + #endif + return furAlpha; +} + +void ApplyNiloToonFurOcclusionShadowAO(inout ToonSurfaceData surfaceData, Varyings input, float furNoise) +{ + float furLengthScaled = _NiloFurLength * _NiloFurStrength; + float furAOLengthScale = saturate(furLengthScaled / 0.015); + float furOcclusion = lerp(1.0, input.furLayer, _NiloFurOcclusionShadowAO * furAOLengthScale); + surfaceData.occlusion *= furOcclusion; +} + +void ApplyNiloToonFurColorDarkenAO(inout half3 color, Varyings input, float furNoise) +{ + UNITY_BRANCH + if (_NiloFurColorDarkenAO <= 0) + return; + + #if NiloToonFurDepthPrepassPass + // Cutout color+depth prepass: match lilToon's FUR_PRE root darkening without sampling noise again. + float scaledColorAO = _NiloFurColorDarkenAO * saturate(1.0 - fwidth(input.furLayer)); + color *= input.furLayer * scaledColorAO * 2.0 + 1.0 - scaledColorAO; + #else + // Transparent color pass: reuse the fur noise already sampled for alpha. + float colorAOMask = saturate(1.0 - furNoise + furNoise * input.furLayer); + color *= colorAOMask * _NiloFurColorDarkenAO * 1.25 + 1.0 - _NiloFurColorDarkenAO; + #endif +} + +void ApplyNiloToonFurAlphaMaskAndRim( + inout half3 color, + inout ToonSurfaceData surfaceData, + Varyings input, + ToonLightingData lightingData, + float furNoise) +{ + if (_NiloFurShowOnSkinFace < 0.5) + { + half skinFaceArea = max(lightingData.isFaceArea, lightingData.isSkinArea); + clip(0.5 - skinFaceArea); + } + + surfaceData.alpha = ComputeNiloToonFurAlphaAndClip(input.uv01.xy, input.furLayer, furNoise); + + float3 furNormalWS = normalize(input.normalWS_averageShadowAttenuation.xyz); + float3 furViewDirWS = lightingData.viewDirectionWS; + half3 furLightColor = min(lightingData.mainLight.color, 1.0); + half3 furInvLighting = saturate((1.0 - furLightColor) * sqrt(furLightColor)); + half furInvLightingGray = dot(furInvLighting, 1.0 / 3.0); + color += NiloFurRim(input.furLayer, furNormalWS, furViewDirWS, + _NiloFurRimColor, _NiloFurRimFresnelPower, _NiloFurRimAntiLight, furInvLightingGray) * furLightColor; +} +#endif diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Fragment.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Fragment.hlsl.meta new file mode 100644 index 000000000..2d367dd65 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Fragment.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9d957f06e02c4836aece8c3251663376 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_PrepassBuffer.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_PrepassBuffer.hlsl new file mode 100644 index 000000000..f318fa8a6 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_PrepassBuffer.hlsl @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +#if NiloToonFurPrepassBufferPass +float4 FurNiloToonPrepassBufferColorOutput(Varyings input, FRONT_FACE_TYPE IsFrontFace : FRONT_FACE_SEMANTIC) : SV_TARGET +{ + BaseColorAlphaClipTest(input, IsFrontFace); + +#if _NILOTOON_FUR + float furNoise = ComputeNiloToonFurNoise(input.uv01.xy); + float furAlpha = ComputeNiloToonFurAlphaAndClip(input.uv01.xy, input.furLayer, furNoise); + + if (_NiloFurShowOnSkinFace < 0.5) + { + half skinFaceArea = max(GetFaceArea(input.uv01.xy), GetSkinArea(input.uv01.xy)); + clip(0.5 - skinFaceArea); + } +#else + discard; + float furAlpha = 0; +#endif + + float sceneLinearDepth = Convert_SV_PositionZ_ToLinearViewSpaceDepth(LoadSceneDepth(input.positionCS.xy)); + float selfLinearDepth = Convert_SV_PositionZ_ToLinearViewSpaceDepth(input.positionCS.z); + + float depthBias = -0.0001; + float2 depthGradient = float2(ddx(selfLinearDepth), ddy(selfLinearDepth)); + float gradientBias = length(depthGradient) * 0.5; + depthBias = depthBias - gradientBias; + + if(sceneLinearDepth < selfLinearDepth + depthBias) + return 0; + + float isFace = GetFaceArea(input.uv01.xy); + float4 prepassOutput = float4(isFace, _AllowNiloToonBloomCharacterAreaOverride * _AllowedNiloToonBloomOverrideStrength, 0, 1); + +#if !NiloToonFurPrepassBufferDepthPass + prepassOutput.a = furAlpha; +#endif + + return prepassOutput; +} +#endif diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_PrepassBuffer.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_PrepassBuffer.hlsl.meta new file mode 100644 index 000000000..c35cb0fbb --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_PrepassBuffer.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bf10aac6613f4b41bdcf313ea2bc630d +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Textures.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Textures.hlsl new file mode 100644 index 000000000..dcf3208ed --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Textures.hlsl @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +#if NiloToonIsAnyFurPass + TEXTURE2D(_NiloFurNoiseTex); + TEXTURE2D(_NiloFurMask); + TEXTURE2D(_NiloFurLengthMask); + #if _NILOTOON_FUR_VECTORTEX + sampler2D _NiloFurVectorTex; + #endif +#endif diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Textures.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Textures.hlsl.meta new file mode 100644 index 000000000..b7e23c5e9 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Textures.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e4f04ee117d9417487801baeb4d4fcad +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Uniforms.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Uniforms.hlsl new file mode 100644 index 000000000..3faf482c9 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Uniforms.hlsl @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// Included inside UnityPerMaterial CBUFFER. +// Do not add preprocessor conditionals here. SRP Batcher requires identical CBUFFER layout across variants. + +float4 _NiloFurNoiseTiling; // xy = tiling, zw = offset +float4 _NiloFurVector; // xyz = tangent-space direction; use _NiloFurLength for length +float _NiloFurLength; +float _NiloFurStrength; +float4 _NiloFurRimColor; +float _NiloFurGravity; +float _NiloFurOcclusionShadowAO; +float _NiloFurColorDarkenAO; +float _NiloFurRootOffset; +float _NiloFurRandomize; +float _NiloFurRimFresnelPower; +float _NiloFurRimAntiLight; +float _NiloFurVectorScale; +float _NiloFurCutoutLength; +float _NiloFurLayerNum; +float _NiloFurCull; +float _VertexColor2FurVector; +float _EnableFur; +float _NiloFurShowOnSkinFace; diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Uniforms.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Uniforms.hlsl.meta new file mode 100644 index 000000000..c72d5ecf5 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Uniforms.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1680d183b58a4909a0535bc17b4e66ae +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Vertex.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Vertex.hlsl new file mode 100644 index 000000000..b6c423ea8 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Vertex.hlsl @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +#if NiloToonIsAnyFurPass +void ApplyNiloToonFurVertexData(inout Varyings output, Attributes input) +{ + float3 furVectorTexTS = float3(0.0, 0.0, 1.0); + float useFurVectorTex = 0.0; + #if _NILOTOON_FUR_VECTORTEX + { + furVectorTexTS = UnpackNormalScale(tex2Dlod(_NiloFurVectorTex, float4(input.uv, 0, 0)), _NiloFurVectorScale); + useFurVectorTex = 1.0; + } + #endif + + float furCutoutLength = 1.0; + #if NiloToonFurDepthPrepassPass || NiloToonFurPrepassBufferDepthPass + furCutoutLength = _NiloFurCutoutLength; + #endif + + output.furVector = NiloComputeFurVectorWS( + _NiloFurVector.xyz, + _NiloFurLength * _NiloFurStrength, + furCutoutLength, + input.normalOS, + input.tangentOS, + _NiloFurGravity, + input.color.rgb, + _VertexColor2FurVector, + furVectorTexTS, + useFurVectorTex); + + output.furLayer = 0; + output.furVertexID = input.vertexID; +} +#endif diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Vertex.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Vertex.hlsl.meta new file mode 100644 index 000000000..6c0178d93 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Fur_Vertex.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b41d833a8151410aab0e61541162709d +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericMatCap.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericMatCap.hlsl new file mode 100644 index 000000000..46b94cb45 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericMatCap.hlsl @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +half3 BlendGenericMatCapColor(half3 dstCol, half3 srcCol, half3 srcA, uint blendMode) +{ + half3 add = dstCol + srcCol; + half3 mul = dstCol * srcCol; + half3 outCol = dstCol; + + if (blendMode == 0) outCol = srcCol; + else if (blendMode == 1) outCol = add; + else if (blendMode == 2) outCol = max(add - mul, dstCol); + else if (blendMode == 3) outCol = mul; + + return lerp(dstCol, outCol, srcA); +} + +float3 GetGenericMatCapCameraUpWS() +{ + return float3(UNITY_MATRIX_I_V[0][1], UNITY_MATRIX_I_V[1][1], UNITY_MATRIX_I_V[2][1]); +} + +float3 GetGenericMatCapCameraForwardWS() +{ + return normalize(-float3(UNITY_MATRIX_I_V[0][2], UNITY_MATRIX_I_V[1][2], UNITY_MATRIX_I_V[2][2])); +} + +float2 CalcGenericMatCapUV(float2 uv1, float3 normalWS, ToonLightingData lightingData, float4 mapST, float4 blendUV1, half zRotCancel, half perspective, half vrParallaxStrength) +{ + // VR stereo fix: head direction = HMD-center based (stable across eyes), + // viewDirection = per-eye (parallax-correct). The vrParallaxStrength slider + // lerps between "stable (0)" and "per-eye parallax (1)". Without this fix, + // both vectors were equal and the slider had no effect. + float3 headDirectionWS = GetMatCapHeadDirectionWS(lightingData.positionWS, lightingData.viewDirectionWS); + float3 viewDirectionWS = lightingData.viewDirectionWS; + float3 normalVD = normalize(lerp(headDirectionWS, viewDirectionWS, vrParallaxStrength)); + + if (unity_OrthoParams.w > 0.5 || perspective < 0.5) + { + normalVD = GetGenericMatCapCameraForwardWS(); + } + + float3 bitangentVD = zRotCancel > 0.5 ? float3(0, 1, 0) : GetGenericMatCapCameraUpWS(); + bitangentVD = normalize(bitangentVD - normalVD * dot(bitangentVD, normalVD)); + float3 tangentVD = cross(normalVD, bitangentVD); + + float2 uvMat = float2(dot(tangentVD, normalWS), dot(bitangentVD, normalWS)); + uvMat = lerp(uvMat, saturate(uv1) * 2 - 1, blendUV1.xy); + uvMat = uvMat * mapST.xy + mapST.zw; + + return uvMat * 0.5 + 0.5; +} + +// lilToon-faithful matcap is applied as a post-light decoration on the lit color, +// not as a pre-light albedo modifier. Inner guard makes the body empty unless the +// shader keyword is on AND we are in the ForwardLit pass (matcap should not affect +// outline / shadow / depth / stencil passes). +void ApplyGenericMatCap1(inout half3 color, ToonSurfaceData surfaceData, Varyings varyings, ToonLightingData lightingData) +{ +#if _GENERIC_MATCAP1 && NiloToonForwardLitPass && !_NILOTOON_FUR + half3 normalWS = normalize(lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _GenericMatCap1NormalStrength)); + + #if _GENERIC_MATCAP1_CUSTOM_NORMAL + float2 bumpUv = CalcUV(GetUV(varyings), _GenericMatCap1BumpMap_ST); + half3 customNormalTS = UnpackNormalScale(tex2D(_GenericMatCap1BumpMap, bumpUv), _GenericMatCap1BumpScale); + normalWS = NormalizeNormalPerPixel(TransformTangentToWorld(customNormalTS, lightingData.TBN_WS)); + #endif + + float2 matCapUv = CalcGenericMatCapUV(GetUV(varyings, 1), normalWS, lightingData, _GenericMatCap1Map_ST, _GenericMatCap1BlendUV1, _GenericMatCap1ZRotCancel, _GenericMatCap1Perspective, _GenericMatCap1VRParallaxStrength); + half4 matCapColor = _GenericMatCap1Color * tex2Dlod(_GenericMatCap1Map, float4(matCapUv, 0, _GenericMatCap1Lod)); + matCapColor.rgb = lerp(matCapColor.rgb, matCapColor.rgb * saturate(lightingData.mainLight.color), _GenericMatCap1EnableLighting); + matCapColor.a = lerp(matCapColor.a, matCapColor.a * lightingData.averageShadowAttenuation, _GenericMatCap1ShadowMask); + + if (_GenericMatCap1ApplyTransparency > 0.5) + { + matCapColor.a *= surfaceData.alpha; + } + + matCapColor.a = lightingData.facing < (_GenericMatCap1BackfaceMask - 1.0) ? 0.0 : matCapColor.a; + + float2 maskUv = CalcUV(GetUV(varyings), _GenericMatCap1Mask_ST); + half3 matCapMask = tex2D(_GenericMatCap1Mask, maskUv).rgb; + matCapColor.rgb = lerp(matCapColor.rgb, matCapColor.rgb * surfaceData.albedo, _GenericMatCap1MainStrength); + color = BlendGenericMatCapColor(color, matCapColor.rgb, _GenericMatCap1Blend * matCapColor.a * matCapMask, _GenericMatCap1BlendMode); +#endif +} + +void ApplyGenericMatCap2(inout half3 color, ToonSurfaceData surfaceData, Varyings varyings, ToonLightingData lightingData) +{ +#if _GENERIC_MATCAP2 && NiloToonForwardLitPass && !_NILOTOON_FUR + half3 normalWS = normalize(lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _GenericMatCap2NormalStrength)); + + #if _GENERIC_MATCAP2_CUSTOM_NORMAL + float2 bumpUv = CalcUV(GetUV(varyings), _GenericMatCap2BumpMap_ST); + half3 customNormalTS = UnpackNormalScale(tex2D(_GenericMatCap2BumpMap, bumpUv), _GenericMatCap2BumpScale); + normalWS = NormalizeNormalPerPixel(TransformTangentToWorld(customNormalTS, lightingData.TBN_WS)); + #endif + + float2 matCapUv = CalcGenericMatCapUV(GetUV(varyings, 1), normalWS, lightingData, _GenericMatCap2Map_ST, _GenericMatCap2BlendUV1, _GenericMatCap2ZRotCancel, _GenericMatCap2Perspective, _GenericMatCap2VRParallaxStrength); + half4 matCapColor = _GenericMatCap2Color * tex2Dlod(_GenericMatCap2Map, float4(matCapUv, 0, _GenericMatCap2Lod)); + matCapColor.rgb = lerp(matCapColor.rgb, matCapColor.rgb * saturate(lightingData.mainLight.color), _GenericMatCap2EnableLighting); + matCapColor.a = lerp(matCapColor.a, matCapColor.a * lightingData.averageShadowAttenuation, _GenericMatCap2ShadowMask); + + if (_GenericMatCap2ApplyTransparency > 0.5) + { + matCapColor.a *= surfaceData.alpha; + } + + matCapColor.a = lightingData.facing < (_GenericMatCap2BackfaceMask - 1.0) ? 0.0 : matCapColor.a; + + float2 maskUv = CalcUV(GetUV(varyings), _GenericMatCap2Mask_ST); + half3 matCapMask = tex2D(_GenericMatCap2Mask, maskUv).rgb; + matCapColor.rgb = lerp(matCapColor.rgb, matCapColor.rgb * surfaceData.albedo, _GenericMatCap2MainStrength); + color = BlendGenericMatCapColor(color, matCapColor.rgb, _GenericMatCap2Blend * matCapColor.a * matCapMask, _GenericMatCap2BlendMode); +#endif +} diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericMatCap.hlsl.meta similarity index 75% rename from Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl.meta rename to Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericMatCap.hlsl.meta index f886f4585..8b18c8a3b 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl.meta +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericMatCap.hlsl.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 433eaffdfbbdaff41b9794f5adc9878a +guid: 2b5945c68eb04394e882e97b34e66537 ShaderIncludeImporter: externalObjects: {} userData: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericReflection.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericReflection.hlsl new file mode 100644 index 000000000..47ca164ba --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericReflection.hlsl @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +#if _GENERIC_REFLECTION +half3 BlendGenericReflectionColor(half3 dstCol, half3 srcCol, half3 srcA, uint blendMode) +{ + half3 add = dstCol + srcCol; + half3 mul = dstCol * srcCol; + half3 outCol = dstCol; + + if (blendMode == 0) outCol = srcCol; + else if (blendMode == 1) outCol = add; + else if (blendMode == 2) outCol = max(add - mul, dstCol); + else if (blendMode == 3) outCol = mul; + + return lerp(dstCol, outCol, srcA); +} + +half GenericReflectionTooningScale(half value, half border, half blur) +{ + half borderMin = saturate(border - blur * 0.5h); + half borderMax = saturate(border + blur * 0.5h); + return saturate((value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * _lilAAStrength)); +} + +void GenericReflectionGSAAForSmoothness(inout half smoothness, half3 normalWS, half strength) +{ + float3 dx = abs(ddx(normalWS)); + float3 dy = abs(ddy(normalWS)); + float dxy = max(dot(dx, dx), dot(dy, dy)); + float roughnessGSAA = dxy / (dxy * 5.0 + 0.002) * strength; + smoothness = min(smoothness, saturate(1.0h - roughnessGSAA)); +} + +half3 GenericReflectionFresnelTerm(half3 f0, half cosA) +{ + half a = 1.0h - cosA; + half a5 = a * a * a * a * a; + return f0 + (1.0h - f0) * a5; +} + +half3 GenericReflectionFresnelLerp(half3 f0, half3 f90, half cosA) +{ + half a = 1.0h - cosA; + half a5 = a * a * a * a * a; + return lerp(f0, f90, a5); +} + +half3 DecodeGenericReflectionCubemap(half4 data) +{ + half alpha = _GenericReflectionCubemap_HDR.w * (data.a - 1.0h) + 1.0h; + + #if defined(UNITY_COLORSPACE_GAMMA) + return (_GenericReflectionCubemap_HDR.x * alpha) * data.rgb; + #elif defined(UNITY_USE_NATIVE_HDR) + return _GenericReflectionCubemap_HDR.x * data.rgb; + #else + return (_GenericReflectionCubemap_HDR.x * pow(abs(alpha), _GenericReflectionCubemap_HDR.y)) * data.rgb; + #endif +} + +half3 SampleGenericReflectionCubemap(half3 reflectVector, half perceptualRoughness) +{ + half mip = perceptualRoughness * (10.2h - 4.2h * perceptualRoughness); + half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD( + _GenericReflectionCubemap, + sampler_linear_repeat, + reflectVector, + mip)); + + return DecodeGenericReflectionCubemap(encodedIrradiance); +} + +half3 SampleGenericReflectionEnvironment(half3 reflectVector, half perceptualRoughness, ToonSurfaceData surfaceData, ToonLightingData lightingData) +{ + if (_GenericReflectionCubeOverride > 0.5h) + { + half3 cubemapColor = SampleGenericReflectionCubemap(reflectVector, perceptualRoughness); + cubemapColor *= _GenericReflectionCubeColor.rgb; + cubemapColor *= lerp(1.0h.xxx, saturate(lightingData.mainLight.color), _GenericReflectionCubeEnableLighting); + return cubemapColor; + } + + #if UNITY_VERSION > 202220 + return GlossyEnvironmentReflection(reflectVector, lightingData.positionWS, perceptualRoughness, surfaceData.occlusion, lightingData.normalizedScreenSpaceUV); + #else + return GlossyEnvironmentReflection(reflectVector, lightingData.positionWS, perceptualRoughness, surfaceData.occlusion); + #endif +} + +half3 ApplyGenericReflectionSpecular(half3 normalWS, half smoothnessRoughness, half3 specular, ToonLightingData lightingData) +{ + half3 viewDirWS = normalize(lightingData.viewDirectionWS); + half3 lightDirWS = normalize(lightingData.mainLight.direction); + half3 halfDirWS = normalize(viewDirWS + lightDirWS); + half NdotH = saturate(dot(normalWS, halfDirWS)); + + if (_GenericReflectionSpecularToon > 0.5h) + { + half specularArea = pow(NdotH, rcp(max(smoothnessRoughness, 0.002h))); + return GenericReflectionTooningScale(specularArea, _GenericReflectionSpecularBorder, _GenericReflectionSpecularBlur).xxx; + } + + half NdotV = saturate(dot(normalWS, viewDirWS)); + half NdotL = saturate(dot(normalWS, lightDirWS)); + half LdotH = saturate(dot(lightDirWS, halfDirWS)); + half roughness = max(smoothnessRoughness, 0.002h); + half lambdaV = NdotL * (NdotV * (1.0h - roughness) + roughness); + half lambdaL = NdotV * (NdotL * (1.0h - roughness) + roughness); + half roughness2 = roughness * roughness; + half d = (NdotH * roughness2 - NdotH) * NdotH + 1.0h; + half ggx = roughness2 / (d * d + 1e-7h); + + #if defined(SHADER_API_MOBILE) || defined(SHADER_API_SWITCH) + half smithJointGGX = 0.5h / (lambdaV + lambdaL + 1e-4h); + #else + half smithJointGGX = 0.5h / (lambdaV + lambdaL + 1e-5h); + #endif + + half specularTerm = smithJointGGX * ggx; + #if defined(UNITY_COLORSPACE_GAMMA) + specularTerm = sqrt(max(1e-4h, specularTerm)); + #endif + + specularTerm *= NdotL; + return specularTerm * GenericReflectionFresnelTerm(specular, LdotH); +} +#endif + +void ApplyGenericReflection(inout half3 color, ToonSurfaceData surfaceData, Varyings varyings, ToonLightingData lightingData) +{ +#if _GENERIC_REFLECTION && NiloToonForwardLitPass + half3 baseNormalWS = normalize(lightingData.normalWS); + half smoothness = saturate(_GenericReflectionSmoothness * SAMPLE_TEXTURE2D( + _GenericReflectionSmoothnessMap, + sampler_linear_repeat, + CalcUV(GetUV(varyings), _GenericReflectionSmoothnessMap_ST)).r); + GenericReflectionGSAAForSmoothness(smoothness, baseNormalWS, _GenericReflectionGSAAStrength); + half perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness); + half roughness = perceptualRoughness * perceptualRoughness; + + half4 colorMask = SAMPLE_TEXTURE2D( + _GenericReflectionColorMaskMap, + sampler_linear_repeat, + CalcUV(GetUV(varyings), _GenericReflectionColorMaskMap_ST)); + half4 reflectionColor = _GenericReflectionColor * colorMask; + half reflectionAlpha = _GenericReflectionBlend * reflectionColor.a; + + if (_GenericReflectionApplyTransparency > 0.5h) + { + reflectionAlpha *= surfaceData.alpha; + } + + half metallicMask = SAMPLE_TEXTURE2D( + _GenericReflectionMetallicMap, + sampler_linear_repeat, + CalcUV(GetUV(varyings), _GenericReflectionMetallicMap_ST)).r; + half metallic = saturate(_GenericReflectionMetallic * metallicMask); + + color -= metallic * color; + half3 specular = lerp(_GenericReflectionReflectance.xxx, surfaceData.albedo, metallic); + + if (_GenericReflectionApplySpecular > 0.5h) + { + half3 specularNormalWS = normalize(lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _GenericReflectionSpecularNormalStrength)); + half3 specularReflection = ApplyGenericReflectionSpecular(specularNormalWS, roughness, specular, lightingData); + color = BlendGenericReflectionColor( + color, + reflectionColor.rgb * saturate(lightingData.mainLight.color), + specularReflection * reflectionAlpha, + _GenericReflectionBlendMode); + } + + if (_GenericReflectionApplyReflection <= 0.5h) + { + return; + } + + half3 normalWS = normalize(lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _GenericReflectionNormalStrength)); + half3 reflectionVectorWS = reflect(-lightingData.viewDirectionWS, normalWS); + half3 envReflectionColor = SampleGenericReflectionEnvironment(reflectionVectorWS, perceptualRoughness, surfaceData, lightingData); + half oneMinusReflectivity = 0.96h * (1.0h - metallic); + half grazingTerm = saturate(smoothness + (1.0h - oneMinusReflectivity)); + half surfaceReduction = 1.0h / (roughness * roughness + 1.0h); + half normalNdotV = saturate(dot(normalWS, lightingData.viewDirectionWS)); + half3 reflectCol = surfaceReduction * envReflectionColor * GenericReflectionFresnelLerp(specular, grazingTerm.xxx, normalNdotV); + + color = BlendGenericReflectionColor( + color, + reflectionColor.rgb, + reflectCol * reflectionAlpha, + _GenericReflectionBlendMode); +#endif +} diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericReflection.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericReflection.hlsl.meta new file mode 100644 index 000000000..1ba5821b5 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericReflection.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1d7bd87051248fa438c2d8ff561a161c +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D.hlsl new file mode 100644 index 000000000..9e7b9f8ac --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D.hlsl @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// For more information, visit -> https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample + +// #pragma once is a safe guard best practice in almost every .hlsl, +// doing this can make sure your .hlsl's user can include this .hlsl anywhere anytime without producing any multi include conflict +#pragma once + +#if _GENERIC_RIMLIGHT3D +void ApplyNiloToonCharacterGenericRimLight3D( + inout half3 result, + ToonSurfaceData surfaceData, + Varyings input, + ToonLightingData lightingData, + Light light, + half finalShadowArea, + half inShadow25PercentMul) +{ + float2 genericRimLight3DColorUv = CalcUV(GetUV(input), _GenericRimLight3DColorTex_ST); + half4 genericRimLight3DColorTex = SAMPLE_TEXTURE2D(_GenericRimLight3DColorTex, sampler_BaseMap, genericRimLight3DColorUv); +#if _FACE_MASK_ON + half3 genericRimLight3DSmoothedNormalWS = normalize(input.smoothedNormalWS); +#else + half3 genericRimLight3DSmoothedNormalWS = input.smoothedNormalWS; +#endif + half3 genericRimLight3DNoNormalMapWS = lerp(lightingData.normalWS_NoNormalMap, genericRimLight3DSmoothedNormalWS, lightingData.isFaceArea); + half3 genericRimLight3DNormalWS = lerp(lightingData.normalWS, genericRimLight3DSmoothedNormalWS, lightingData.isFaceArea); + + result = ApplyNiloGenericRimLight3D( + result, + surfaceData.albedo, + lightingData.facing, + genericRimLight3DNoNormalMapWS, + genericRimLight3DNormalWS, + lightingData.viewDirectionWS, + light.direction, + min(_GlobalMainDirectionalLightMaxContribution, light.color), + finalShadowArea, + inShadow25PercentMul, + genericRimLight3DColorTex, + _GenericRimLight3DColor, + _GenericRimLight3DIndirColor, + _GenericRimLight3DAlpha, + _GenericRimLight3DMainStrength, + _GenericRimLight3DEnableLighting, + _GenericRimLight3DShadowMask, + _GenericRimLight3DBackfaceMask, + _GenericRimLight3DBlendMode, + _GenericRimLight3DDirStrength, + _GenericRimLight3DDirRange, + _GenericRimLight3DBorder, + _GenericRimLight3DBlur, + _GenericRimLight3DIndirRange, + _GenericRimLight3DIndirBorder, + _GenericRimLight3DIndirBlur, + _GenericRimLight3DNormalStrength, + _GenericRimLight3DFresnelPower, + _GenericRimLight3DVRParallaxStrength); +} +#endif diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D.hlsl.meta new file mode 100644 index 000000000..9859fd6d8 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4e59bf66d68cc9a448c4d455828a0a96 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D_Uniforms.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D_Uniforms.hlsl new file mode 100644 index 000000000..675dabba9 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D_Uniforms.hlsl @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// Included inside UnityPerMaterial CBUFFER. +// Do not add #if/#ifdef/#ifndef here. SRP Batcher requires identical CBUFFER layout across variants. + +half4 _GenericRimLight3DColor; +float4 _GenericRimLight3DColorTex_ST; +half _GenericRimLight3DAlpha; +half _GenericRimLight3DMainStrength; +half _GenericRimLight3DEnableLighting; +half _GenericRimLight3DShadowMask; +half _GenericRimLight3DBackfaceMask; +uint _GenericRimLight3DBlendMode; + +half _GenericRimLight3DDirStrength; +half _GenericRimLight3DDirRange; +half _GenericRimLight3DBorder; +half _GenericRimLight3DBlur; + +half _GenericRimLight3DIndirRange; +half4 _GenericRimLight3DIndirColor; +half _GenericRimLight3DIndirBorder; +half _GenericRimLight3DIndirBlur; + +half _GenericRimLight3DNormalStrength; +half _GenericRimLight3DFresnelPower; +half _GenericRimLight3DVRParallaxStrength; diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D_Uniforms.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D_Uniforms.hlsl.meta new file mode 100644 index 000000000..3f18474e6 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_GenericRimLight3D_Uniforms.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 03e7c2de542d44358099e53f71ddfc07 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LightingEquation.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LightingEquation.hlsl index 8ed6a7ef6..3d3742a86 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LightingEquation.hlsl +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LightingEquation.hlsl @@ -8,6 +8,8 @@ #pragma once #include "NiloToonCharacter_RiderSupport.hlsl" +#include "NiloToonCharacter_GenericRimLight3D.hlsl" +#include "NiloToonCharacter_LilToonShadowMode.hlsl" // calculate Albedo's shadow area's color, // any light's light color is NOT considered in this function yet! @@ -85,6 +87,11 @@ half3 CalculateLightIndependentSelfShadowAlbedoColor(const ToonSurfaceData surfa result = lerp(result, finalOverriddenShadowColor, finalApplyStrength); #endif + // lilToon _ShadowMainStrength equivalent: must run last (after override texture), before light color. + // Note: rawAlbedo here may include matcap/env-reflection mutations from upstream Apply* functions, + // matching NiloToon's existing lit-area albedo usage but slightly diverging from lilToon's pure main color. + result = lerp(result, result * rawAlbedo, _SelfShadowAlbedoMulStrength); + return result; } @@ -185,6 +192,10 @@ half4 ShadeMainLight(inout ToonSurfaceData surfaceData, Varyings input, ToonLigh half directOcclusion = surfaceData.occlusion; // hardcode 100% usage, unlike indirectOcclusion in ShadeGI(), it is not adjustable selfLightAttenuation *= directOcclusion; #endif + // Fur AO writes to surfaceData.occlusion even when no occlusion-map keyword is enabled. +#if NiloToonIsAnyFurPass && !AnyOcclusionEnabled + selfLightAttenuation *= surfaceData.occlusion; +#endif #if _ISFACE && (_FACE_SHADOW_GRADIENTMAP || _FACE_3D_RIMLIGHT_AND_SHADOW) @@ -756,7 +767,18 @@ half4 ShadeMainLight(inout ToonSurfaceData surfaceData, Varyings input, ToonLigh // [ramp lighting override] // if enabled ramp lighting texture, we will ignore ALU lighting color, and use _RampLightingTex as shadow color instead -#if _RAMP_LIGHTING +#if _SHADOW_MODE_LILTOON + NiloToonLilToonShadowModeResult lilToonShadowModeResult = CalculateNiloToonLilToonShadowMode( + surfaceData, + lightingData, + light, + selfShadowMapShadow, + depthDiffShadow, + finalShadowArea); + + finalShadowArea = lilToonShadowModeResult.finalShadowAreaForNiloEffects; + half3 lightColorIndependentLitColor = lilToonShadowModeResult.lightColorIndependentLitColor; +#elif _RAMP_LIGHTING // 1.find ramp uv.x half rampUvX = ((NoL+celShadeMidPointOffset) * 0.5 + 0.5); rampUvX = invLerp(_RampLightingNdotLRemapStart,_RampLightingNdotLRemapEnd,rampUvX);// allow user to remap @@ -808,7 +830,7 @@ half4 ShadeMainLight(inout ToonSurfaceData surfaceData, Varyings input, ToonLigh #else // if NOT enable ramp lighting texture, calculate shadow color by ALU (HSV edit, see CalculateLightIndependentSelfShadowAlbedoColor(...)) half3 inSelfShadowAlbedoColor = CalculateLightIndependentSelfShadowAlbedoColor(surfaceData, lightingData, finalShadowArea); - half3 lightColorIndependentLitColor = lerp(inSelfShadowAlbedoColor,surfaceData.albedo, finalShadowArea); + half3 lightColorIndependentLitColor = lerp(inSelfShadowAlbedoColor, surfaceData.albedo, finalShadowArea); #endif // [extra user defined color tint control to shadow area] @@ -1001,7 +1023,7 @@ half4 ShadeMainLight(inout ToonSurfaceData surfaceData, Varyings input, ToonLigh #endif // apply all specular light to lit pass (ignore outline pass) -#if NiloToonForwardLitPass && _SPECULARHIGHLIGHTS +#if NiloToonForwardLitPass && _SPECULARHIGHLIGHTS && !_NILOTOON_FUR half specularShadowMask = lerp(finalShadowArea,1,_SpecularShowInShadowArea); #if _RAMP_SPECULAR result = lerp(result,result * specularLitAdd, remappedSpecularRawArea * selfShadowMapShadow * lightingData.averageShadowAttenuation * specularShadowMask * surfaceData.specularMask); @@ -1012,11 +1034,15 @@ half4 ShadeMainLight(inout ToonSurfaceData surfaceData, Varyings input, ToonLigh #endif #endif -#if NiloToonForwardLitPass && _NILOGLITTER +#if (NiloToonForwardLitPass || NiloToonSelfOutlinePass) && _GENERIC_RIMLIGHT3D + ApplyNiloToonCharacterGenericRimLight3D(result, surfaceData, input, lightingData, light, finalShadowArea, inShadow25PercentMul); +#endif + +#if NiloToonForwardLitPass && _NILOGLITTER && !_NILOTOON_FUR result += glitterLitAdd; #endif -#if NiloToonForwardLitPass || NiloToonSelfOutlinePass +#if (NiloToonForwardLitPass || NiloToonSelfOutlinePass) && !_NILOTOON_FUR // (1): // min(2,light.color) to prevent over bright light.color // (2): @@ -1051,13 +1077,14 @@ half4 ShadeMainLight(inout ToonSurfaceData surfaceData, Varyings input, ToonLigh result += rimAttenuation * rimLightColor; #endif -#if NiloToonForwardLitPass && _ISFACE && _FACE_3D_RIMLIGHT_AND_SHADOW +#if NiloToonForwardLitPass && _ISFACE && _FACE_3D_RIMLIGHT_AND_SHADOW && !_NILOTOON_FUR result += face3DRimAddColor * finalShadowArea; // face 3D rim block by shadow // TODO: should we add to rimAttenuation? #endif -#if NiloToonForwardLitPass && _KAJIYAKAY_SPECULAR - result += kajiyaSpecularAdd; +#if NiloToonForwardLitPass && _KAJIYAKAY_SPECULAR && !_NILOTOON_FUR + half kajiyaShadowMask = lerp(finalShadowArea,1,_HairStrandSpecularShowInShadowArea); + result += kajiyaSpecularAdd * kajiyaShadowMask; #endif return half4(lerp(result,surfaceData.albedo,_AsUnlit),rimAttenuation); diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode.hlsl new file mode 100644 index 000000000..cbced6a04 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode.hlsl @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +#if _SHADOW_MODE_LILTOON +struct NiloToonLilToonShadowModeResult +{ + half3 lightColorIndependentLitColor; + half finalShadowAreaForNiloEffects; +}; + +float NiloToonLilToonTooningNoSaturateScale(float aaStrength, float value, float border, float blur) +{ + float borderMin = saturate(border - blur * 0.5); + float borderMax = saturate(border + blur * 0.5); + return (value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * aaStrength); +} + +float NiloToonLilToonTooningNoSaturateScale(float aaStrength, float value, float border, float blur, float borderRange) +{ + float borderMin = saturate(border - blur * 0.5 - borderRange); + float borderMax = saturate(border + blur * 0.5); + return (value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * aaStrength); +} + +float NiloToonLilToonTooningScale(float aaStrength, float value, float border, float blur) +{ + return saturate(NiloToonLilToonTooningNoSaturateScale(aaStrength, value, border, blur)); +} + +float NiloToonLilToonTooningScale(float aaStrength, float value, float border, float blur, float borderRange) +{ + return saturate(NiloToonLilToonTooningNoSaturateScale(aaStrength, value, border, blur, borderRange)); +} + +float3 NiloToonLilToonLinearToSRGB(float3 col) +{ + float3 low = col * 12.92; + float3 high = 1.055 * pow(max(col, 0.0), 1.0 / 2.4) - 0.055; + return lerp(low, high, step(0.0031308, col)); +} + +void NiloToonLilToonCalcLUTUV(float3 col, float resX, float resY, out float4 uv, out float factor) +{ +#if !UNITY_COLORSPACE_GAMMA + col = NiloToonLilToonLinearToSRGB(col); +#endif + float3 res = float3(resX, resY, resX * resY); + float3 resInv = float3(1.0, -1.0, 1.0) / res; + + float3 col2 = (col - col * resInv.z) + 0.5 * resInv.z; + float4 b2 = saturate(col2.b + resInv.z * float2(-0.5, 0.5)).xxyy * res.zyzy; + float4 b3 = floor(b2); + uv = float4(0, 1, 0, 1) + (col2.rgrg + b3) * resInv.xyxy; + factor = abs(b2.x - b3.x); +} + +// Match lilToon's shared sampler behavior for shadow masks. +#define NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(textureName, uv, lod) \ + ((lod) > 0 ? SAMPLE_TEXTURE2D_GRAD(textureName, sampler_linear_repeat, uv, max(abs(ddx(uv)), lod), max(abs(ddy(uv)), lod)) : SAMPLE_TEXTURE2D(textureName, sampler_linear_repeat, uv)) + +#define NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(textureName, uv, lutUv, lutFactor) \ + (_lilShadowColorType == 1 ? lerp(SAMPLE_TEXTURE2D_LOD(textureName, sampler_linear_clamp, (lutUv).xy, 0), SAMPLE_TEXTURE2D_LOD(textureName, sampler_linear_clamp, (lutUv).zw, 0), lutFactor) : SAMPLE_TEXTURE2D(textureName, sampler_BaseMap, uv)) + +half NiloToonLilToonRemapAO(half value, half minValue, half maxValue) +{ + return invLerpClamp(minValue, maxValue, value); +} + +NiloToonLilToonShadowModeResult CalculateNiloToonLilToonShadowMode( + ToonSurfaceData surfaceData, + ToonLightingData lightingData, + Light light, + half selfShadowMapShadow, + half depthDiffShadow, + half finalNiloShadowArea) +{ + NiloToonLilToonShadowModeResult result; + + if (!_EnableShadowColor) + { + result.lightColorIndependentLitColor = surfaceData.albedo; + result.finalShadowAreaForNiloEffects = finalNiloShadowArea; + return result; + } + + const float2 uv = lightingData.uv; + const half3 rawAlbedo = surfaceData.albedo; + const half3 L = light.direction; + + // lilToon also adds distance(fd.L, fd.origL) for _LightDirectionOverride; intentionally skipped here. + half receivedShadow = saturate(light.shadowAttenuation); + #if _NILOTOON_RECEIVE_SELF_SHADOW + receivedShadow *= selfShadowMapShadow; + #endif + receivedShadow *= depthDiffShadow; + receivedShadow = saturate(receivedShadow); + + half3 N1 = lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _lilShadowNormalStrength); + half3 N2 = lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _lilShadow2ndNormalStrength); + half3 N3 = lerp(lightingData.normalWS_NoNormalMap, lightingData.normalWS, _lilShadow3rdNormalStrength); + + half4 shadowStrengthMask = NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(_lilShadowStrengthMask, uv, _lilShadowStrengthMaskLOD); + + half4 lns = 1.0; + lns.x = saturate(dot(L, N1) * 0.5 + 0.5); + lns.y = saturate(dot(L, N2) * 0.5 + 0.5); + lns.z = saturate(dot(L, N3) * 0.5 + 0.5); + lns.w = lns.x; + + half aaStrength = _lilAAStrength; + + if (_lilShadowMaskType == 2) + { + float3 faceR = mul((float3x3)UNITY_MATRIX_M, float3(-1.0, 0.0, 0.0)); + float LdotR = dot(L.xz, faceR.xz); + half sdf = LdotR < 0 ? shadowStrengthMask.g : shadowStrengthMask.r; + + float3 faceF = mul((float3x3)UNITY_MATRIX_M, float3(0.0, 0.0, 1.0)); + faceF.y *= _lilShadowFlatBlur; + faceF = SafeNormalize(faceF); + + float3 faceL = L; + faceL.y *= _lilShadowFlatBlur; + faceL = SafeNormalize(faceL); + + half lnSDF = dot(faceL, faceF); + lns = lerp(saturate(lnSDF * 0.5 + sdf * 0.5 + 0.25), lns, shadowStrengthMask.b); + aaStrength = 0; + shadowStrengthMask.r = shadowStrengthMask.a; + } + + lns.x *= lerp(1.0, receivedShadow, _lilShadowReceive); + lns.y *= lerp(1.0, receivedShadow, _lilShadow2ndReceive); + lns.z *= lerp(1.0, receivedShadow, _lilShadow3rdReceive); + + half shadowBlur = _lilShadowBlur; + half shadow2ndBlur = _lilShadow2ndBlur; + half shadow3rdBlur = _lilShadow3rdBlur; + half4 shadowBlurMask = NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(_lilShadowBlurMask, uv, _lilShadowBlurMaskLOD); + shadowBlur *= shadowBlurMask.r; + shadow2ndBlur *= shadowBlurMask.g; + shadow3rdBlur *= shadowBlurMask.b; + + half4 shadowBorderMask = NILO_LIL_SAMPLE_SHADOW_MASK_WITH_LOD(_lilShadowBorderMask, uv, _lilShadowBorderMaskLOD); + shadowBorderMask.r = NiloToonLilToonRemapAO(shadowBorderMask.r, _lilShadowAO1Min, _lilShadowAO1Max); + shadowBorderMask.g = NiloToonLilToonRemapAO(shadowBorderMask.g, _lilShadowAO2Min, _lilShadowAO2Max); + shadowBorderMask.b = NiloToonLilToonRemapAO(shadowBorderMask.b, _lilShadowAO3Min, _lilShadowAO3Max); + + lns.xyz = _lilShadowPostAO ? lns.xyz : lns.xyz * shadowBorderMask.rgb; + lns.w = lns.x; + lns.x = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.x, _lilShadowBorder, shadowBlur); + lns.y = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.y, _lilShadow2ndBorder, shadow2ndBlur); + lns.w = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.w, _lilShadowBorder, shadowBlur, _lilShadowBorderRange); + lns.z = NiloToonLilToonTooningNoSaturateScale(aaStrength, lns.z, _lilShadow3rdBorder, shadow3rdBlur); + lns = _lilShadowPostAO ? lns * shadowBorderMask.rgbr : lns; + lns = saturate(lns); + + half backfaceShadow = lightingData.facing < 0.0 ? 1.0 - _BackFaceForceShadow : 1.0; + lns.x *= backfaceShadow; + lns.y *= backfaceShadow; + lns.z *= backfaceShadow; + lns.w *= backfaceShadow; + + half shadowStrength = _lilShadowStrength; + if (_lilShadowMaskType == 1) + { + half3 flatN = normalize(mul((float3x3)UNITY_MATRIX_M, float3(0.0, 0.25, 1.0))); + half lnFlat = saturate((dot(flatN, L) + _lilShadowFlatBorder) / _lilShadowFlatBlur); + lnFlat *= lerp(1.0, receivedShadow, _lilShadowReceive); + lns = lerp(lnFlat, lns, shadowStrengthMask.r); + } + else + { + shadowStrength *= shadowStrengthMask.r; + } + lns.x = lerp(1.0, lns.x, shadowStrength); + + float4 shadowLutUv; + float shadowLutFactor; + NiloToonLilToonCalcLUTUV(rawAlbedo, 16, 1, shadowLutUv, shadowLutFactor); + + half4 shadowColorTex = NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(_lilShadowColorTex, uv, shadowLutUv, shadowLutFactor); + half4 shadow2ndColorTex = NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(_lilShadow2ndColorTex, uv, shadowLutUv, shadowLutFactor); + half4 shadow3rdColorTex = NILO_LIL_SAMPLE_SHADOW_COLOR_TEX(_lilShadow3rdColorTex, uv, shadowLutUv, shadowLutFactor); + + half3 indirectColor = lerp(rawAlbedo, shadowColorTex.rgb, shadowColorTex.a) * _lilShadowColor.rgb; + + half3 shadow2ndColor = lerp(rawAlbedo, shadow2ndColorTex.rgb, shadow2ndColorTex.a) * _lilShadow2ndColor.rgb; + lns.y = _lilShadow2ndColor.a - lns.y * _lilShadow2ndColor.a; + indirectColor = lerp(indirectColor, shadow2ndColor, lns.y); + + half3 shadow3rdColor = lerp(rawAlbedo, shadow3rdColorTex.rgb, shadow3rdColorTex.a) * _lilShadow3rdColor.rgb; + lns.z = _lilShadow3rdColor.a - lns.z * _lilShadow3rdColor.a; + indirectColor = lerp(indirectColor, shadow3rdColor, lns.z); + + indirectColor = lerp(indirectColor, indirectColor * rawAlbedo, _lilShadowMainStrength); + indirectColor = lerp(indirectColor, rawAlbedo, saturate(Luminance(lightingData.SH) * _lilShadowEnvStrength)); + indirectColor = min(indirectColor, rawAlbedo); + indirectColor = lerp(indirectColor, rawAlbedo, lns.w * _lilShadowBorderColor.rgb); + + result.lightColorIndependentLitColor = lerp(indirectColor, rawAlbedo, lns.x); + result.finalShadowAreaForNiloEffects = saturate(lns.x); + return result; +} +#endif diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode.hlsl.meta new file mode 100644 index 000000000..05eb73562 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 602d56e60bb28e2428412c87e33383be +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Textures.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Textures.hlsl new file mode 100644 index 000000000..edcf64ddc --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Textures.hlsl @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +#pragma once + +#if _SHADOW_MODE_LILTOON +TEXTURE2D(_lilShadowStrengthMask); +TEXTURE2D(_lilShadowColorTex); +TEXTURE2D(_lilShadow2ndColorTex); +TEXTURE2D(_lilShadow3rdColorTex); +TEXTURE2D(_lilShadowBlurMask); +TEXTURE2D(_lilShadowBorderMask); +#endif diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Textures.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Textures.hlsl.meta new file mode 100644 index 000000000..eaf0a4e97 --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Textures.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e53ed770086de994db59210d04ab01cb +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Uniforms.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Uniforms.hlsl new file mode 100644 index 000000000..28ee6bbfa --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Uniforms.hlsl @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA) +// Copyright (c) 2021 Kuroneko ShaderLab Limited + +// Included inside UnityPerMaterial CBUFFER. +// Do not add preprocessor conditionals here. SRP Batcher requires identical CBUFFER layout across variants. +// lilToon _ShadowCasterBias is intentionally not ported; caster pass behavior stays NiloToon. + +half4 _lilShadowColor; +half4 _lilShadow2ndColor; +half4 _lilShadow3rdColor; +half4 _lilShadowBorderColor; + +half _lilShadowStrength; +half _lilShadowStrengthMaskLOD; +half _lilShadowMaskType; +half _lilShadowFlatBorder; +half _lilShadowFlatBlur; + +half _lilShadowColorType; +half _lilShadowBorder; +half _lilShadowBlur; +half _lilShadowNormalStrength; +half _lilShadowReceive; +half _lilShadow2ndBorder; +half _lilShadow2ndBlur; +half _lilShadow2ndNormalStrength; +half _lilShadow2ndReceive; +half _lilShadow3rdBorder; +half _lilShadow3rdBlur; +half _lilShadow3rdNormalStrength; +half _lilShadow3rdReceive; + +half _lilShadowBorderRange; +half _lilShadowMainStrength; +half _lilShadowEnvStrength; +half _lilAAStrength; + +half _lilShadowBlurMaskLOD; +half _lilShadowBorderMaskLOD; +half _lilShadowPostAO; +half _lilShadowAO1Min; +half _lilShadowAO1Max; +half _lilShadowAO2Min; +half _lilShadowAO2Max; +half _lilShadowAO3Min; +half _lilShadowAO3Max; diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Uniforms.hlsl.meta b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Uniforms.hlsl.meta new file mode 100644 index 000000000..adbdb1edb --- /dev/null +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_LilToonShadowMode_Uniforms.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 121544f4c2d19ae4da915ef8a5a51adc +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl index 701efe7bb..b606ca801 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacter_HLSL/NiloToonCharacter_Shared.hlsl @@ -20,18 +20,21 @@ #if NiloToonSelfOutlinePass || NiloToonExtraThickOutlinePass || NiloToonCharacterAreaStencilBufferFillPass || NiloToonDepthOnlyOrDepthNormalPass || NiloToonPrepassBufferPass #define NiloToonIsAnyOutlinePass 1 #endif -#if NiloToonForwardLitPass || NiloToonSelfOutlinePass +#if NiloToonForwardLitPass || NiloToonSelfOutlinePass || NiloToonGBufferPass || NiloToonFurPass #define NiloToonIsAnyLitColorPass 1 #endif -#if NiloToonIsAnyLitColorPass || NiloToonDepthOnlyOrDepthNormalPass || NiloToonExtraThickOutlinePass || NiloToonPrepassBufferPass +#if NiloToonFurPass || NiloToonFurPrepassBufferPass + #define NiloToonIsAnyFurPass 1 +#endif +#if NiloToonIsAnyLitColorPass || NiloToonDepthOnlyOrDepthNormalPass || NiloToonExtraThickOutlinePass || NiloToonPrepassBufferPass || NiloToonFurPrepassBufferPass #define ApplyZOffset 1 // foreach pass that will edit "ZOffsetFinalSum", will be included in "ApplyZOffset" #endif -#if NiloToonIsAnyLitColorPass || NiloToonDepthOnlyOrDepthNormalPass || NiloToonExtraThickOutlinePass || NiloToonPrepassBufferPass || NiloToonCharacterAreaStencilBufferFillPass || NiloToonCharacterAreaColorFillPass +#if NiloToonIsAnyLitColorPass || NiloToonDepthOnlyOrDepthNormalPass || NiloToonExtraThickOutlinePass || NiloToonPrepassBufferPass || NiloToonFurPrepassBufferPass || NiloToonCharacterAreaStencilBufferFillPass || NiloToonCharacterAreaColorFillPass #define ApplyPerspectiveRemoval 1 #endif // because _DETAIL always sample detail normal map -#if _NORMALMAP || _DETAIL || _KAJIYAKAY_SPECULAR || _DYNAMIC_EYE || _PARALLAXMAP +#if _NORMALMAP || _DETAIL || _KAJIYAKAY_SPECULAR || _DYNAMIC_EYE || _PARALLAXMAP || _GENERIC_MATCAP1_CUSTOM_NORMAL || _GENERIC_MATCAP2_CUSTOM_NORMAL #define VaryingsHasTangentWS 1 #endif #if _PARALLAXMAP @@ -152,6 +155,15 @@ struct Varyings #endif //-------------------------------------------------------------------- + // Fur fields (Standalone Only) — set by vertex shader, consumed by geometry & fragment shader. + // ** MAINTENANCE NOTE **: If you add/remove fields in this Varyings struct, + // you MUST also update InterpolateVaryings() in NiloToonCharacter_FurGeom.hlsl. +#if NiloToonIsAnyFurPass + float3 furVector : TEXCOORD8; // fur extrusion direction (world space) + float furLayer : TEXCOORD9; // 0 = root, 1 = tip + nointerpolation uint furVertexID : TEXCOORD10; // stable seed for lilToon-style fur randomize +#endif + // to support GPU instancing and Single Pass Stereo rendering(VR), add the following section //------------------------------------------------------------------------------------------------------------------------------ // see ShadowCasterPass.hlsl for why these lines are removed for NiloToonCharSelfShadowCasterPass @@ -202,6 +214,9 @@ SAMPLER(sampler_linear_clamp); SAMPLER(sampler_linear_repeat); TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); +#if _BASEMAP_HSVG_MASK +TEXTURE2D(_BaseMapHSVGMaskTex); +#endif #if _ALPHAOVERRIDEMAP sampler2D _AlphaOverrideTex; @@ -265,8 +280,13 @@ TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); #endif #endif #if _ENVIRONMENTREFLECTIONS + TEXTURE2D(_EnvironmentReflectionColorMaskMap); TEXTURE2D(_EnvironmentReflectionMaskMap); #endif +#if _ENVIRONMENTREFLECTIONS_OVERRIDE_CUBEMAP + TEXTURECUBE(_EnvironmentReflectionOverrideCubemap); + SAMPLER(sampler_EnvironmentReflectionOverrideCubemap); +#endif #if _MATCAP_BLEND sampler2D _MatCapAlphaBlendMap; TEXTURE2D(_MatCapAlphaBlendMaskMap); @@ -279,6 +299,30 @@ TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); sampler2D _MatCapOcclusionMap; TEXTURE2D(_MatCapOcclusionMaskMap); #endif +#if _GENERIC_MATCAP1 + sampler2D _GenericMatCap1Map; + sampler2D _GenericMatCap1Mask; + #if _GENERIC_MATCAP1_CUSTOM_NORMAL + sampler2D _GenericMatCap1BumpMap; + #endif +#endif +#if _GENERIC_MATCAP2 + sampler2D _GenericMatCap2Map; + sampler2D _GenericMatCap2Mask; + #if _GENERIC_MATCAP2_CUSTOM_NORMAL + sampler2D _GenericMatCap2BumpMap; + #endif +#endif +#if _GENERIC_RIMLIGHT3D + TEXTURE2D(_GenericRimLight3DColorTex); +#endif +#if _GENERIC_REFLECTION + TEXTURECUBE(_GenericReflectionCubemap); + TEXTURE2D(_GenericReflectionSmoothnessMap); + TEXTURE2D(_GenericReflectionColorMaskMap); + TEXTURE2D(_GenericReflectionMetallicMap); +#endif +#include "NiloToonCharacter_LilToonShadowMode_Textures.hlsl" #if _RAMP_LIGHTING TEXTURE2D(_DynamicRampLightingTex); TEXTURE2D(_RampLightingTex); @@ -302,9 +346,9 @@ TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); sampler2D _SmoothnessMap; #endif #if _SPECULARHIGHLIGHTS - sampler2D _SpecularMap; + TEXTURE2D(_SpecularMap); #if _SPECULARHIGHLIGHTS_TEX_TINT - sampler2D _SpecularColorTintMap; + TEXTURE2D(_SpecularColorTintMap); #endif #endif #if _NILOGLITTER @@ -386,6 +430,7 @@ TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap); #if NiloToonCharacterAreaColorFillPass TEXTURE2D(_CharacterAreaColorFillTexture); #endif +#include "NiloToonCharacter_Fur_Textures.hlsl" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NiloToon's global textures //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -439,9 +484,15 @@ SAMPLER_CMP(sampler_NiloToonCharSelfShadowMapRT_LinearClampCompare); // need Lin // - "OpenGLES + any GPU" is safe also // *Split a big CBUFFER into 2 CBUFFER(UnityPerMaterial, UnityPerMaterialTwo) doesn't work #ifndef SHADER_API_VULKAN -CBUFFER_START(UnityPerMaterial) +#define NILO_UNITY_PER_MATERIAL_CBUFFER_START CBUFFER_START(UnityPerMaterial) +#define NILO_UNITY_PER_MATERIAL_CBUFFER_END CBUFFER_END +#else +#define NILO_UNITY_PER_MATERIAL_CBUFFER_START +#define NILO_UNITY_PER_MATERIAL_CBUFFER_END #endif +NILO_UNITY_PER_MATERIAL_CBUFFER_START + float _RenderCharacter; // identity if material is currently controlled by NiloToonPerCharacterRenderController script @@ -480,6 +531,10 @@ CBUFFER_START(UnityPerMaterial) half4 _BaseColor; half4 _BaseColor2; half _BaseMapBrightness; + half _BaseMapHue; + half _BaseMapSaturation; + half _BaseMapValue; + half _BaseMapGamma; half3 _PerCharacterBaseColorTint; half _MultiplyBRPColor; @@ -769,6 +824,74 @@ CBUFFER_START(UnityPerMaterial) half _MatCapOcclusionMaskMapRemapStart; half _MatCapOcclusionMaskMapRemapEnd; + // generic mat cap 1 + half4 _GenericMatCap1Color; + float4 _GenericMatCap1Map_ST; + float4 _GenericMatCap1Mask_ST; + float4 _GenericMatCap1BumpMap_ST; + float4 _GenericMatCap1BlendUV1; + half _GenericMatCap1MainStrength; + half _GenericMatCap1Blend; + half _GenericMatCap1EnableLighting; + half _GenericMatCap1ShadowMask; + half _GenericMatCap1BackfaceMask; + half _GenericMatCap1Lod; + uint _GenericMatCap1BlendMode; + half _GenericMatCap1ApplyTransparency; + half _GenericMatCap1NormalStrength; + half _GenericMatCap1BumpScale; + half _GenericMatCap1ZRotCancel; + half _GenericMatCap1Perspective; + half _GenericMatCap1VRParallaxStrength; + + // generic mat cap 2 + half4 _GenericMatCap2Color; + float4 _GenericMatCap2Map_ST; + float4 _GenericMatCap2Mask_ST; + float4 _GenericMatCap2BumpMap_ST; + float4 _GenericMatCap2BlendUV1; + half _GenericMatCap2MainStrength; + half _GenericMatCap2Blend; + half _GenericMatCap2EnableLighting; + half _GenericMatCap2ShadowMask; + half _GenericMatCap2BackfaceMask; + half _GenericMatCap2Lod; + uint _GenericMatCap2BlendMode; + half _GenericMatCap2ApplyTransparency; + half _GenericMatCap2NormalStrength; + half _GenericMatCap2BumpScale; + half _GenericMatCap2ZRotCancel; + half _GenericMatCap2Perspective; + half _GenericMatCap2VRParallaxStrength; + + // generic rim light 3D + #include "NiloToonCharacter_GenericRimLight3D_Uniforms.hlsl" + + // generic reflection + half4 _GenericReflectionColor; + half4 _GenericReflectionCubeColor; + float4 _GenericReflectionSmoothnessMap_ST; + float4 _GenericReflectionColorMaskMap_ST; + float4 _GenericReflectionMetallicMap_ST; + half _GenericReflectionBlend; + uint _GenericReflectionBlendMode; + half _GenericReflectionSmoothness; + half _GenericReflectionGSAAStrength; + half _GenericReflectionApplySpecular; + half _GenericReflectionApplySpecularFA; + half _GenericReflectionSpecularToon; + half _GenericReflectionSpecularNormalStrength; + half _GenericReflectionSpecularBorder; + half _GenericReflectionSpecularBlur; + half _GenericReflectionApplyReflection; + half _GenericReflectionReflectance; + half _GenericReflectionMetallic; + half _GenericReflectionCubeOverride; + half _GenericReflectionCubeEnableLighting; + half _GenericReflectionApplyTransparency; + half _GenericReflectionNormalStrength; + half4 _GenericReflectionCubemap_HDR; + // occlusion half _OcclusionStrength; half _OcclusionStrengthIndirectMultiplier; @@ -886,9 +1009,11 @@ CBUFFER_START(UnityPerMaterial) half _EnvironmentReflectionMaskMapRemapStart; half _EnvironmentReflectionMaskMapRemapEnd; float _EnvironmentReflectionApplytoFaces; + half4 _EnvironmentReflectionOverrideCubemap_HDR; // kayjiya-kay hair specular half _HairStrandSpecularMixWithBaseMapColor; + half _HairStrandSpecularShowInShadowArea; half _HairStrandSpecularTintMapUsage; float4 _HairStrandSpecularTintMapTilingXyOffsetZw; half _HairStrandSpecularOverallIntensity; @@ -919,6 +1044,7 @@ CBUFFER_START(UnityPerMaterial) half _SelfShadowAreaHueOffset; half _SelfShadowAreaSaturationBoost; half _SelfShadowAreaValueMul; + half _SelfShadowAlbedoMulStrength; half3 _SelfShadowTintColor; half _LitToShadowTransitionAreaIntensity; half _LitToShadowTransitionAreaHueOffset; @@ -935,6 +1061,9 @@ CBUFFER_START(UnityPerMaterial) half3 _FaceShadowTintColor2; half _FaceShadowBrightness; + // lilToon shadow mode + #include "NiloToonCharacter_LilToonShadowMode_Uniforms.hlsl" + // override shadow color by tex half _OverrideShadowColorByTexMode; half _OverrideShadowColorByTexIntensity; @@ -1255,6 +1384,9 @@ CBUFFER_START(UnityPerMaterial) half _DecalSmoothnessApplyStrength; half _DecalSpecularApplyStrength; + // Fur (Standalone Only) + #include "NiloToonCharacter_Fur_Uniforms.hlsl" + // Pass On/Off float _AllowRenderURPShadowCasterPass; float _AllowRenderDepthOnlyOrDepthNormalsPass; @@ -1271,9 +1403,7 @@ CBUFFER_START(UnityPerMaterial) // Pre-Multiply alpha options half _PreMultiplyAlphaIntoRGBOutput; -#ifndef SHADER_API_VULKAN -CBUFFER_END -#endif +NILO_UNITY_PER_MATERIAL_CBUFFER_END //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Global uniforms // if an uniform is not a per material uniform, @@ -1653,6 +1783,9 @@ half4 GetCombinedBaseColor() // it is made for NiloToonURP's user to extend more global features by themselves in an isolated .hlsl file #include "NiloToonCharacter_ExtendFunctionsForUserCustomLogic.hlsl" +// fur vertex-stage implementation +#include "NiloToonCharacter_Fur_Vertex.hlsl" + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // vertex shared functions //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1812,6 +1945,10 @@ bool ShouldDisableRendering() // so here only #if NiloToonSelfOutlinePass is used instead of #if NiloToonIsAnyOutlinePass. #if NiloToonSelfOutlinePass shouldDisableRendering = shouldDisableRendering || !ShouldRenderOutline(); + // When fur is active, disable classic outline. lilToon's fur shader also has no outline. + #if _NILOTOON_FUR + shouldDisableRendering = true; + #endif #endif // Material's "Pass On/Off" section @@ -2403,6 +2540,15 @@ Varyings VertexShaderAllWork(Attributes input) output.positionCS = NiloDoPerspectiveRemoval(output.positionCS,positionWS,_NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID],_PerspectiveRemovalRadius,_PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight); #endif + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Fur vector computation (Standalone Only) + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#if NiloToonIsAnyFurPass + { + ApplyNiloToonFurVertexData(output, input); + } +#endif + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // User custom logic ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2636,6 +2782,28 @@ half4 GetFinalBaseColor(Varyings input, UVData uvData, float facing) } #endif +#if NiloToonIsAnyLitColorPass + const bool shouldApplyBaseMapHSVGammaToThisMaterial = (_BaseMapHue != 0) || (_BaseMapSaturation != 1) || (_BaseMapValue != 1) || (_BaseMapGamma != 1); + UNITY_BRANCH + if(shouldApplyBaseMapHSVGammaToThisMaterial) + { + // Match lilToon's HSVG order: gamma first, then HSV(hue add, sat/value multiply). + half3 baseMapBeforeHSVG = color.rgb; + half3 baseMapAfterHSVG = pow(abs(baseMapBeforeHSVG), _BaseMapGamma); + half3 hsv = RgbToHsv(baseMapAfterHSVG); + hsv = half3(hsv.x + _BaseMapHue, saturate(hsv.y * _BaseMapSaturation), saturate(hsv.z * _BaseMapValue)); + baseMapAfterHSVG = HsvToRgb(hsv); + +#if _BASEMAP_HSVG_MASK + // Match lilToon's _MainColorAdjustMask behavior with a dedicated variant so default materials pay no texture cost. + half baseMapHSVGMask = SAMPLE_TEXTURE2D(_BaseMapHSVGMaskTex, sampler_BaseMap, uvData.GetUV(_BaseMapUVIndex)).r; +#else + half baseMapHSVGMask = 1; +#endif + color.rgb = lerp(baseMapBeforeHSVG, baseMapAfterHSVG, baseMapHSVGMask); + } +#endif + color *= GetCombinedBaseColor(); // edit color's rgba(including alpha also, not just rgb), since _BaseColor/_BaseColor2/_Color is per material, using _BaseColor/_BaseColor2/_Color's alpha to control rendering alpha should be intentional by user color.rgb *= _BaseMapBrightness; @@ -2980,7 +3148,7 @@ half4 GetFinalSpecularRGBA(UVData uvData, half3 baseColor, float facing) { #if _SPECULARHIGHLIGHTS // mask - half4 texValue = tex2D(_SpecularMap, uvData.GetUV(_SpecularMapUVIndex)); + half4 texValue = SAMPLE_TEXTURE2D(_SpecularMap, sampler_linear_repeat, uvData.GetUV(_SpecularMapUVIndex)); half specularMask = dot(texValue, _SpecularMapChannelMask); specularMask = _SpecularMapAsIDMap ? abs(specularMask * 255 - _SpecularMapExtractFromID) < 2 ? 1 : 0 : specularMask; @@ -2999,7 +3167,7 @@ half4 GetFinalSpecularRGBA(UVData uvData, half3 baseColor, float facing) #if _SPECULARHIGHLIGHTS_TEX_TINT float2 specularColorTintMapUV = uvData.GetUV(_SpecularColorTintMapUseSecondUv ? 1 : 0); specularColorTintMapUV = specularColorTintMapUV * _SpecularColorTintMapTilingXyOffsetZw.xy + _SpecularColorTintMapTilingXyOffsetZw.zw; - specularRGBResult *= lerp(1,tex2D(_SpecularColorTintMap, specularColorTintMapUV).rgb,_SpecularColorTintMapUsage); + specularRGBResult *= lerp(1, SAMPLE_TEXTURE2D(_SpecularColorTintMap, sampler_linear_repeat, specularColorTintMapUV).rgb, _SpecularColorTintMapUsage); #endif return half4(specularRGBResult,specularMask); #else @@ -3324,7 +3492,9 @@ ToonLightingData InitializeLightingData(Varyings input, half3 normalTS, float fa // [require normalmap finish first] // a shared matcap uv for all matcap features - lightingData.matcapUV = CalcMatCapUV(lightingData.viewDirectionWS,lightingData.normalWS); + // VR stereo fix: use HMD-center "head direction" instead of per-eye viewDir so matcap UV stays consistent across both eyes + half3 matcapHeadDirWS = GetMatCapHeadDirectionWS(lightingData.positionWS, lightingData.viewDirectionWS); + lightingData.matcapUV = CalcMatCapUV(matcapHeadDirWS, lightingData.normalWS); lightingData.matcapUV = _EnableUVEditGroup ? lightingData.matcapUV * _MatCapUVTiling : lightingData.matcapUV; //-------------------------------------------------------------------- @@ -3593,6 +3763,9 @@ ToonLightingData InitializeLightingData(Varyings input, half3 normalTS, float fa // fragment shared functions (Step3: override surfaceData.albedo) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include "NiloToonCharacter_GenericMatCap.hlsl" +#include "NiloToonCharacter_GenericReflection.hlsl" + // [Dynamic Eye] // currently using a simple method only // (not HDRP's method: https://github.com/Unity-Technologies/Graphics/blob/c6ae7599b33ca48852eddd592b3e40f33f2dd982/com.unity.render-pipelines.high-definition/Runtime/Material/Eye/EyeUtils.hlsl) @@ -3650,6 +3823,9 @@ void ApplyPostLightingPerCharacterBaseMapOverride(inout half3 originalSurfaceCol // [MatCap(Color Replace)] void ApplyMatCapColorReplace(inout ToonSurfaceData surfaceData, Varyings varyings, ToonLightingData lightingData) { +#if _NILOTOON_FUR + return; // fur skips matcap color replace so base mesh matches fur shell color +#endif #if _MATCAP_BLEND half matCapAlphaBlendFinalUsage = _MatCapAlphaBlendUsage; @@ -3672,6 +3848,9 @@ void ApplyMatCapColorReplace(inout ToonSurfaceData surfaceData, Varyings varying // [Mat Cap(additive)] void ApplyMatCapAdditive(inout ToonSurfaceData surfaceData, Varyings varyings, ToonLightingData lightingData) { +#if _NILOTOON_FUR + return; // fur skips matcap additive +#endif #if _MATCAP_ADD // read matcap texture float2 matCapAddUV = lightingData.matcapUV.xy * (0.5 * _MatCapAdditiveUvScale) + 0.5; @@ -3736,9 +3915,30 @@ void ApplyMatCapOcclusion(inout ToonSurfaceData surfaceData, Varyings varyings, #endif } +// [Environment Reflections - Override Cubemap] +#if _ENVIRONMENTREFLECTIONS_OVERRIDE_CUBEMAP +half3 GlossyEnvironmentReflection_OverrideCubemap(half3 reflectVector, half perceptualRoughness, half occlusion) +{ + half mip = PerceptualRoughnessToMipmapLevel(perceptualRoughness); + half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD( + _EnvironmentReflectionOverrideCubemap, + sampler_EnvironmentReflectionOverrideCubemap, + reflectVector, + mip)); + #if defined(UNITY_USE_NATIVE_HDR) + return encodedIrradiance.rgb * occlusion; + #else + return DecodeHDREnvironment(encodedIrradiance, _EnvironmentReflectionOverrideCubemap_HDR) * occlusion; + #endif +} +#endif + // [Environment Reflections] void ApplyEnvironmentReflections(inout ToonSurfaceData surfaceData, Varyings varyings, ToonLightingData lightingData) { +#if _NILOTOON_FUR + return; // fur skips environment reflections +#endif // [How to sample reflection probe correctly?] // see URP's GlobalIllumination.hlsl -> // half3 GlobalIllumination(BRDFData brdfData, BRDFData brdfDataClearCoat, float clearCoatMask, @@ -3750,7 +3950,9 @@ void ApplyEnvironmentReflections(inout ToonSurfaceData surfaceData, Varyings var // PerceptualRoughness is equal to the (1-raw smoothness texture) linear value half roughness = PerceptualSmoothnessToPerceptualRoughness(smoothness); - #if UNITY_VERSION > 202220 + #if _ENVIRONMENTREFLECTIONS_OVERRIDE_CUBEMAP + half3 GlossyEnvironmentReflectionResult = GlossyEnvironmentReflection_OverrideCubemap(lightingData.reflectionVectorWS, roughness, surfaceData.occlusion); + #elif UNITY_VERSION > 202220 half3 GlossyEnvironmentReflectionResult = GlossyEnvironmentReflection(lightingData.reflectionVectorWS, lightingData.positionWS, roughness, surfaceData.occlusion, lightingData.normalizedScreenSpaceUV); #else half3 GlossyEnvironmentReflectionResult = GlossyEnvironmentReflection(lightingData.reflectionVectorWS, lightingData.positionWS, roughness, surfaceData.occlusion); @@ -3761,6 +3963,10 @@ void ApplyEnvironmentReflections(inout ToonSurfaceData surfaceData, Varyings var half applyIntensity = _EnvironmentReflectionUsage; + half4 colorMask = SAMPLE_TEXTURE2D(_EnvironmentReflectionColorMaskMap, sampler_linear_repeat, GetUV(varyings)); + environmentReflection *= colorMask.rgb; + applyIntensity *= colorMask.a; + // mask by an optional mask texture // (decided to not use shader_feature for this mask section, else too much shader_feature is used) half mask = dot(SAMPLE_TEXTURE2D(_EnvironmentReflectionMaskMap, sampler_BaseMap, GetUV(varyings)),_EnvironmentReflectionMaskMapChannelMask); // reuse sampler_BaseMap to save sampler count @@ -3789,19 +3995,19 @@ void ApplyEnvironmentReflections(inout ToonSurfaceData surfaceData, Varyings var // [back face color tint] void ApplyBackFaceColorTintIfForwardLitPass(inout half3 originalSurfaceColor, Varyings varyings, ToonLightingData lightingData, half facing) { -#if NiloToonForwardLitPass +#if NiloToonForwardLitPass || NiloToonFurPass originalSurfaceColor *= facing < 0 ? _BackFaceTintColor : 1; #endif } void ApplyBackFaceForceShadowIfForwardLitPass(inout ToonSurfaceData surfaceData, ToonLightingData lightingData) { -#if NiloToonForwardLitPass +#if NiloToonForwardLitPass || NiloToonFurPass surfaceData.occlusion *= lightingData.facing < 0 ? 1 - _BackFaceForceShadow : 1; #endif } void ApplyBackFaceReplaceBaseMapColorIfForwardLitPass(inout ToonSurfaceData surfaceData, ToonLightingData lightingData) { -#if NiloToonForwardLitPass +#if NiloToonForwardLitPass || NiloToonFurPass surfaceData.albedo = lightingData.facing < 0 ? lerp(surfaceData.albedo, _BackFaceBaseMapReplaceColor.rgb, _BackFaceBaseMapReplaceColor.a) : surfaceData.albedo; #endif } @@ -4189,7 +4395,7 @@ void ApplyPerCharacterEffectColorEdit(inout half3 color, ToonLightingData lighti color.rgb = lerp(color.rgb,_PerCharEffectLerpColor.rgb,_PerCharEffectLerpColor.a); // rim light (outline pass don't need this) -#if NiloToonForwardLitPass +#if NiloToonForwardLitPass && !_NILOTOON_FUR // Use PolygonNdotV instead of NdotV, // because ToonLightingData's NdotV is normalmap applied & normalized, we DONT want normalmap affecting rim light here. half NdotV = lightingData.NdotV_NoNormalMap; @@ -4350,8 +4556,12 @@ void ApplyOverrideOutputAlpha(inout half outputAlpha) // since when rendering opaque material, most of the cases the alpha value on RT is expected to be one, but not alpha value of _BaseMap // forcing 1 will make rendering character mask(RT's alpha) always correct. // https://docs.unity3d.com/ScriptReference/Rendering.BlendMode.html + // Fur color pass always uses its own alpha blending, so do not force alpha to 1 + // based on the material surface preset's _SrcBlend/_DstBlend values. +#if !NiloToonIsAnyFurPass if((_SrcBlend == 1) && (_DstBlend == 0)) outputAlpha = 1; +#endif #if NiloToonSelfOutlinePass outputAlpha = 1; // outline pass always render as opaque colors, semi-transparent outline is not allowed, so for outline we force output alpha = 1 to make alpha correct when user use RenderTexture's alpha as mask @@ -4396,6 +4606,11 @@ void InitAllData(inout Varyings input, float facing, half faceArea, out UVData u surfaceData = InitializeSurfaceData(input, uvData, facing, normalTS, detailMask, detailUV); } +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Fur helpers shared by fur color/depth/prepass-buffer passes. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include "NiloToonCharacter_Fur_Fragment.hlsl" + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // only NiloToonCharacter.shader will be calling this function by using // #pragma fragment FragmentShaderAllWork @@ -4456,8 +4671,14 @@ void FragmentShaderAllWork(Varyings input, FRONT_FACE_TYPE IsFrontFace : FRONT_F ////////////////////////////////////////////////////////////////////////////////////////// float facing = IS_FRONT_VFACE(IsFrontFace, 1.0, -1.0); + // Fur shell strips emit front/back triangles in one strip. lilToon shades fur shells with the + // interpolated shell normal instead of flipping normals per triangle face. +#if NiloToonIsAnyFurPass + facing = 1.0; +#endif + // not apply "flip normal" to "NiloToonOutline" lit color pass, because we need to original normal for light shading and shadowmap normal bias -#if !NiloToonIsAnyOutlinePass +#if !NiloToonIsAnyOutlinePass && !NiloToonIsAnyFurPass input.normalWS_averageShadowAttenuation.xyz *= facing; input.smoothedNormalWS *= facing; #endif @@ -4504,7 +4725,7 @@ void FragmentShaderAllWork(Varyings input, FRONT_FACE_TYPE IsFrontFace : FRONT_F // (apply first) edit albedo ApplyDynamicEye(surfaceData, input, lightingData); ApplyMatCapColorReplace(surfaceData, input, lightingData); - // (apply later) also edit albedo, by reflection features + // (apply later) also edit albedo, by reflection features ApplyEnvironmentReflections(surfaceData, input, lightingData); ApplyMatCapAdditive(surfaceData, input, lightingData); // (apply last) replace albedo for back face @@ -4524,14 +4745,33 @@ void FragmentShaderAllWork(Varyings input, FRONT_FACE_TYPE IsFrontFace : FRONT_F ////////////////////////////////////////////////////////////////////////////////////////// ApplyAlbedoPreLightingEditIfOutlinePass(surfaceData); + ////////////////////////////////////////////////////////////////////////////////////////// + // Fur AO: apply as occlusion before lighting, so toon shadow handles darkening. + ////////////////////////////////////////////////////////////////////////////////////////// +#if NiloToonIsAnyFurPass && _NILOTOON_FUR + float furNoise = ComputeNiloToonFurNoise(input.uv01.xy); + ApplyNiloToonFurOcclusionShadowAO(surfaceData, input, furNoise); +#endif + ////////////////////////////////////////////////////////////////////////////////////////// // apply all lighting calculation - ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// half3 color = ShadeAllLights(surfaceData, lightingData, input, uvData); +#if NiloToonIsAnyFurPass && _NILOTOON_FUR + ApplyNiloToonFurColorDarkenAO(color, input, furNoise); +#endif + + ////////////////////////////////////////////////////////////////////////////////////////// + // apply post-light decoration (lilToon-faithful: matcap blends onto lit color, not albedo) + ////////////////////////////////////////////////////////////////////////////////////////// + ApplyGenericReflection(color, surfaceData, input, lightingData); + ApplyGenericMatCap1(color, surfaceData, input, lightingData); + ApplyGenericMatCap2(color, surfaceData, input, lightingData); + ////////////////////////////////////////////////////////////////////////////////////////// // apply outline color calculation - ////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// ApplySurfaceToClassicOutlineColorEditIfOutlinePass(color, surfaceData, lightingData); ApplySurfaceToScreenSpaceOutlineColorEditIfSurfacePass(color, surfaceData, lightingData); ApplySurfaceToScreenSpaceOutlineV2ColorEditIfSurfacePass(color, surfaceData, lightingData); @@ -4551,6 +4791,13 @@ void FragmentShaderAllWork(Varyings input, FRONT_FACE_TYPE IsFrontFace : FRONT_F ////////////////////////////////////////////////////////////////////////////////////////// ApplyDissolve(color, input, lightingData, uvData); + ////////////////////////////////////////////////////////////////////////////////////////// + // Fur shading (Standalone Only): noise alpha, face/skin masking, rim fresnel. + ////////////////////////////////////////////////////////////////////////////////////////// +#if NiloToonIsAnyFurPass && _NILOTOON_FUR + ApplyNiloToonFurAlphaMaskAndRim(color, surfaceData, input, lightingData, furNoise); +#endif + ////////////////////////////////////////////////////////////////////////////////////////// // apply fog (with extend logic functions before and after fog) ////////////////////////////////////////////////////////////////////////////////////////// @@ -4736,4 +4983,6 @@ float4 BaseColorAlphaClipTest_AndNiloToonPrepassBufferColorOutput(Varyings input // if character pixel is still visible(not blocked by scene), draw to _NiloToonPrepassBufferTex return float4(isFace,_AllowNiloToonBloomCharacterAreaOverride * _AllowedNiloToonBloomOverrideStrength,0,1); -} \ No newline at end of file +} + +#include "NiloToonCharacter_Fur_PrepassBuffer.hlsl" diff --git a/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonAverageShadowTestRT.shader b/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonAverageShadowTestRT.shader index 3c40c2cf4..fd6d27e50 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonAverageShadowTestRT.shader +++ b/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonAverageShadowTestRT.shader @@ -23,7 +23,7 @@ Shader "Hidden/NiloToon/AverageShadowTestRT" // for most game type, 128 is a big enough number, but still not affect performance #define MAX_CHARACTER_COUNT 128 #define MAX_DATA_ARRAY_SIZE 512 // = 128 characters * 4 data slot - #define TEST_COUNT 5 // usually 5 is smooth enough, it means (5+1+5)^3 = total of 1331 shadow tests for 1 character per frame + #define TEST_COUNT 6 // 2D hemisphere surface sampling: 13x13 grid = 169 points, 113 after circular disk mask, per character per frame float _GlobalAverageShadowTestBoundingSphereDataArray[MAX_DATA_ARRAY_SIZE]; float _GlobalAverageShadowStrength; @@ -51,35 +51,60 @@ Shader "Hidden/NiloToon/AverageShadowTestRT" Light mainLight = GetMainLight(); - // TODO: [bug] when camera is close to character, shadow will fadeout if shadow cascade is > 1 + // Note: close-camera fadeout from cascade mismatch is addressed by explicit per-sample cascade selection below. + // Remaining risk is only third-party renderer behavior that does not preserve URP shadow constants/keywords. - // [Disabled. because enable this will make shadow fadeout too easily when camera is close to character] - // added to prevent generating shadow due to near by objects - //center += mainLight.direction; // hardcode 1m, not the best solution + // Sample the light-facing hemisphere surface of the bounding sphere instead of the full 3D volume. + // This significantly reduces self-shadowing: surface points face the light and sit in front of + // the character mesh from the light's POV, so the character's own ShadowCaster cannot occlude them. + float3 lightDir = normalize(mainLight.direction); - // [Disabled. because enable this will make character darken when camera is close to character] - // added to prevent out of bound - //radius = min(radius, distance(center,_WorldSpaceCameraPos)-_ProjectionParams.y); + float3 helperUp = abs(lightDir.y) < 0.999 ? float3(0,1,0) : float3(1,0,0); + float3 U = normalize(cross(helperUp, lightDir)); + float3 V = cross(lightDir, U); + + float bias = min(0.01 * radius, 0.05); - // this crazy forloop^3 looks extremely scary, - // but it will run once per active character only, so it will not affect performance at all float shadowTestSum = 0; - for(int x = -TEST_COUNT ; x < TEST_COUNT ; x++) - for(int y = -TEST_COUNT ; y < TEST_COUNT ; y++) - for(int z = -TEST_COUNT ; z < TEST_COUNT ; z++) + float sampleCount = 0; + + for(int gu = -TEST_COUNT; gu <= TEST_COUNT; gu++) + for(int gv = -TEST_COUNT; gv <= TEST_COUNT; gv++) { - float3 shadowTestPosWS = center + float3(x,y,z) / TEST_COUNT / 2.0 * radius; + float fu = (float)gu / (float)TEST_COUNT; + float fv = (float)gv / (float)TEST_COUNT; + float d2 = fu * fu + fv * fv; + if(d2 > 1.0) continue; - // copy from LitForwardPass.hlsl -> void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData); - float4 shadowCoord = TransformWorldToShadowCoord(shadowTestPosWS); + float3 samplePos = center + + (fu * U + fv * V) * radius + + lightDir * (sqrt(max(0.0, 1.0 - d2)) * radius + bias); - // copy from Lighting.hlsl -> half4 UniversalFragmentPBR(InputData inputData, SurfaceData surfaceData); - float shadowAttenuation = MainLightRealtimeShadow(shadowCoord); + // Multi-cascade and screen-space keyword variants both use explicit cascade selection. + // CASCADE keeps skip-on-outside behavior; SCREEN falls back to cascade 0 to stay valid + // when split-sphere data is unavailable (e.g., single-cascade projects). + #if defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN) + half cascadeIndex = ComputeCascadeIndex(samplePos); + #if defined(_MAIN_LIGHT_SHADOWS_CASCADE) + if(cascadeIndex >= half(4.0)) continue; + #else + if(cascadeIndex >= half(4.0)) cascadeIndex = half(0.0); + #endif + float4 shadowCoord = float4(mul(_MainLightWorldToShadow[cascadeIndex], float4(samplePos, 1.0)).xyz, 0.0); + #else + float4 shadowCoord = TransformWorldToShadowCoord(samplePos); + #endif - shadowTestSum += shadowAttenuation; + shadowTestSum += MainLightRealtimeShadow(shadowCoord); + sampleCount += 1.0; } - float count1D = TEST_COUNT * 2 + 1; - shadowTestSum /= float(count1D*count1D*count1D) * 0.25; // 0.25 can be any number. the bigger the number, the more easier to be in shadow + + if(sampleCount < 1.0) return 1; // all samples outside cascade coverage -> no shadow data, assume lit (matches URP convention) + + shadowTestSum /= sampleCount; + + // Compress range: partial shadow barely darkens, only heavy shadow is visible + shadowTestSum = smoothstep(0.25, 0.75, shadowTestSum); return lerp(1,saturate(shadowTestSum),_GlobalAverageShadowStrength); } diff --git a/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonKinoMotion/LICENSE.txt b/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonKinoMotion/LICENSE.txt index 573c05398..f855a9e95 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonKinoMotion/LICENSE.txt +++ b/Assets/NiloToonURP/Shaders/NiloToonRendererFeatureShaders/Resources/NiloToonKinoMotion/LICENSE.txt @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa7959134513b4e505d5415529232cb935557fe5f0cce7e65508ce1b860e8fc8 -size 1080 +oid sha256:66ffe1da984b21a070364ed1fc50460981907679559b0a39ca4c22ac8a498aff +size 1101 diff --git a/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_BottomToTop.png.meta b/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_BottomToTop.png.meta index 22b83689d..4e736cbd9 100644 --- a/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_BottomToTop.png.meta +++ b/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_BottomToTop.png.meta @@ -70,13 +70,13 @@ TextureImporter: maxTextureSize: 32 resizeAlgorithm: 0 textureFormat: -1 - textureCompression: 0 - compressionQuality: 50 + textureCompression: 2 + compressionQuality: 100 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 - serializedVersion: 3 buildTarget: Standalone maxTextureSize: 8192 diff --git a/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_LeftToRight.png.meta b/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_LeftToRight.png.meta index b586177c3..3050a1e52 100644 --- a/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_LeftToRight.png.meta +++ b/Assets/NiloToonURP/Textures/DissolveThreshold/DissolveThreshold_LeftToRight.png.meta @@ -70,13 +70,13 @@ TextureImporter: maxTextureSize: 32 resizeAlgorithm: 0 textureFormat: -1 - textureCompression: 0 - compressionQuality: 50 + textureCompression: 2 + compressionQuality: 100 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 - serializedVersion: 3 buildTarget: Standalone maxTextureSize: 8192 diff --git a/Assets/NiloToonURP/Textures/Matcap_Metal4Gold.png.meta b/Assets/NiloToonURP/Textures/Matcap_Metal4Gold.png.meta index 7e06f716c..61454fbfc 100644 --- a/Assets/NiloToonURP/Textures/Matcap_Metal4Gold.png.meta +++ b/Assets/NiloToonURP/Textures/Matcap_Metal4Gold.png.meta @@ -70,13 +70,13 @@ TextureImporter: maxTextureSize: 8192 resizeAlgorithm: 0 textureFormat: -1 - textureCompression: 0 - compressionQuality: 50 + textureCompression: 2 + compressionQuality: 100 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 - serializedVersion: 3 buildTarget: Standalone maxTextureSize: 8192 diff --git a/Assets/NiloToonURP/Textures/Matcap_StockingBlack.psd.meta b/Assets/NiloToonURP/Textures/Matcap_StockingBlack.psd.meta index 56f4eb660..3b8d95a2a 100644 --- a/Assets/NiloToonURP/Textures/Matcap_StockingBlack.psd.meta +++ b/Assets/NiloToonURP/Textures/Matcap_StockingBlack.psd.meta @@ -70,13 +70,13 @@ TextureImporter: maxTextureSize: 8192 resizeAlgorithm: 0 textureFormat: -1 - textureCompression: 0 - compressionQuality: 50 + textureCompression: 2 + compressionQuality: 100 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 - serializedVersion: 3 buildTarget: Standalone maxTextureSize: 8192 diff --git a/Assets/NiloToonURP/Textures/NiloFurNoise.png b/Assets/NiloToonURP/Textures/NiloFurNoise.png new file mode 100644 index 000000000..bb7be383f --- /dev/null +++ b/Assets/NiloToonURP/Textures/NiloFurNoise.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89682c08cee076054dd022ac37aa2a303ee33cfa09984050a132db6033a39c43 +size 67269 diff --git a/Assets/NiloToonURP/Textures/NiloFurNoise.png.meta b/Assets/NiloToonURP/Textures/NiloFurNoise.png.meta new file mode 100644 index 000000000..6a6749a18 --- /dev/null +++ b/Assets/NiloToonURP/Textures/NiloFurNoise.png.meta @@ -0,0 +1,99 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 256 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 2 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/NiloToonURP/package.json b/Assets/NiloToonURP/package.json index 3e630e299..043ef105d 100644 --- a/Assets/NiloToonURP/package.json +++ b/Assets/NiloToonURP/package.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:958badb29d6abeb7554b8bcd8765db8977f16eea41aa1c54ecdebbf3ea82ec33 -size 828 +oid sha256:c6b17d84d92ca36380121ff5dec4f6f88695302c0dc6aaf3319f1970b599e73c +size 829 diff --git a/Assets/Resources/Settings/Streamingle Render Pipeline Asset_Renderer.asset b/Assets/Resources/Settings/Streamingle Render Pipeline Asset_Renderer.asset index 8cd49a10a..4731314ac 100644 --- a/Assets/Resources/Settings/Streamingle Render Pipeline Asset_Renderer.asset +++ b/Assets/Resources/Settings/Streamingle Render Pipeline Asset_Renderer.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5fecc227bda1c93111504ca778501363518064e789ff1df2342d7141979cdc9c -size 20245 +oid sha256:0cb7ad8bae21f5d0a0ca44a8d7d320f6d00cb6ab7e02c69de99ae6946c2617ed +size 20371 diff --git a/Assets/ResourcesData/Character/@003_치요/#Fan_Character/M_meechu_Chiyo_MayoDan_00.mat b/Assets/ResourcesData/Character/@003_치요/#Fan_Character/M_meechu_Chiyo_MayoDan_00.mat index 04c5696e9..7d579d4a2 100644 --- a/Assets/ResourcesData/Character/@003_치요/#Fan_Character/M_meechu_Chiyo_MayoDan_00.mat +++ b/Assets/ResourcesData/Character/@003_치요/#Fan_Character/M_meechu_Chiyo_MayoDan_00.mat @@ -8,8 +8,12 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: M_meechu_Chiyo_MayoDan_00 - m_Shader: {fileID: 4800000, guid: 8b2f353da1dd05244a7bee1562a2306a, type: 3} - m_ValidKeywords: [] + m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS + - _RECEIVE_URP_SHADOW m_InvalidKeywords: - MTOON_OUTLINE_COLOR_FIXED - MTOON_OUTLINE_WIDTH_WORLD @@ -21,13 +25,114 @@ Material: m_CustomRenderQueue: -1 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: + - _AlphaOverrideTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMap: + m_Texture: {fileID: 2800000, guid: 92eac158242c7d648b2f8abb15dd325e, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer10MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer10Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer1MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer1Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer2MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer2Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer3MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer3Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer4MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer4Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer5MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer5Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer6MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer6Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer7MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer7Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer8MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer8Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer9MaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMapStackingLayer9Tex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _BumpMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _CharacterAreaColorFillTexture: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DepthTexRimLightAndShadowWidthTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DepthTexRimLightMaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _DetailAlbedoMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -40,18 +145,82 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _DissolveThresholdMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DynamicEyePupilMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DynamicEyePupilMaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DynamicEyeWhiteMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DynamicRampLightingTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _EffectTexture: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _EmissionAnimTintRampMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _EmissionMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _EmissionMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EnvironmentReflectionMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Face3DRimLightAndShadow_CheekRimLightMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Face3DRimLightAndShadow_CheekShadowMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Face3DRimLightAndShadow_NoseRimLightMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Face3DRimLightAndShadow_NoseShadowMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceShadowGradientMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FaceShadowGradientMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _FakeReflect: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _HairStrandSpecularTintMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _Highlight: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -60,6 +229,30 @@ Material: m_Texture: {fileID: 2800000, guid: 92eac158242c7d648b2f8abb15dd325e, type: 3} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _MatCapAdditiveMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapAdditiveMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapAlphaBlendMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapAlphaBlendMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapOcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapOcclusionMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _Matcap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -72,6 +265,14 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _NiloGlitterTintColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _NiloToonSelfShadowIntensityMultiplierTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _NormalMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -84,14 +285,66 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _OutlineTintColorMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineWidthTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _OutlineWidthTexture: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _OutlineZOffsetMaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OverrideOutlineColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OverrideShadowColorMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OverrideShadowColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _ParallaxMap: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _PerCharacterBaseMapOverrideMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _PerMaterialDissolvePatternMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _PerMaterialDissolveThresholdMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RampLightingSampleUvYTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RampLightingTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RampSpecularSampleUvYTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RampSpecularTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _ReceiveShadowTexture: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -104,14 +357,42 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _ScreenSpaceOutlineDepthSensitivityTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ScreenSpaceOutlineNormalsSensitivityTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _ShadeTexture: m_Texture: {fileID: 2800000, guid: a82681eb06a96c743ac6ea15707975fa, type: 3} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _ShadingGradeMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _ShadingGradeTexture: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _SkinMaskMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SmoothnessMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecularColorTintMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecularMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _SphereAdd: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} @@ -132,97 +413,887 @@ Material: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} + - _ZOffsetMaskTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} - _texcoord: m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - m_Ints: [] + m_Ints: + - _CharacterID: 0 + - _DissolveMode: 0 m_Floats: - _1or2: 1 + - _AddPrecomputedVelocity: 0 + - _AdditionalLightCelShadeMidPoint: 0 + - _AdditionalLightCelShadeMidPointForFaceArea: 0 + - _AdditionalLightCelShadeSoftness: 0.05 + - _AdditionalLightCelShadeSoftnessForFaceArea: 0.15 + - _AdditionalLightDistanceAttenuationClamp: 2 + - _AdditionalLightIgnoreCelShade: 0.2 + - _AdditionalLightIgnoreCelShadeForFaceArea: 0.2 + - _AdditionalLightIgnoreOcclusion: 0.2 + - _AllowNiloToonBloomCharacterAreaOverride: 1 + - _AllowPerCharacterDissolve: 1 + - _AllowPerCharacterDitherFadeout: 1 + - _AllowRenderDepthOnlyOrDepthNormalsPass: 1 + - _AllowRenderExtraThickOutlinePass: 1 + - _AllowRenderMotionVectorsPass: 1 + - _AllowRenderNiloToonCharacterAreaColorFillPass: 1 + - _AllowRenderNiloToonCharacterAreaStencilBufferFillPass: 1 + - _AllowRenderNiloToonPrepassBufferPass: 1 + - _AllowRenderNiloToonSelfShadowPass: 1 + - _AllowRenderURPShadowCasterPass: 1 + - _AllowRenderURPUniversalForwardOnlyPass: 1 + - _AllowedNiloToonBloomOverrideStrength: 1 + - _AlphaClip: 0 + - _AlphaOverrideMode: 0 + - _AlphaOverrideStrength: 1 + - _AlphaOverrideTexInvertColor: 0 + - _AlphaOverrideTexUVIndex: 0 + - _AlphaOverrideTexValueOffset: 0 + - _AlphaOverrideTexValueScale: 1 - _AlphaToMask: 0 + - _ApplyAlphaOverrideOnlyWhenFaceForwardIsPointingToCamera: 0 + - _ApplyAlphaOverrideOnlyWhenFaceForwardIsPointingToCameraRemapEnd: 1 + - _ApplyAlphaOverrideOnlyWhenFaceForwardIsPointingToCameraRemapMinMaxSlider: 1 + - _ApplyAlphaOverrideOnlyWhenFaceForwardIsPointingToCameraRemapStart: 0 + - _ApplyDepthTexRimLightFixDottedLineArtifacts: 1 + - _AsUnlit: 0 + - _BackFaceForceShadow: 0 - _BaseCellOffset: 1 - _BaseCellSharpness: 0 + - _BaseMapBrightness: 1 + - _BaseMapStackingLayer10ApplytoFaces: 0 + - _BaseMapStackingLayer10ColorBlendMode: 0 + - _BaseMapStackingLayer10Enable: 0 + - _BaseMapStackingLayer10MaskInvertColor: 0 + - _BaseMapStackingLayer10MaskRemapEnd: 1 + - _BaseMapStackingLayer10MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer10MaskRemapStart: 0 + - _BaseMapStackingLayer10MaskTexAsIDMap: 0 + - _BaseMapStackingLayer10MaskTexExtractFromID: 255 + - _BaseMapStackingLayer10MaskUVIndex: 0 + - _BaseMapStackingLayer10MasterStrength: 1 + - _BaseMapStackingLayer10TexIgnoreAlpha: 0 + - _BaseMapStackingLayer10TexUVIndex: 0 + - _BaseMapStackingLayer10TexUVRotateSpeed: 0 + - _BaseMapStackingLayer10TexUVRotatedAngle: 0 + - _BaseMapStackingLayer1ApplytoFaces: 0 + - _BaseMapStackingLayer1ColorBlendMode: 0 + - _BaseMapStackingLayer1Enable: 0 + - _BaseMapStackingLayer1MaskInvertColor: 0 + - _BaseMapStackingLayer1MaskRemapEnd: 1 + - _BaseMapStackingLayer1MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer1MaskRemapStart: 0 + - _BaseMapStackingLayer1MaskTexAsIDMap: 0 + - _BaseMapStackingLayer1MaskTexExtractFromID: 255 + - _BaseMapStackingLayer1MaskUVIndex: 0 + - _BaseMapStackingLayer1MasterStrength: 1 + - _BaseMapStackingLayer1TexIgnoreAlpha: 0 + - _BaseMapStackingLayer1TexUVIndex: 0 + - _BaseMapStackingLayer1TexUVRotateSpeed: 0 + - _BaseMapStackingLayer1TexUVRotatedAngle: 0 + - _BaseMapStackingLayer2ApplytoFaces: 0 + - _BaseMapStackingLayer2ColorBlendMode: 0 + - _BaseMapStackingLayer2Enable: 0 + - _BaseMapStackingLayer2MaskInvertColor: 0 + - _BaseMapStackingLayer2MaskRemapEnd: 1 + - _BaseMapStackingLayer2MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer2MaskRemapStart: 0 + - _BaseMapStackingLayer2MaskTexAsIDMap: 0 + - _BaseMapStackingLayer2MaskTexExtractFromID: 255 + - _BaseMapStackingLayer2MaskUVIndex: 0 + - _BaseMapStackingLayer2MasterStrength: 1 + - _BaseMapStackingLayer2TexIgnoreAlpha: 0 + - _BaseMapStackingLayer2TexUVIndex: 0 + - _BaseMapStackingLayer2TexUVRotateSpeed: 0 + - _BaseMapStackingLayer2TexUVRotatedAngle: 0 + - _BaseMapStackingLayer3ApplytoFaces: 0 + - _BaseMapStackingLayer3ColorBlendMode: 0 + - _BaseMapStackingLayer3Enable: 0 + - _BaseMapStackingLayer3MaskInvertColor: 0 + - _BaseMapStackingLayer3MaskRemapEnd: 1 + - _BaseMapStackingLayer3MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer3MaskRemapStart: 0 + - _BaseMapStackingLayer3MaskTexAsIDMap: 0 + - _BaseMapStackingLayer3MaskTexExtractFromID: 255 + - _BaseMapStackingLayer3MaskUVIndex: 0 + - _BaseMapStackingLayer3MasterStrength: 1 + - _BaseMapStackingLayer3TexIgnoreAlpha: 0 + - _BaseMapStackingLayer3TexUVIndex: 0 + - _BaseMapStackingLayer3TexUVRotateSpeed: 0 + - _BaseMapStackingLayer3TexUVRotatedAngle: 0 + - _BaseMapStackingLayer4ApplytoFaces: 0 + - _BaseMapStackingLayer4ColorBlendMode: 0 + - _BaseMapStackingLayer4Enable: 0 + - _BaseMapStackingLayer4MaskInvertColor: 0 + - _BaseMapStackingLayer4MaskRemapEnd: 1 + - _BaseMapStackingLayer4MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer4MaskRemapStart: 0 + - _BaseMapStackingLayer4MaskTexAsIDMap: 0 + - _BaseMapStackingLayer4MaskTexExtractFromID: 255 + - _BaseMapStackingLayer4MaskUVIndex: 0 + - _BaseMapStackingLayer4MasterStrength: 1 + - _BaseMapStackingLayer4TexIgnoreAlpha: 0 + - _BaseMapStackingLayer4TexUVIndex: 0 + - _BaseMapStackingLayer4TexUVRotateSpeed: 0 + - _BaseMapStackingLayer4TexUVRotatedAngle: 0 + - _BaseMapStackingLayer5ApplytoFaces: 0 + - _BaseMapStackingLayer5ColorBlendMode: 0 + - _BaseMapStackingLayer5Enable: 0 + - _BaseMapStackingLayer5MaskInvertColor: 0 + - _BaseMapStackingLayer5MaskRemapEnd: 1 + - _BaseMapStackingLayer5MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer5MaskRemapStart: 0 + - _BaseMapStackingLayer5MaskTexAsIDMap: 0 + - _BaseMapStackingLayer5MaskTexExtractFromID: 255 + - _BaseMapStackingLayer5MaskUVIndex: 0 + - _BaseMapStackingLayer5MasterStrength: 1 + - _BaseMapStackingLayer5TexIgnoreAlpha: 0 + - _BaseMapStackingLayer5TexUVIndex: 0 + - _BaseMapStackingLayer5TexUVRotateSpeed: 0 + - _BaseMapStackingLayer5TexUVRotatedAngle: 0 + - _BaseMapStackingLayer6ApplytoFaces: 0 + - _BaseMapStackingLayer6ColorBlendMode: 0 + - _BaseMapStackingLayer6Enable: 0 + - _BaseMapStackingLayer6MaskInvertColor: 0 + - _BaseMapStackingLayer6MaskRemapEnd: 1 + - _BaseMapStackingLayer6MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer6MaskRemapStart: 0 + - _BaseMapStackingLayer6MaskTexAsIDMap: 0 + - _BaseMapStackingLayer6MaskTexExtractFromID: 255 + - _BaseMapStackingLayer6MaskUVIndex: 0 + - _BaseMapStackingLayer6MasterStrength: 1 + - _BaseMapStackingLayer6TexIgnoreAlpha: 0 + - _BaseMapStackingLayer6TexUVIndex: 0 + - _BaseMapStackingLayer6TexUVRotateSpeed: 0 + - _BaseMapStackingLayer6TexUVRotatedAngle: 0 + - _BaseMapStackingLayer7ApplytoFaces: 0 + - _BaseMapStackingLayer7ColorBlendMode: 0 + - _BaseMapStackingLayer7Enable: 0 + - _BaseMapStackingLayer7MaskInvertColor: 0 + - _BaseMapStackingLayer7MaskRemapEnd: 1 + - _BaseMapStackingLayer7MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer7MaskRemapStart: 0 + - _BaseMapStackingLayer7MaskTexAsIDMap: 0 + - _BaseMapStackingLayer7MaskTexExtractFromID: 255 + - _BaseMapStackingLayer7MaskUVIndex: 0 + - _BaseMapStackingLayer7MasterStrength: 1 + - _BaseMapStackingLayer7TexIgnoreAlpha: 0 + - _BaseMapStackingLayer7TexUVIndex: 0 + - _BaseMapStackingLayer7TexUVRotateSpeed: 0 + - _BaseMapStackingLayer7TexUVRotatedAngle: 0 + - _BaseMapStackingLayer8ApplytoFaces: 0 + - _BaseMapStackingLayer8ColorBlendMode: 0 + - _BaseMapStackingLayer8Enable: 0 + - _BaseMapStackingLayer8MaskInvertColor: 0 + - _BaseMapStackingLayer8MaskRemapEnd: 1 + - _BaseMapStackingLayer8MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer8MaskRemapStart: 0 + - _BaseMapStackingLayer8MaskTexAsIDMap: 0 + - _BaseMapStackingLayer8MaskTexExtractFromID: 255 + - _BaseMapStackingLayer8MaskUVIndex: 0 + - _BaseMapStackingLayer8MasterStrength: 1 + - _BaseMapStackingLayer8TexIgnoreAlpha: 0 + - _BaseMapStackingLayer8TexUVIndex: 0 + - _BaseMapStackingLayer8TexUVRotateSpeed: 0 + - _BaseMapStackingLayer8TexUVRotatedAngle: 0 + - _BaseMapStackingLayer9ApplytoFaces: 0 + - _BaseMapStackingLayer9ColorBlendMode: 0 + - _BaseMapStackingLayer9Enable: 0 + - _BaseMapStackingLayer9MaskInvertColor: 0 + - _BaseMapStackingLayer9MaskRemapEnd: 1 + - _BaseMapStackingLayer9MaskRemapMinMaxSlider: 1 + - _BaseMapStackingLayer9MaskRemapStart: 0 + - _BaseMapStackingLayer9MaskTexAsIDMap: 0 + - _BaseMapStackingLayer9MaskTexExtractFromID: 255 + - _BaseMapStackingLayer9MaskUVIndex: 0 + - _BaseMapStackingLayer9MasterStrength: 1 + - _BaseMapStackingLayer9TexIgnoreAlpha: 0 + - _BaseMapStackingLayer9TexUVIndex: 0 + - _BaseMapStackingLayer9TexUVRotateSpeed: 0 + - _BaseMapStackingLayer9TexUVRotatedAngle: 0 + - _BaseMapUVIndex: 0 - _BlendMode: 0 + - _BlendOp: 0 - _BoostThreshold: 0 + - _BumpMapApplytoFaces: 0 + - _BumpMapUVIndex: 0 - _BumpScale: 1 - _BurnEffect: 0 + - _CelShadeMidPoint: 0 + - _CelShadeMidPointForFaceArea: -0.3 + - _CelShadeSoftness: 0.05 + - _CelShadeSoftnessForFaceArea: 0.15 - _Chagelinesize: 1 + - _CharacterAreaColorFillEnabled: 0 + - _CharacterAreaColorFillRendersBlockedArea: 0 + - _CharacterAreaColorFillRendersVisibleArea: 0 + - _CharacterAreaColorFillTextureUVIndex: 5 + - _CharacterBoundRadius: 1.25 + - _ColorMask: 15 + - _ColorRenderStatesGroup: 0 + - _ColorRenderStatesGroupPreset: 0 + - _ControlledByNiloToonPerCharacterRenderController: 0 + - _Cull: 2 - _CullMode: 2 + - _CullNiloToonSelfShadowCaster: 1 + - _CullOutline: 1 - _Cutoff: 0.5 + - _DebugFaceShadowGradientMap: 0 - _DebugMode: 0 + - _DecalAlbedoApplyStrength: 1 + - _DecalGroup: 0 + - _DecalNormalApplyStrength: 1 + - _DecalOcclusionApplyStrength: 1 + - _DecalSmoothnessApplyStrength: 1 + - _DecalSpecularApplyStrength: 1 + - _DepthRenderStatesGroup: 0 + - _DepthTexRimLight3DFallbackMidPoint: 0.7 + - _DepthTexRimLight3DFallbackRemoveFlatPolygonRimLight: 1 + - _DepthTexRimLight3DFallbackSoftness: 0.02 + - _DepthTexRimLight3DRimMaskEnable: 0 + - _DepthTexRimLight3DRimMaskThreshold: 0.5 + - _DepthTexRimLightAndShadowReduceWidthWhenCameraIsClose: 1 + - _DepthTexRimLightAndShadowSafeViewDistance: 1 + - _DepthTexRimLightAndShadowWidthExtraMultiplier: 1 + - _DepthTexRimLightAndShadowWidthMultiplier: 0.5 + - _DepthTexRimLightBlockByShadow: 0 + - _DepthTexRimLightFadeoutRange: 1 + - _DepthTexRimLightFixDottedLineArtifactsExtendMultiplier: 0.1 + - _DepthTexRimLightIgnoreLightDir: 0 + - _DepthTexRimLightIntensity: 1.5 + - _DepthTexRimLightMaskTexInvertColor: 0 + - _DepthTexRimLightMinimumThresholdOffsetForFace: 0.5 + - _DepthTexRimLightMixWithBaseMapColor: 0.5 + - _DepthTexRimLightThresholdOffset: 0 + - _DepthTexRimLightUsage: 1 + - _DepthTexRimLightWidthClampForFace: 0.5 + - _DepthTexRimLightWidthMultiplier: 1 + - _DepthTexShadowBrightness: 0.85 + - _DepthTexShadowBrightnessForFace: 1 + - _DepthTexShadowColorStyleForFacePreset: 0 + - _DepthTexShadowColorStyleForNonFacePreset: 0 + - _DepthTexShadowFadeoutRange: 1 + - _DepthTexShadowFixedDirectionForFace: 0 + - _DepthTexShadowThresholdOffset: 0 + - _DepthTexShadowUsage: 1 + - _DepthTexShadowWidthMultiplier: 1 + - _DetailAlbedoMapScale: 1 + - _DetailAlbedoWhitePoint: 0.5 + - _DetailMaskInvertColor: 0 - _DetailNormalMapScale: 1 + - _DetailUseSecondUv: 0 + - _DissolveAmount: 0 + - _DissolveBorderRange: 0.02 + - _DissolveNoiseStrength: 1 + - _DissolvePatternMapPreset: 0 + - _DissolveThresholdMapPreset: 0 + - _DissolveThresholdMapTilingX: 1 + - _DissolveThresholdMapTilingY: 1 - _Dissolve_Offset: 1 + - _DitherFadeoutAmount: 0 + - _DitherFadeoutNormalScaleFix: 1 - _DstBlend: 0 + - _DstBlendAlpha: 10 + - _DynamicEyeFinalBrightness: 2 + - _DynamicEyePupilDepthScale: 0.4 + - _DynamicEyePupilMaskSoftness: 0.216 + - _DynamicEyePupilSize: -0.384 + - _DynamicEyeSize: 2.2 + - _EditFinalOutputAlphaEnable: 0 - _EffectBland: 0 + - _EmissionAnimTintRampMapSpeed: 1 - _EmissionEffect: 0 + - _EmissionIntensity: 1 + - _EmissionMapUseSingleChannelOnly: 0 + - _EmissionMaskMapInvertColor: 0 + - _EmissionMaskMapRemapEnd: 1 + - _EmissionMaskMapRemapMinMaxSlider: 1 + - _EmissionMaskMapRemapStart: 0 + - _EnableDynamicEyeFeature: 0 + - _EnableEmissionAnimTintRampMap: 0 + - _EnableFace3DRimLightAndShadow: 0 + - _EnableNiloToonSelfShadowMapping: 1 + - _EnableNiloToonSelfShadowMappingDepthBias: 0 + - _EnableNiloToonSelfShadowMappingNormalBias: 0 + - _EnablePerMaterialDissolve: 0 + - _EnableRendering: 1 + - _EnableShadowColor: 1 + - _EnableUVEditGroup: 0 + - _EnvironmentReflectionApplyAddBlending: 0 + - _EnvironmentReflectionApplyReplaceBlending: 1 + - _EnvironmentReflectionApplytoFaces: 0 + - _EnvironmentReflectionBrightness: 1 + - _EnvironmentReflectionFresnelEffect: 0 + - _EnvironmentReflectionFresnelPower: 1 + - _EnvironmentReflectionFresnelRemapEnd: 1 + - _EnvironmentReflectionFresnelRemapMinMaxSlider: 1 + - _EnvironmentReflectionFresnelRemapStart: 0 + - _EnvironmentReflectionMaskMapInvertColor: 0 + - _EnvironmentReflectionMaskMapRemapEnd: 1 + - _EnvironmentReflectionMaskMapRemapMinMaxSlider: 1 + - _EnvironmentReflectionMaskMapRemapStart: 0 + - _EnvironmentReflectionShouldApplyToFaceArea: 0 + - _EnvironmentReflectionSmoothnessMultiplier: 1 + - _EnvironmentReflectionTintAlbedo: 1 + - _EnvironmentReflectionUsage: 1 - _Environmentaldata: 1 + - _ExtraThickOutlineEnabled: 0 + - _ExtraThickOutlineMaxFinalWidth: 100 + - _ExtraThickOutlineWidth: 4 + - _ExtraThickOutlineWriteIntoDepthTexture: 0 + - _ExtraThickOutlineZOffset: -0.1 + - _ExtraThickOutlineZWrite: 0 + - _Face3DRimLightAndShadow_CheekRimLightIntensity: 1 + - _Face3DRimLightAndShadow_CheekRimLightSoftness: 0.1 + - _Face3DRimLightAndShadow_CheekRimLightThreshold: 0.7 + - _Face3DRimLightAndShadow_CheekShadowIntensity: 1 + - _Face3DRimLightAndShadow_CheekShadowSoftness: 0.1 + - _Face3DRimLightAndShadow_CheekShadowThreshold: 0.7 + - _Face3DRimLightAndShadow_NoseRimLightIntensity: 1 + - _Face3DRimLightAndShadow_NoseShadowIntensity: 1 + - _FaceAreaCameraDepthTextureZWriteOffset: 0.04 + - _FaceMaskMapInvertColor: 0 + - _FaceMaskMapRemapEnd: 1 + - _FaceMaskMapRemapMinMaxSlider: 1 + - _FaceMaskMapRemapStart: 0 + - _FaceShadowBrightness: 1 + - _FaceShadowGradientIntensity: 1 + - _FaceShadowGradientMapFaceMidPoint: 0.5 + - _FaceShadowGradientMapInvertColor: 0 + - _FaceShadowGradientMapPreset: 0 + - _FaceShadowGradientMapUVIndex: 0 + - _FaceShadowGradientMapUVxInvert: 1 + - _FaceShadowGradientMaskMapInvertColor: 0 + - _FaceShadowGradientMaskMapUVIndex: 0 + - _FaceShadowGradientOffset: 0.1 + - _FaceShadowGradientResultSoftness: 0.005 + - _FaceShadowGradientThresholdMax: 1 + - _FaceShadowGradientThresholdMin: 0 + - _FaceShadowGradientThresholdMinMax: 1 - _FakeReflectBlur: 0.5 - _FakeReflectonoff: 0 + - _FixFaceNormalAmount: 1 + - _FixFaceNormalAmountPerMaterial: 1 + - _FixFaceNormalUseFlattenOrProxySphereMethod: 0 + - _ForceFinalOutputAlphaEqualsOne: 0 + - _GGXDirectSpecularSmoothnessMultiplier: 1 - _GlayEffect: 0 - _GlossMapScale: 1 - _Glossiness: 0.5 - _GlossyReflections: 1 + - _HairStrandSpecularMainExponent: 256 + - _HairStrandSpecularMainIntensity: 1 + - _HairStrandSpecularMixWithBaseMapColor: 0.5 + - _HairStrandSpecularOverallIntensity: 1 + - _HairStrandSpecularSecondExponent: 128 + - _HairStrandSpecularSecondIntensity: 1 + - _HairStrandSpecularShapeFrequency: 750 + - _HairStrandSpecularShapePositionOffset: 0 + - _HairStrandSpecularShapeShift: 0.015 + - _HairStrandSpecularTintMapUsage: 1 + - _HairStrandSpecularUVDirection: 0 + - _HairStrandSpecularUVIndex: 0 - _HighlightCellOffset: -1 - _IceEffect: 0 + - _IgnoreDefaultMainLightFaceShadow: 1 - _IndirectDiffuseContribution: 1 + - _IndirectLightFlatten: 1 - _IndirectLightIntensity: 0.1 - _IndirectSpecularContribution: 1 + - _IsFace: 0 + - _IsSkin: 0 - _LightColorAttenuation: 0 - _LightEffect: 0 - _LightEnvironmentalValue: 1 + - _LightingStyleDirectionalLightRenderFacePreset: 0 + - _LightingStyleFaceOverrideGroup: 0 + - _LightingStyleGroup: 0 - _LineEffect_Sel: 0 + - _LitToShadowTransitionAreaHueOffset: 0.01 + - _LitToShadowTransitionAreaIntensity: 1 + - _LitToShadowTransitionAreaSaturationBoost: 0.5 + - _LitToShadowTransitionAreaValueMul: 1 - _MToonVersion: 38 + - _MainLightIgnoreCelShade: 0 + - _MainLightIgnoreCelShadeForFaceArea: 0 + - _MainLightNonSkinDiffuseNormalMapStrength: 1 + - _MainLightSkinDiffuseNormalMapStrength: 1 - _MaskClipValue: 0.5 + - _MatCapAdditiveApplytoFaces: 0 + - _MatCapAdditiveExtractBrightArea: 0 + - _MatCapAdditiveIntensity: 1 + - _MatCapAdditiveMapAlphaAsMask: 0 + - _MatCapAdditiveMaskMapInvertColor: 0 + - _MatCapAdditiveMaskMapRemapEnd: 1 + - _MatCapAdditiveMaskMapRemapMinMaxSlider: 1 + - _MatCapAdditiveMaskMapRemapStart: 0 + - _MatCapAdditiveMixWithBaseMapColor: 0.5 + - _MatCapAdditivePreset: 0 + - _MatCapAdditiveUvScale: 1 + - _MatCapAlphaBlendMapAlphaAsMask: 0 + - _MatCapAlphaBlendMaskMapInvertColor: 0 + - _MatCapAlphaBlendMaskMapRemapEnd: 1 + - _MatCapAlphaBlendMaskMapRemapMinMaxSlider: 1 + - _MatCapAlphaBlendMaskMapRemapStart: 0 + - _MatCapAlphaBlendPreset: 0 + - _MatCapAlphaBlendUsage: 1 + - _MatCapAlphaBlendUvScale: 1 + - _MatCapOcclusionIntensity: 1 + - _MatCapOcclusionMapAlphaAsMask: 0 + - _MatCapOcclusionMapRemapEnd: 1 + - _MatCapOcclusionMapRemapMinMaxSlider: 1 + - _MatCapOcclusionMapRemapStart: 0 + - _MatCapOcclusionMaskMapInvert: 0 + - _MatCapOcclusionMaskMapRemapEnd: 1 + - _MatCapOcclusionMaskMapRemapMinMaxSlider: 1 + - _MatCapOcclusionMaskMapRemapStart: 0 + - _MatCapOcclusionPreset: 0 + - _MatCapOcclusionUvScale: 1 - _MatCap_Blur: 0 - _Matcaponoff: 0 - _Metallic: 0 - _Mode: 0 + - _MultiplyBRPColor: 0 + - _MultiplyBaseColorToEmissionColor: 0 + - _MultiplyBaseColorToSpecularColor: 0.5 + - _MultiplyLightColorToEmissionColor: 0 + - _NiloGlitterDensity: 1 + - _NiloGlitterIntensity: 1 + - _NiloGlitterRndomNormalStrength: 0.5 + - _NiloGlitterSize: 1 + - _NiloGlitterTintColorTexUVIndex: 0 + - _NiloGlitterUVIndex: 0 + - _NiloToonSelfShadowIntensity: 1 + - _NiloToonSelfShadowIntensityForFace: 0 + - _NiloToonSelfShadowIntensityForNonFace: 1 + - _NiloToonSelfShadowMappingDepthBias: 0 + - _NiloToonSelfShadowMappingNormalBias: 0 - _NoiseSize: 4 - _NormalScale: 1 + - _OcclusionMapApplytoFaces: 0 + - _OcclusionMapInvertColor: 0 + - _OcclusionMapStylePreset: 0 + - _OcclusionMapUVIndex: 0 + - _OcclusionRemapEnd: 1 + - _OcclusionRemapMinMaxSlider: 1 + - _OcclusionRemapStart: 0 - _OcclusionStrength: 1 - _OutLineOnOff: 0 + - _OutlineApplyAutoWidthAdjustment: 1 + - _OutlineBaseZOffset: 0 - _OutlineColorMode: 0 - _OutlineCullMode: 1 - _OutlineLightingMix: 1 - _OutlineScaledMaxDistance: 1 + - _OutlineUniformLengthInViewSpace: 0 + - _OutlineUseBakedSmoothNormal: 1 + - _OutlineUsePreLightingReplaceColor: 0 + - _OutlineUseReplaceColor: 0 - _OutlineWidth: 0.04 + - _OutlineWidthExtraMultiplier: 1 - _OutlineWidthMode: 1 + - _OutlineZOffset: 0.0001 + - _OutlineZOffsetForFaceArea: 0.02 + - _OutlineZOffsetMaskRemapEnd: 1 + - _OutlineZOffsetMaskRemapMinMaxSlider: 1 + - _OutlineZOffsetMaskRemapStart: 0 + - _OutlineZOffsetMaskTexFromVertexColorInvertColor: 0 + - _OutlineZOffsetMaskTexInvertColor: 0 + - _OverrideAdditionalLightCelShadeParamForFaceArea: 1 + - _OverrideByFaceShadowTintColor: 1 + - _OverrideBySkinShadowTintColor: 1 + - _OverrideCelShadeParamForFaceArea: 1 + - _OverrideOutlineColorByTexIntensity: 1 + - _OverrideOutlineColorTexIgnoreAlphaChannel: 0 + - _OverrideShadowColorByTexIntensity: 1 + - _OverrideShadowColorByTexMode: 0 + - _OverrideShadowColorMaskMapInvertColor: 0 + - _OverrideShadowColorTexIgnoreAlphaChannel: 0 - _Parallax: 0.02 + - _ParallaxApplyToUVIndex: 0 + - _ParallaxMapEnable: 0 + - _ParallaxSampleUVIndex: 0 + - _PassOnOffGroup: 0 + - _PerCharEffectDesaturatePercentage: 0 + - _PerCharEffectRimSharpnessPower: 4 + - _PerCharReceiveAverageURPShadowMap: 1 + - _PerCharReceiveNiloToonSelfShadowMap: 1 + - _PerCharReceiveStandardURPShadowMap: 1 + - _PerCharZOffset: 0 + - _PerCharacterBaseMapOverrideAmount: 0 + - _PerCharacterBaseMapOverrideBlendMode: 0 + - _PerCharacterBaseMapOverrideUVIndex: 0 + - _PerCharacterEffectGroup: 0 + - _PerCharacterOutlineWidthMultiply: 1 + - _PerCharacterRenderOutline: 1 + - _PerMaterialDissolveCutoff: -1 + - _PerMaterialDissolveEdgeWidth: 0.05 + - _PerMaterialDissolvePatternMapInvertColor: 0 + - _PerMaterialDissolvePatternMapStrength: 0.1 + - _PerMaterialDissolvePatternMapUVIndex: 0 + - _PerMaterialDissolvePatternMapUVTiling: 1 + - _PerMaterialDissolveThresholdMapInvertColor: 0 + - _PerMaterialDissolveThresholdMapUVIndex: 0 + - _PerMaterialDissolveThresholdMapUVTiling: 1 + - _PerMaterialEnableDepthTextureRimLightAndShadow: 1 + - _PerspectiveRemovalAmount: 0 + - _PerspectiveRemovalEndHeight: 1 + - _PerspectiveRemovalRadius: 1 + - _PerspectiveRemovalStartHeight: 0 + - _PreMultiplyAlphaIntoRGBOutput: 0 + - _RampLightTexMode: 1 + - _RampLightingFaceAreaRemoveEffect: 1 + - _RampLightingNdotLRemapEnd: 1 + - _RampLightingNdotLRemapMinMaxSlider: 1 + - _RampLightingNdotLRemapStart: 0 + - _RampLightingSampleUvYTexInvertColor: 0 + - _RampLightingTexSampleUvY: 0.5 + - _RampLightingUvYRemapEnd: 1 + - _RampLightingUvYRemapMinMaxSlider: 1 + - _RampLightingUvYRemapStart: 0 + - _RampSpecularTexSampleUvY: 0.5 + - _RampSpecularWhitePoint: 0.5 + - _ReceiveEnvironmentReflection: 0 + - _ReceiveSelfShadowMappingPosOffset: 0 + - _ReceiveSelfShadowMappingPosOffsetForFaceArea: 1 - _ReceiveShadowRate: 1 + - _ReceiveURPAdditionalLightShadowMapping: 1 + - _ReceiveURPAdditionalLightShadowMappingAmount: 1 + - _ReceiveURPAdditionalLightShadowMappingAmountForFace: 1 + - _ReceiveURPAdditionalLightShadowMappingAmountForNonFace: 1 + - _ReceiveURPShadowMapping: 1 + - _ReceiveURPShadowMappingAmount: 1 + - _ReceiveURPShadowMappingAmountForFace: 1 + - _ReceiveURPShadowMappingAmountForNonFace: 1 + - _RenderCharacter: 1 + - _RenderFaceGroup: 0 + - _RenderFacePreset: 0 + - _RenderOutline: 1 + - _RenderScreenSpaceOutline: 0 + - _RenderScreenSpaceOutlineV2: 0 - _RimColorPower: 1 - _RimFresnelPower: 1 - _RimLift: 0 - _RimLightingMix: 0 - _RimOffset: 0.6 - _RimPower: 0.4 + - _ScreenSpaceOutlineDepthSensitivity: 1 + - _ScreenSpaceOutlineDepthSensitivityIfFace: 1 + - _ScreenSpaceOutlineDepthSensitivityTexRemapEnd: 1 + - _ScreenSpaceOutlineDepthSensitivityTexRemapMinMaxSlider: 1 + - _ScreenSpaceOutlineDepthSensitivityTexRemapStart: 0 + - _ScreenSpaceOutlineNormalsSensitivity: 1 + - _ScreenSpaceOutlineNormalsSensitivityIfFace: 1 + - _ScreenSpaceOutlineNormalsSensitivityTexRemapEnd: 1 + - _ScreenSpaceOutlineNormalsSensitivityTexRemapMinMaxSlider: 1 + - _ScreenSpaceOutlineNormalsSensitivityTexRemapStart: 0 + - _ScreenSpaceOutlineUseReplaceColor: 0 + - _ScreenSpaceOutlineWidth: 1 + - _ScreenSpaceOutlineWidthIfFace: 0 + - _SelfShadowAreaHSVStrength: 1 + - _SelfShadowAreaHueOffset: 0 + - _SelfShadowAreaSaturationBoost: 0.2 + - _SelfShadowAreaValueMul: 0.7 - _SetGray: 0 - _ShadeShift: 0 - _ShadeToony: 0.9 + - _ShadingGradeMapApplyRange: 1 + - _ShadingGradeMapInvertColor: 0 + - _ShadingGradeMapMidPointOffset: 0 + - _ShadingGradeMapRemapEnd: 1 + - _ShadingGradeMapRemapMinMaxSlider: 1 + - _ShadingGradeMapRemapStart: 0 + - _ShadingGradeMapStrength: 1 - _ShadingGradeRate: 1 - _ShadowBoost: 0 + - _SkinFaceShadowColorPreset: 0 + - _SkinMaskMapAsIDMap: 0 + - _SkinMaskMapExtractFromID: 255 + - _SkinMaskMapInvertColor: 0 + - _SkinMaskMapRemapEnd: 1 + - _SkinMaskMapRemapMinMaxSlider: 1 + - _SkinMaskMapRemapStart: 0 + - _SkinShadowBrightness: 1 + - _Smoothness: 0.5 + - _SmoothnessGroup: 0 + - _SmoothnessMapInputIsRoughnessMap: 0 + - _SmoothnessMapRemapEnd: 1 + - _SmoothnessMapRemapMinMaxSlider: 1 + - _SmoothnessMapRemapStart: 0 - _SmoothnessTextureChannel: 0 + - _SpecularApplytoFaces: 0 + - _SpecularAreaRemapMidPoint: 0.1 + - _SpecularAreaRemapRange: 0.05 + - _SpecularAreaRemapUsage: 0 + - _SpecularColorTintMapUsage: 1 + - _SpecularColorTintMapUseSecondUv: 0 - _SpecularHighlights: 1 + - _SpecularIntensity: 1 + - _SpecularMapAsIDMap: 0 + - _SpecularMapExtractFromID: 255 + - _SpecularMapInvertColor: 0 + - _SpecularMapRemapEnd: 1 + - _SpecularMapRemapMinMaxSlider: 1 + - _SpecularMapRemapStart: 0 + - _SpecularMapUVIndex: 0 + - _SpecularReactToLightDirMode: 0 + - _SpecularShowInShadowArea: 0 + - _SpecularUseReplaceBlending: 0 - _SrcBlend: 1 + - _SrcBlendAlpha: 1 - _StaticHighLights: 0 + - _StencilComp: 0 + - _StencilGroup: 0 + - _StencilPass: 0 + - _StencilPreset: 0 + - _StencilRef: 0 + - _SupportClothDynamics: 0 + - _SurfaceTypePreset: 0 - _TileSize: 10 + - _UIDisplayMode: 100 + - _UV0RotateSpeed: 0 + - _UV0RotatedAngle: 0 + - _UV1RotateSpeed: 0 + - _UV1RotatedAngle: 0 + - _UV2RotateSpeed: 0 + - _UV2RotatedAngle: 0 + - _UV3RotateSpeed: 0 + - _UV3RotatedAngle: 0 - _UVSec: 0 + - _UnityCameraDepthTextureWriteOutlineExtrudedPosition: 0 + - _UseAlphaOverrideTex: 0 + - _UseDepthTexRimLightAndShadowWidthMultiplierFromVertexColor: 0 + - _UseDepthTexRimLightAndShadowWidthTex: 0 + - _UseDepthTexRimLightMaskTex: 0 + - _UseDetailMap: 0 + - _UseEmission: 0 + - _UseFaceMaskMap: 0 + - _UseFaceShadowGradientMap: 0 + - _UseGGXDirectSpecular: 1 + - _UseHairStrandSpecularTintMap: 0 + - _UseKajiyaKaySpecular: 0 + - _UseMatCapAdditive: 0 + - _UseMatCapAlphaBlend: 0 + - _UseMatCapOcclusion: 0 + - _UseNiloGlitter: 0 + - _UseNiloToonSelfShadowIntensityMultiplierTex: 0 + - _UseNormalMap: 0 + - _UseOcclusion: 0 + - _UseOutlineTintColorMap: 0 + - _UseOutlineWidthMaskFromVertexColor: 0 + - _UseOutlineWidthTex: 0 + - _UseOutlineZOffsetMaskFromVertexColor: 0 + - _UseOutlineZOffsetTex: 0 + - _UseOverrideOutlineColorByTexture: 0 + - _UseOverrideShadowColorByTexture: 0 + - _UseRampLightingSampleUvYTex: 0 + - _UseRampLightingTex: 0 + - _UseRampSpecularSampleUvYTex: 0 + - _UseRampSpecularTex: 0 + - _UseShadingGradeMap: 0 + - _UseSkinMaskMap: 0 + - _UseSmoothnessMap: 0 + - _UseSpecular: 0 + - _UseSpecularColorTintMap: 0 + - _UseZOffsetMaskTex: 0 - _UvAnimRotation: 0 - _UvAnimScrollX: 0 - _UvAnimScrollY: 0 - _Worldline: -2 - _WorldorDissolvemask: 0 + - _XRMotionVectorsPass: 1 + - _ZOffset: 0 + - _ZOffsetEnable: 0 + - _ZOffsetMaskMapInvertColor: 0 + - _ZOffsetMultiplierForTraditionalOutlinePass: 1 + - _ZOffsetPreset: 0 + - _ZTest: 4 - _ZWrite: 1 - __dirty: 0 m_Colors: + - _AlphaOverrideTexChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _BackFaceBaseMapReplaceColor: {r: 0, g: 0, b: 0, a: 0} + - _BackFaceTintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseColor2: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer10MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer10TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer10TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer10TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer10TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer1MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer1TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer1TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer1TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer1TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer2MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer2TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer2TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer2TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer2TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer3MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer3TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer3TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer3TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer3TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer4MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer4TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer4TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer4TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer4TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer5MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer5TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer5TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer5TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer5TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer6MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer6TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer6TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer6TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer6TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer7MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer7TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer7TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer7TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer7TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer8MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer8TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer8TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer8TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer8TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseMapStackingLayer9MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer9TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} + - _BaseMapStackingLayer9TexUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer9TexUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BaseMapStackingLayer9TintColor: {r: 1, g: 1, b: 1, a: 1} + - _BumpMapUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _BumpMapUVScrollSpeed: {r: 0, g: 0, b: 0, a: 0} + - _CharacterAreaColorFillColor: {r: 1, g: 1, b: 1, a: 0.5} + - _CharacterAreaColorFillTextureUVScrollSpeed: {r: 0, g: 0, b: 0, a: 1} + - _CharacterAreaColorFillTextureUVTilingOffset: {r: 1, g: 1, b: 0, a: 0} + - _CharacterBoundCenterPosWS: {r: 0, g: 0, b: 0, a: 1} - _Color: {r: 0.33962262, g: 0.33962262, b: 0.33962262, a: 1} + - _DepthTexRimLightAndShadowWidthMultiplierFromVertexColorChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _DepthTexRimLightAndShadowWidthTexChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _DepthTexRimLightMaskTexChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _DepthTexRimLightTintColor: {r: 1, g: 1, b: 1, a: 1} + - _DepthTexShadowTintColor: {r: 1, g: 1, b: 1, a: 1} + - _DepthTexShadowTintColorForFace: {r: 1, g: 0.85, b: 0.85, a: 1} + - _DetailMapsScaleTiling: {r: 1, g: 1, b: 0, a: 0} + - _DetailMaskChannelMask: {r: 1, g: 0, b: 0, a: 0} + - _DissolveBorderTintColor: {r: 0, g: 4, b: 4, a: 1} - _DissolveLineColor: {r: 0, g: 0, b: 0, a: 0} + - _DynamicEyeFinalTintColor: {r: 1, g: 1, b: 1, a: 1} + - _DynamicEyePupilColor: {r: 1, g: 1, b: 1, a: 1} + - _DynamicEyePupilMaskTexChannelMask: {r: 0, g: 0, b: 0, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _EmissionMapSingleChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _EmissionMapTilingXyOffsetZw: {r: 1, g: 1, b: 0, a: 0} + - _EmissionMapUVScrollSpeed: {r: 0, g: 0, b: 0, a: 0} + - _EmissionMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _EnvironmentReflectionColor: {r: 1, g: 1, b: 1, a: 1} + - _EnvironmentReflectionMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _ExtraThickOutlineColor: {r: 1, g: 1, b: 1, a: 1} + - _ExtraThickOutlineViewSpacePosOffset: {r: 0, g: 0, b: 0, a: 1} + - _Face3DRimLightAndShadow_CheekRimLightMaskMapChannel: {r: 1, g: 0, b: 0, a: 0} + - _Face3DRimLightAndShadow_CheekRimLightTintColor: {r: 1, g: 1, b: 1, a: 1} + - _Face3DRimLightAndShadow_CheekShadowMaskMapChannel: {r: 1, g: 0, b: 0, a: 0} + - _Face3DRimLightAndShadow_CheekShadowTintColor: {r: 1, g: 1, b: 1, a: 1} + - _Face3DRimLightAndShadow_NoseRimLightMaskMapChannel: {r: 1, g: 0, b: 0, a: 0} + - _Face3DRimLightAndShadow_NoseRimLightTintColor: {r: 1, g: 1, b: 1, a: 1} + - _Face3DRimLightAndShadow_NoseShadowMaskMapChannel: {r: 1, g: 0, b: 0, a: 0} + - _Face3DRimLightAndShadow_NoseShadowTintColor: {r: 1, g: 1, b: 1, a: 1} + - _FaceForwardDirection: {r: 0, g: 0, b: 1, a: 1} + - _FaceMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _FaceShadowGradientMapChannel: {r: 1, g: 0, b: 0, a: 0} + - _FaceShadowGradientMapUVCenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _FaceShadowGradientMapUVScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _FaceShadowGradientMaskMapChannel: {r: 0, g: 1, b: 0, a: 0} + - _FaceShadowTintColor: {r: 1, g: 0.9, b: 0.9, a: 1} + - _FaceShadowTintColor2: {r: 1, g: 1, b: 1, a: 1} + - _FaceUpDirection: {r: 0, g: 1, b: 0, a: 1} + - _HairStrandSpecularMainColor: {r: 1, g: 1, b: 1, a: 1} + - _HairStrandSpecularSecondColor: {r: 1, g: 1, b: 1, a: 1} + - _HairStrandSpecularTintMapTilingXyOffsetZw: {r: 1, g: 1, b: 0, a: 0} + - _HeadBonePositionWS: {r: 0, g: 0, b: 0, a: 1} - _HighlightTint: {r: 1, g: 1, b: 1, a: 1} - _LineEmissoin: {r: 0, g: 0, b: 0, a: 0} + - _LitToShadowTransitionAreaTintColor: {r: 1, g: 1, b: 1, a: 1} + - _LowSaturationFallbackColor: {r: 0.3764706, g: 0.4141177, b: 0.5019608, a: 0} + - _MatCapAdditiveColor: {r: 1, g: 1, b: 1, a: 1} + - _MatCapAdditiveMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _MatCapAlphaBlendMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _MatCapAlphaBlendTintColor: {r: 1, g: 1, b: 1, a: 1} + - _MatCapOcclusionMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _MatCapOcclusionMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _MatCapUVTiling: {r: 1, g: 1, b: 0, a: 0} + - _NiloGlitterTintColor: {r: 1, g: 1, b: 1, a: 1} + - _NiloToonSelfShadowMappingTintColor: {r: 1, g: 1, b: 1, a: 1} + - _OcclusionMapChannelMask: {r: 0, g: 1, b: 0, a: 0} - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _OutlineOcclusionAreaTintColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlinePreLightingReplaceColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlineReplaceColor: {r: 1, g: 1, b: 1, a: 1} - _OutlineTint: {r: 0.5754717, g: 0.5754717, b: 0.5754717, a: 1} + - _OutlineTintColor: {r: 0.25, g: 0.25, b: 0.25, a: 1} + - _OutlineTintColorSkinAreaOverride: {r: 0.4, g: 0.2, b: 0.2, a: 1} + - _OutlineWidthMaskFromVertexColor: {r: 0, g: 1, b: 0, a: 0} + - _OutlineWidthTexChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _OutlineZOffsetMaskFromVertexColor: {r: 0, g: 1, b: 0, a: 0} + - _OutlineZOffsetMaskTexChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _OverrideOutlineColorTexTintColor: {r: 1, g: 1, b: 1, a: 1} + - _OverrideShadowColorMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _OverrideShadowColorTexTintColor: {r: 1, g: 1, b: 1, a: 1} + - _PerCharEffectAddColor: {r: 0, g: 0, b: 0, a: 1} + - _PerCharEffectLerpColor: {r: 1, g: 1, b: 0, a: 0} + - _PerCharEffectRimColor: {r: 0, g: 0, b: 0, a: 1} + - _PerCharEffectTintColor: {r: 1, g: 1, b: 1, a: 1} + - _PerCharacterBaseColorTint: {r: 1, g: 1, b: 1, a: 1} + - _PerCharacterBaseMapOverrideTilingOffset: {r: 1, g: 1, b: 0, a: 0} + - _PerCharacterBaseMapOverrideTintColor: {r: 1, g: 1, b: 1, a: 1} + - _PerCharacterBaseMapOverrideUVScrollSpeed: {r: 0, g: 0, b: 0, a: 0} + - _PerCharacterOutlineColorLerp: {r: 1, g: 1, b: 1, a: 0} + - _PerCharacterOutlineColorTint: {r: 1, g: 1, b: 1, a: 1} + - _PerMaterialDissolveEdgeColor: {r: 16, g: 8, b: 0, a: 1} + - _PerMaterialDissolvePatternMapChannelMask: {r: 1, g: 0, b: 0, a: 0} + - _PerMaterialDissolveThresholdMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _RampLightingSampleUvYTexChannelMask: {r: 0, g: 1, b: 0, a: 0} - _RimColor: {r: 0, g: 0, b: 0, a: 1} + - _ScreenSpaceOutlineDepthSensitivityTexChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _ScreenSpaceOutlineNormalsSensitivityTexChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _ScreenSpaceOutlineOcclusionAreaTintColor: {r: 1, g: 1, b: 1, a: 1} + - _ScreenSpaceOutlineReplaceColor: {r: 1, g: 1, b: 1, a: 1} + - _ScreenSpaceOutlineTintColor: {r: 0.1, g: 0.1, b: 0.1, a: 1} + - _SelfShadowTintColor: {r: 1, g: 1, b: 1, a: 1} - _ShadeColor: {r: 0, g: 0, b: 0, a: 1} + - _ShadingGradeMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _SkinMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} + - _SkinShadowTintColor: {r: 1, g: 0.8, b: 0.8, a: 1} + - _SkinShadowTintColor2: {r: 1, g: 1, b: 1, a: 1} + - _SmoothnessMapChannelMask: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecularColorTintMapTilingXyOffsetZw: {r: 1, g: 1, b: 0, a: 0} + - _SpecularMapChannelMask: {r: 0, g: 0, b: 1, a: 0} + - _URPShadowMappingTintColor: {r: 1, g: 1, b: 1, a: 1} + - _UV0CenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _UV0ScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _UV0ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} + - _UV1CenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _UV1ScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _UV1ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} + - _UV2CenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _UV2ScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _UV2ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} + - _UV3CenterPivotScalePos: {r: 1, g: 1, b: 0, a: 0} + - _UV3ScaleOffset: {r: 1, g: 1, b: 0, a: 0} + - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _VolumeInvSize: {r: 0, g: 0, b: 0, a: 0} - _VolumeMin: {r: 0, g: 0, b: 0, a: 0} + - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/B_B_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/B_B_Copy.mat index 734282c17..2f0fc22b3 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/B_B_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/B_B_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: B_B_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _ALPHAOVERRIDEMAP - _BASEMAP_STACKING_LAYER1 @@ -26,6 +28,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1563,7 +1566,7 @@ Material: - _BackFaceTintColor: {r: 1, g: 1, b: 1, a: 1} - _BackfaceColor: {r: 0, g: 0, b: 0, a: 0} - _BacklightColor: {r: 6.4416227, g: 6.4416227, b: 6.4416227, a: 1} - - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _BaseColor: {r: 1, g: 1, b: 1, a: 0.3137255} - _BaseColor2: {r: 1, g: 1, b: 1, a: 1} - _BaseMapStackingLayer10MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} - _BaseMapStackingLayer10TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} @@ -1822,3 +1825,4 @@ Material: - _egc6: {r: 1, g: 1, b: 1, a: 0} - _egc7: {r: 1, g: 1, b: 1, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Black_B_R_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Black_B_R_Copy.mat index aabac0b96..b879ae126 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Black_B_R_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Black_B_R_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Black_B_R_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _ALPHAOVERRIDEMAP - _BASEMAP_STACKING_LAYER1 @@ -26,6 +28,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1822,3 +1825,4 @@ Material: - _egc6: {r: 1, g: 1, b: 1, a: 0} - _egc7: {r: 1, g: 1, b: 1, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Body_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Body_Copy.mat index e31ed9b37..a537150c5 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Body_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Body_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Body_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _MATCAP_OCCLUSION @@ -21,6 +23,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1177,3 +1180,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Ear_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Ear_Copy.mat index 54ba4ec11..b42eedf21 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Ear_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Ear_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Ear_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _RECEIVE_URP_SHADOW @@ -21,6 +23,7 @@ Material: stringTagMap: {} disabledShaderPasses: - NiloToonSelfShadowCaster + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1176,3 +1179,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Alpha_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Alpha_Copy.mat index a36dccdce..df251a08e 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Alpha_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Alpha_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Face_Alpha_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _ALPHAOVERRIDEMAP - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS @@ -22,6 +24,7 @@ Material: stringTagMap: {} disabledShaderPasses: - NiloToonOutline + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1178,3 +1181,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Copy.mat index 09bf3b111..2a86eac19 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Face_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _EMISSION @@ -23,6 +25,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1179,3 +1182,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Heart_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Heart_Copy.mat index 12d1186b4..85612151a 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Heart_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Face_Heart_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Face_Heart_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _ISFACE @@ -21,6 +23,7 @@ Material: stringTagMap: {} disabledShaderPasses: - NiloToonOutline + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1177,3 +1180,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Back_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Back_Copy.mat index c823d9ccb..3a3208e24 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Back_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Back_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Hair_Back_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _KAJIYAKAY_SPECULAR @@ -24,6 +26,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1179,3 +1182,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Front_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Front_Copy.mat index cc966226f..5870aad86 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Front_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Front_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Hair_Front_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _KAJIYAKAY_SPECULAR @@ -24,6 +26,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1179,3 +1182,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Side_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Side_Copy.mat index a39aade80..0ac83b128 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Side_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Hair_Side_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Hair_Side_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _KAJIYAKAY_SPECULAR @@ -24,6 +26,7 @@ Material: m_CustomRenderQueue: -1 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1139,3 +1142,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Horn_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Horn_Copy.mat index bf0905790..b2a7473fe 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Horn_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Horn_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Horn_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _EMISSION @@ -22,6 +24,7 @@ Material: stringTagMap: {} disabledShaderPasses: - NiloToonSelfShadowCaster + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1177,3 +1180,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Inwear_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Inwear_Copy.mat index ec83d52c2..6fb69daa6 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Inwear_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Inwear_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Inwear_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _RECEIVE_URP_SHADOW @@ -19,6 +21,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1175,3 +1178,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/New Material_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/New Material_Copy.mat index 4434c6843..639116ae7 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/New Material_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/New Material_Copy.mat @@ -9,19 +9,24 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: New Material_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _BASEMAP_STACKING_LAYER1 - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _RECEIVE_URP_SHADOW - _SPECULARHIGHLIGHTS m_InvalidKeywords: + - _ENVIRONMENTREFLECTIONS_OFF - _GLOSSYREFLECTIONS_OFF m_LightmapFlags: 4 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 m_CustomRenderQueue: 2000 stringTagMap: {} - disabledShaderPasses: [] + disabledShaderPasses: + - MOTIONVECTORS + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -914,7 +919,7 @@ Material: - _SkinMaskMapRemapMinMaxSlider: 1 - _SkinMaskMapRemapStart: 0 - _SkinShadowBrightness: 1 - - _Smoothness: 0.346 + - _Smoothness: 0 - _SmoothnessGroup: 0 - _SmoothnessMapInputIsRoughnessMap: 0 - _SmoothnessMapRemapEnd: 1 @@ -1008,7 +1013,7 @@ Material: - _AlphaOverrideTexChannelMask: {r: 0, g: 1, b: 0, a: 0} - _BackFaceBaseMapReplaceColor: {r: 0, g: 0, b: 0, a: 0} - _BackFaceTintColor: {r: 1, g: 1, b: 1, a: 1} - - _BaseColor: {r: 0.01860091, g: 0.018627828, b: 0.01886791, a: 1} + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} - _BaseColor2: {r: 1, g: 1, b: 1, a: 1} - _BaseMapStackingLayer10MaskTexChannel: {r: 0, g: 1, b: 0, a: 0} - _BaseMapStackingLayer10TexUVAnimSpeed: {r: 0, g: 0, b: 0, a: 0} @@ -1066,7 +1071,7 @@ Material: - _CharacterAreaColorFillTextureUVScrollSpeed: {r: 0, g: 0, b: 0, a: 1} - _CharacterAreaColorFillTextureUVTilingOffset: {r: 1, g: 1, b: 0, a: 0} - _CharacterBoundCenterPosWS: {r: 0, g: 0, b: 0, a: 1} - - _Color: {r: 1, g: 1, b: 1, a: 1} + - _Color: {r: 0.01860091, g: 0.018627828, b: 0.01886791, a: 1} - _DepthTexRimLightAndShadowWidthMultiplierFromVertexColorChannelMask: {r: 0, g: 1, b: 0, a: 0} - _DepthTexRimLightAndShadowWidthTexChannelMask: {r: 0, g: 1, b: 0, a: 0} - _DepthTexRimLightMaskTexChannelMask: {r: 0, g: 1, b: 0, a: 0} @@ -1177,3 +1182,17 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &4723840190139575602 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Tail_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Tail_Copy.mat index 66683f45f..2e278a9e8 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Tail_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/Tail_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: Tail_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _RECEIVE_URP_SHADOW @@ -22,6 +24,7 @@ Material: stringTagMap: {} disabledShaderPasses: - NiloToonSelfShadowCaster + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1177,3 +1180,4 @@ Material: - _UV3ScrollSpeed: {r: 0, g: 0, b: 0, a: 0} - _ZOffsetMaskMapChannelMask: {r: 0, g: 1, b: 0, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/W_B_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/W_B_Copy.mat index 9faa2a053..51a0d0573 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/W_B_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/W_B_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: W_B_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _BASEMAP_STACKING_LAYER1 - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS @@ -24,6 +26,7 @@ Material: m_CustomRenderQueue: 2000 stringTagMap: {} disabledShaderPasses: [] + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1813,3 +1816,4 @@ Material: - _egc6: {r: 1, g: 1, b: 1, a: 0} - _egc7: {r: 1, g: 1, b: 1, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/underpants_Copy.mat b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/underpants_Copy.mat index 4ca8ae849..ba5c497be 100644 --- a/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/underpants_Copy.mat +++ b/Assets/ResourcesData/Character/@018_만타/Avatar/만타_260119_검정수트/Materials/underpants_Copy.mat @@ -9,6 +9,8 @@ Material: m_PrefabAsset: {fileID: 0} m_Name: underpants_Copy m_Shader: {fileID: 4800000, guid: b4f674f383806e5419ee221e39445de0, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 m_ValidKeywords: - _DEPTHTEX_RIMLIGHT_FIX_DOTTED_LINE_ARTIFACTS - _NORMALMAP @@ -21,6 +23,7 @@ Material: stringTagMap: {} disabledShaderPasses: - NiloToonOutline + m_LockedProperties: m_SavedProperties: serializedVersion: 3 m_TexEnvs: @@ -1817,3 +1820,4 @@ Material: - _egc6: {r: 1, g: 1, b: 1, a: 0} - _egc7: {r: 1, g: 1, b: 1, a: 0} m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 06d4dce6e..74da390a9 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cb8e19b764e7c8e269304ee1605c6ec0478341905338de9672e5193c0fd21ba -size 16347 +oid sha256:0b9a3d4d1cb02d1585df521f78b0794e5aa66a5203d0aa21c02821f19d57e033 +size 16274 diff --git a/Streamingle_URP.slnx b/Streamingle_URP.slnx index ffb3e8f6f..f9053635d 100644 --- a/Streamingle_URP.slnx +++ b/Streamingle_URP.slnx @@ -4,11 +4,11 @@ + - @@ -26,7 +26,6 @@ - @@ -44,18 +43,17 @@ - + -