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)