From 3a4fd40144b67322446d702c63fe2ead3d7aab33 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 18 Oct 2024 14:07:29 +0900 Subject: [PATCH 1/5] feat: add API to register vertex index usage --- API-Editor/ShaderInformation.cs | 20 +++++++++++++++++++ .../Processors/ShaderMaterialInformation.cs | 12 ++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/API-Editor/ShaderInformation.cs b/API-Editor/ShaderInformation.cs index 70ee8111..341aeba2 100644 --- a/API-Editor/ShaderInformation.cs +++ b/API-Editor/ShaderInformation.cs @@ -178,6 +178,13 @@ public enum ShaderInformationKind /// Providing this information will allow Avatar Optimizer to optimize the texture usage like UV Packing. /// TextureAndUVUsage = 1, + /// + /// The vertex index usage information. + /// + /// If you don't provide this information, Avatar Optimizer will assume that vertex indices are not used + /// in the shader, so Avatar Optimizer may shuffle the vertex indices. + /// + VertexIndexUsage = 2, } /// @@ -258,6 +265,19 @@ public abstract void RegisterTextureUVUsage( SamplerStateInformation samplerState, UsingUVChannels uvChannels, Matrix2x3? uvMatrix); + + /// + /// Registers the vertex index usage. + /// + /// Calling this will prevent Avatar Optimizer from automatically caning the vertex indices. + /// If user ask, Avatar Optimizer may change the vertex indices. + /// + /// If vertex indices are used only for noise or other purposes that don't affect the mesh much, + /// tou don't need to call this function. + /// + /// This API is to provide . + [PublicAPI] + public abstract void RegisterVertexIndexUsage(); } /// diff --git a/Editor/Processors/ShaderMaterialInformation.cs b/Editor/Processors/ShaderMaterialInformation.cs index 287f2f1f..c7416b19 100644 --- a/Editor/Processors/ShaderMaterialInformation.cs +++ b/Editor/Processors/ShaderMaterialInformation.cs @@ -67,6 +67,7 @@ internal class MaterialInformation public readonly bool HasShaderInformation; public readonly List? TextureUsageInformationList; + public readonly bool UseVertexIndex; public MaterialInformation(Material material, List renderers, BuildContext context) { @@ -76,6 +77,7 @@ public MaterialInformation(Material material, List renderers, BuildCon // collect texture usage information HasShaderInformation = false; + UseVertexIndex = false; TextureUsageInformationList = null; if (ShaderInformationRegistry.GetShaderInformation(material.shader) is { } information) { @@ -88,10 +90,10 @@ public MaterialInformation(Material material, List renderers, BuildCon renderers.Select(renderer => context.GetAnimationComponent(renderer)).ToList()); information.GetMaterialInformation(provider); TextureUsageInformationList = provider.TextureUsageInformations; + UseVertexIndex = provider.UseVertexIndex; } } - class MaterialInformationCallbackImpl : MaterialInformationCallback { private readonly Material _material; @@ -99,6 +101,7 @@ class MaterialInformationCallbackImpl : MaterialInformationCallback private List? _textureUsageInformations; private readonly ShaderInformationKind _supportedKind; + public bool UseVertexIndex { get; private set; } public List? TextureUsageInformations => _textureUsageInformations; public MaterialInformationCallbackImpl(Material material, ShaderInformationKind supportedKind, @@ -227,6 +230,13 @@ public override void RegisterTextureUVUsage( _textureUsageInformations?.Add(new TextureUsageInformation(textureMaterialPropertyName, uvChannel, wrapModeU, wrapModeV)); } + + public override void RegisterVertexIndexUsage() + { + if ((_supportedKind & ShaderInformationKind.VertexIndexUsage) == 0) + throw new InvalidOperationException("RegisterVertexIndexUsage is not registered as supported information"); + UseVertexIndex = true; + } } } From a2f56fb5ee9bfd666d3898c21750ea6da0a1d66e Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 18 Oct 2024 14:08:21 +0900 Subject: [PATCH 2/5] feat(liltoon-info): register vertex id usage --- .../APIInternal/ShaderInformation.Liltoon.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Editor/APIInternal/ShaderInformation.Liltoon.cs b/Editor/APIInternal/ShaderInformation.Liltoon.cs index 7f05d295..fc4a83f0 100644 --- a/Editor/APIInternal/ShaderInformation.Liltoon.cs +++ b/Editor/APIInternal/ShaderInformation.Liltoon.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Reflection; using Anatawa12.AvatarOptimizer.API; using UnityEditor; @@ -12,7 +13,7 @@ internal class LiltoonShaderInformation : ShaderInformation internal override bool IsInternalInformation => true; public override ShaderInformationKind SupportedInformationKind => - ShaderInformationKind.TextureAndUVUsage; + ShaderInformationKind.TextureAndUVUsage | ShaderInformationKind.VertexIndexUsage; static LiltoonShaderInformation() { @@ -558,6 +559,22 @@ public override void GetMaterialInformation(MaterialInformationCallback matInfo) // _BaseMap and _BaseColorMap are unused + // Vertex ID + var idMaskProperties = new[] + { + "_IDMask1", "_IDMask2", "_IDMask3", "_IDMask4", "_IDMask5", "_IDMask6", "_IDMask7", "_IDMask8", + "_IDMaskPrior1", "_IDMaskPrior2", "_IDMaskPrior3", "_IDMaskPrior4", "_IDMaskPrior5", "_IDMaskPrior6", "_IDMaskPrior7", "_IDMaskPrior8", + "_IDMaskIsBitmap", "_IDMaskCompile" + }; + if (idMaskProperties.Any(prop => matInfo.GetInteger(prop) != 0)) + { + // with _IDMaskFrom = 0..7, uv is used for ID Mask, but it will only use integer part + // (cast to int with normal rounding in hlsl) so it's not necessary to register UV usage. + matInfo.RegisterVertexIndexUsage(); + } + + // fur shader will use vertex ID, but it's for noise so it's not necessary to register UV usage. + return; void LIL_SAMPLE_1D(string textureName, SamplerStateInformation samplerName, UsingUVChannels uvChannel) From 2efb3f9af5eb820ea14a4ed87fe42a9464fda275 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 18 Oct 2024 14:22:34 +0900 Subject: [PATCH 3/5] refactor: add GetAllPossibleMaterialFor to get materials including animation ones --- Editor/ContextExtensions.cs | 16 ++++++++++++++++ Editor/Processors/ShaderMaterialInformation.cs | 14 ++------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Editor/ContextExtensions.cs b/Editor/ContextExtensions.cs index ad171986..9ef7a1da 100644 --- a/Editor/ContextExtensions.cs +++ b/Editor/ContextExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Anatawa12.AvatarOptimizer.AnimatorParsersV2; using nadena.dev.ndmf; using UnityEngine; @@ -61,5 +63,19 @@ public static AnimationComponentInfo GetAnimationComponent(this Bu return null; } + + public static IEnumerable GetAllPossibleMaterialFor(this BuildContext context, Renderer renderer) + { + if (context == null) throw new ArgumentNullException(nameof(context)); + if (renderer == null) throw new ArgumentNullException(nameof(renderer)); + var materialsRaw = + renderer is SkinnedMeshRenderer skinned + ? context.GetMeshInfoFor(skinned).SubMeshes.SelectMany(x => x.SharedMaterials) + : renderer.sharedMaterials; + var materials = materialsRaw.OfType(); + var animated = context.GetAnimationComponent(renderer).GetAllObjectProperties() + .SelectMany(x => x.node.Value.PossibleValues).OfType(); + return materials.Concat(animated).Distinct(); + } } } diff --git a/Editor/Processors/ShaderMaterialInformation.cs b/Editor/Processors/ShaderMaterialInformation.cs index c7416b19..2e019eca 100644 --- a/Editor/Processors/ShaderMaterialInformation.cs +++ b/Editor/Processors/ShaderMaterialInformation.cs @@ -14,18 +14,8 @@ protected override void Execute(BuildContext context) var renderersByMaterial = new Dictionary>(); foreach (var renderer in context.GetComponents()) - { - IEnumerable materials; - - if (renderer is SkinnedMeshRenderer skinnedMeshRenderer) - materials = context.GetMeshInfoFor(skinnedMeshRenderer).SubMeshes.SelectMany(x => x.SharedMaterials); - else - materials = renderer.sharedMaterials; - - materials = materials.Concat(context.GetAnimationComponent(renderer).GetAllObjectProperties() - .SelectMany(x => x.node.Value.PossibleValues).OfType()); - - foreach (var material in materials) + { + foreach (var material in context.GetAllPossibleMaterialFor(renderer)) { if (material == null) continue; From 2aa1d5df98be6d45282c3de7108b90f40f81313d Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 18 Oct 2024 17:38:12 +0900 Subject: [PATCH 4/5] feat: do not merge meshes depends on vertex index --- .../Processors/TraceAndOptimize/AutoMergeSkinnedMesh.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Editor/Processors/TraceAndOptimize/AutoMergeSkinnedMesh.cs b/Editor/Processors/TraceAndOptimize/AutoMergeSkinnedMesh.cs index b4a42bc3..7e9ddb06 100644 --- a/Editor/Processors/TraceAndOptimize/AutoMergeSkinnedMesh.cs +++ b/Editor/Processors/TraceAndOptimize/AutoMergeSkinnedMesh.cs @@ -93,6 +93,14 @@ public static List FilterMergeMeshes(BuildContext context, TraceAndOp // light probe proxy volume override must be defined if light probe usage is UseProxyVolume && (meshRenderer.lightProbeUsage != LightProbeUsage.UseProxyVolume || meshRenderer.lightProbeProxyVolumeOverride != null) + // shader must not use vertex index. + // Even if the original mesh is already shuffled, we won't merge automatically because + // user may configure material to match with affected vertex index. + // Note for users reading this comment: Vertex Index after remove mesh or merge mesh is + // not guaranteed so upgrading Avatar Optimizer may break your avatar if you rely on vertex index + // after Remove Mesh By **** or Merge Skinned Mesh. + && !context.GetAllPossibleMaterialFor(meshRenderer) + .Any(x => context.GetMaterialInformation(x)?.UseVertexIndex ?? false) // other notes: // - activeness animation can be ignored here because we'll combine based on activeness animation From 520b28cfbe571e32a29293460850c3685574e84a Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 18 Oct 2024 17:52:12 +0900 Subject: [PATCH 5/5] docs(changelog): Support for Shaders that depends on vertex index --- CHANGELOG-PRERELEASE.md | 3 +++ CHANGELOG.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG-PRERELEASE.md b/CHANGELOG-PRERELEASE.md index 5500004f..a96cd86b 100644 --- a/CHANGELOG-PRERELEASE.md +++ b/CHANGELOG-PRERELEASE.md @@ -21,6 +21,9 @@ The format is based on [Keep a Changelog]. - This feature is added to `Remove Unused Objects` in `Trace and Optimize`. - When you changed shader for an material, properties for previously used shaders might be remain - This may increase your avatar size by unexpectedly including unused textures +- Support for Shaders that depends on vertex index `#1275` + - Avatar Optimizer will not automatically merge meshes that are using vertex index + - since merging them may change vertex order, which changes vertex index ### Changed - Transform gizmo are now hidden while you're editing box of Remove Mesh in Box `#1259` diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e579bb..5202da6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,9 @@ The format is based on [Keep a Changelog]. - Many NDMF tools uses `zh-hans` so previously you may see both 中文 (中国) and 中文 (简体). - I think zh-hans is more accurate expression so I changed so. - Improve RemoveMeshByMask compability with Tex Trans Tool `#1269` +- Support for Shaders that depends on vertex index `#1275` + - Avatar Optimizer will not automatically merge meshes that are using vertex index + - since merging them may change vertex order, which changes vertex index ### Deprecated