diff --git a/API-Editor/ShaderInformation.cs b/API-Editor/ShaderInformation.cs index c460be81..bd170baa 100644 --- a/API-Editor/ShaderInformation.cs +++ b/API-Editor/ShaderInformation.cs @@ -233,6 +233,14 @@ internal MaterialInformationCallback() [PublicAPI] public abstract Vector4? GetVector(string propertyName, bool considerAnimation = true); + /// + /// Returns if the local Shader Keyword is enabled or not. + /// + /// The name of local shader keyword + /// true if the local shader keyword is enabled, false if disabled, null if unknown or mixed. + [PublicAPI] + public abstract bool? IsShaderKeywordEnabled(string keywordName); + /// /// Registers UV Usage that are not considered by Avatar Optimizer. /// diff --git a/CHANGELOG-PRERELEASE.md b/CHANGELOG-PRERELEASE.md index aae4cc7a..f3913d31 100644 --- a/CHANGELOG-PRERELEASE.md +++ b/CHANGELOG-PRERELEASE.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog]. ## [Unreleased] ### Added +- Optimize Texture support for Unity Standard, VRChat SDK Standard Lite, VRChat SDK Toon Lit Shaders `#1346` + - If you want more shader support, please comment to [`#1183`](https://github.com/anatawa12/AvatarOptimizer/issues/1183) with shader name and link! ### Changed - Make error for MergeBone with MergePB rotation mode fix `#1345` diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ca6bd53..3cd82bce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ The format is based on [Keep a Changelog]. - We may relax some restriction in the future. - Because we have to check for each condition if we use AnyState but we can check for only one (in best case) with entry/exit, this generally reduces cost for checking an parameter in a state. - Combined with Entry / Exit to 1D BlendTree optimization, which is implemented in previous release, your AnyState layer may be optimized to 1D BlendTree. -- Optimize Texture in Trace nad Optimize `#1181` `#1184` `#1193` `#1215` `#1225` `#1235` `#1268` `#1278` `#1313` `#1328` `#1338` `#1334` +- Optimize Texture in Trace nad Optimize `#1181` `#1184` `#1193` `#1215` `#1225` `#1235` `#1268` `#1278` `#1313` `#1328` `#1338` `#1334` `#1346` - Avatar Optimizer will pack texture and tries to reduce the VRAM usage. - Currently liltoon is only supported. - `Copy Enablement Animation` to Merge Skinned Mesh `#1173` diff --git a/Editor/APIInternal/ShaderInformation.Standard.cs b/Editor/APIInternal/ShaderInformation.Standard.cs new file mode 100644 index 00000000..0b5cb532 --- /dev/null +++ b/Editor/APIInternal/ShaderInformation.Standard.cs @@ -0,0 +1,61 @@ +using Anatawa12.AvatarOptimizer.API; +using UnityEditor; +using UnityEngine; + +namespace Anatawa12.AvatarOptimizer.APIInternal; + +// Unity builtin "Standard" shader +// https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/DefaultResourcesExtra/Standard.shader +[InitializeOnLoad] +class StandardShaderInformation : ShaderInformation +{ + static StandardShaderInformation() + { + Register(); + } + + private static void Register() + { + var information = new StandardShaderInformation(); + if (!GlobalObjectId.TryParse("GlobalObjectId_V1-4-0000000000000000f000000000000000-46-0", out var id)) return; + var shader = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(id) as Shader; + if (shader == null) return; + ShaderInformationRegistry.RegisterShaderInformation(shader, information); + } + + public override ShaderInformationKind SupportedInformationKind => + ShaderInformationKind.VertexIndexUsage | ShaderInformationKind.TextureAndUVUsage; + public override void GetMaterialInformation(MaterialInformationCallback matInfo) + { + var mainTexST = matInfo.GetVector("_MainTex_ST"); + Matrix2x3? mainTexSTMat = mainTexST is { } st ? Matrix2x3.NewScaleOffset(st) : null; + var mainTexSTMatParallex = mainTexSTMat; + if (matInfo.IsShaderKeywordEnabled("_PARALLAXMAP") != false) + mainTexSTMat = null; + + matInfo.RegisterTextureUVUsage("_ParallaxMap", "_ParallaxMap", UsingUVChannels.UV0, mainTexSTMatParallex); + + matInfo.RegisterTextureUVUsage("_MainTex", "_MainTex", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_MetallicGlossMap", "_MetallicGlossMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_BumpMap", "_BumpMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_OcclusionMap", "_OcclusionMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_EmissionMap", "_EmissionMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_DetailMask", "_DetailMask", UsingUVChannels.UV0, mainTexSTMat); + + var detailMapST = matInfo.GetVector("_DetailAlbedoMap_ST"); + Matrix2x3? detailMapSTMat = detailMapST is { } st2 ? Matrix2x3.NewScaleOffset(st2) : null; + + if (matInfo.IsShaderKeywordEnabled("_PARALLAXMAP") != false) + detailMapSTMat = null; + + var detailMapUV = matInfo.GetFloat("_UVSec") switch + { + null => UsingUVChannels.UV0 | UsingUVChannels.UV1, + 0 => UsingUVChannels.UV0, + _ => UsingUVChannels.UV1, + }; + + matInfo.RegisterTextureUVUsage("_DetailAlbedoMap", "_DetailAlbedoMap", detailMapUV, detailMapSTMat); + matInfo.RegisterTextureUVUsage("_DetailNormalMap", "_DetailNormalMap", detailMapUV, detailMapSTMat); + } +} diff --git a/Editor/APIInternal/ShaderInformation.Standard.cs.meta b/Editor/APIInternal/ShaderInformation.Standard.cs.meta new file mode 100644 index 00000000..f1b57527 --- /dev/null +++ b/Editor/APIInternal/ShaderInformation.Standard.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6b05431a902a41448b9300d2ae66adfe +timeCreated: 1731551395 \ No newline at end of file diff --git a/Editor/APIInternal/ShaderInformation.VRCSDK.cs b/Editor/APIInternal/ShaderInformation.VRCSDK.cs new file mode 100644 index 00000000..c00b9599 --- /dev/null +++ b/Editor/APIInternal/ShaderInformation.VRCSDK.cs @@ -0,0 +1,75 @@ +using Anatawa12.AvatarOptimizer.API; +using UnityEditor; +using UnityEngine; + +namespace Anatawa12.AvatarOptimizer.APIInternal; + +// VRChat SDK Mobile Shaders + +[InitializeOnLoad] +class VRCSDKStandardLiteShaderInformation : ShaderInformation +{ + static VRCSDKStandardLiteShaderInformation() + { + Register(); + } + + private static void Register() + { + var information = new VRCSDKStandardLiteShaderInformation(); + ShaderInformationRegistry.RegisterShaderInformationWithGUID("0b7113dea2069fc4e8943843eff19f70", information); + } + + public override ShaderInformationKind SupportedInformationKind => + ShaderInformationKind.VertexIndexUsage | ShaderInformationKind.TextureAndUVUsage; + public override void GetMaterialInformation(MaterialInformationCallback matInfo) + { + var mainTexST = matInfo.GetVector("_MainTex_ST"); + Matrix2x3? mainTexSTMat = mainTexST is { } st ? Matrix2x3.NewScaleOffset(st) : null; + + matInfo.RegisterTextureUVUsage("_MetallicGlossMap", "_MetallicGlossMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_MainTex", "_MainTex", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_BumpMap", "_BumpMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_OcclusionMap", "_OcclusionMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_EmissionMap", "_EmissionMap", UsingUVChannels.UV0, mainTexSTMat); + matInfo.RegisterTextureUVUsage("_DetailMask", "_DetailMask", UsingUVChannels.UV0, mainTexSTMat); + + var detailMapST = matInfo.GetVector("_DetailAlbedoMap_ST"); + Matrix2x3? detailMapSTMat = detailMapST is { } st2 ? Matrix2x3.NewScaleOffset(st2) : null; + matInfo.RegisterTextureUVUsage("_DetailAlbedoMap", "_DetailAlbedoMap", UsingUVChannels.UV0, mainTexSTMat); + + var detailMapUV = matInfo.GetFloat("_UVSec") switch + { + null => UsingUVChannels.UV0 | UsingUVChannels.UV1, + 0 => UsingUVChannels.UV0, + _ => UsingUVChannels.UV1, + }; + + matInfo.RegisterTextureUVUsage("_DetailAlbedoMap", "_DetailAlbedoMap", detailMapUV, detailMapSTMat); + matInfo.RegisterTextureUVUsage("_DetailNormalMap", "_DetailNormalMap", detailMapUV, detailMapSTMat); + } +} + +[InitializeOnLoad] +class VRCSDKToonLitShaderInformation : ShaderInformation +{ + static VRCSDKToonLitShaderInformation() + { + Register(); + } + + private static void Register() + { + var information = new VRCSDKToonLitShaderInformation(); + ShaderInformationRegistry.RegisterShaderInformationWithGUID("affc81f3d164d734d8f13053effb1c5c", information); + } + + public override ShaderInformationKind SupportedInformationKind => + ShaderInformationKind.VertexIndexUsage | ShaderInformationKind.TextureAndUVUsage; + public override void GetMaterialInformation(MaterialInformationCallback matInfo) + { + var mainTexST = matInfo.GetVector("_MainTex_ST"); + Matrix2x3? mainTexSTMat = mainTexST is { } st ? Matrix2x3.NewScaleOffset(st) : null; + matInfo.RegisterTextureUVUsage("_MainTex", "_MainTex", UsingUVChannels.UV0, mainTexSTMat); + } +} diff --git a/Editor/APIInternal/ShaderInformation.VRCSDK.cs.meta b/Editor/APIInternal/ShaderInformation.VRCSDK.cs.meta new file mode 100644 index 00000000..36491f13 --- /dev/null +++ b/Editor/APIInternal/ShaderInformation.VRCSDK.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 42662f4915a74d46bb9c93274e73d66a +timeCreated: 1731557036 \ No newline at end of file diff --git a/Editor/Processors/ShaderMaterialInformation.cs b/Editor/Processors/ShaderMaterialInformation.cs index 09c3d0a0..a0d5d6a9 100644 --- a/Editor/Processors/ShaderMaterialInformation.cs +++ b/Editor/Processors/ShaderMaterialInformation.cs @@ -5,6 +5,7 @@ using Anatawa12.AvatarOptimizer.ndmf; using nadena.dev.ndmf; using UnityEngine; +using UnityEngine.Rendering; namespace Anatawa12.AvatarOptimizer.Processors; @@ -144,6 +145,8 @@ public MaterialInformationCallbackImpl(Material material, ShaderInformationKind public override Vector4? GetVector(string propertyName, bool considerAnimation = true) => GetValue(propertyName, _material.SafeGetVector, considerAnimation, VectorSubProperties); + public override bool? IsShaderKeywordEnabled(string keywordName) => _material.IsKeywordEnabled(keywordName); + public override void RegisterOtherUVUsage(UsingUVChannels uvChannel) { if ((_supportedKind & ShaderInformationKind.TextureAndUVUsage) == 0)