d4rkc0d3r / d4rkAvatarOptimizer

d4rkpl4y3r's VRChat Avatar 3.0 optimizer
MIT License
402 stars 17 forks source link

Material swaps prevent material slots merging even if target materials end up being the same per mesh #9

Open Asovrix opened 2 years ago

Asovrix commented 2 years ago

I used to use inventory system from SCSS or UDIM Discard feature from Poiyomi to toggle parts of meshes on or off. For this model I decided to use ACLS shader, which doesn't have any feature like this, so I needed to actually split my meshes to accommodate for this feature, since this optimizer is supposed to add a similar logic to any compatible shader. Additionally I have a single material swap for all my meshes that changes its style. I suppose because of this material swap, materials are not getting merged. After I remove material swap logic from my animator, they do get merged as I would expect. To reiterate, my material swap is like this, same named materials are the same:

2022-08-31_20-45-05 Unity_2022-08-31_20-40-57

Version of d4rkAvatarOptimizer used: https://github.com/d4rkc0d3r/d4rkAvatarOptimizer/tree/b70e6f1c76ebcfc16f3ef55c35758ea530ad582a

d4rkc0d3r commented 2 years ago

Yeah just thinking about how to implement this makes my head hurt. I think this would only work in very specific situations and is just not worth the effort and added complexity to implement.
I should mention that material slots that have material swap animations on them can't get merged with other materials in the readme. It seems to be missing in there.

kitlith commented 1 year ago

would it be reasonable to do something like "two material slots can be merged if and only if they are animated in the same animation, together, for all animations they are either both animated or both not animated, and the materials in those slots can be merged in all animations?" is there some other set of reasonable restrictions that would do it? like, some way to encode stuff so that the optimizer can see exactly which "material sets" are being used to merge together.

I have the same usecase of multiple styles on the same avatar. i.e. here's my toon material set, here's my furality material set, here's my shadowy material set.

I wouldn't mind doing extra work to get it into a form that works for the optimizer, even if that's manually listing material sets in a component and manually setting up animations to point towards material references generated by the component.

d4rkc0d3r commented 1 year ago

The problem isn't so much that I have a good set of restrictions and more so that I can't think of a good/reasonable way to implement this. Every time I think about this it just becomes a super complex thing that I can't really wrap my head around so unless that changes at some point this will stay as is.

kitlith commented 1 year ago

A sketch for my manual idea:

User Interface: A list of materials sets. Each material set's UI shows a list of every material slot on the avatar, and allows the user to place materials in. (This could be more compex, I.e. non-overlapping groups of materials, that can each have their own list of material sets.) There is an implicit and non-modifyable "default set" that corresponds to the material that the avatar is present in the slot at build time. The user can then tell the tool exactly what materials they want in each slot for each set. Material slots could be disabled in this feature if they are animated by traditional means.

At build time, you then need to compute which slots are merged together. Conceptually, some kind of set intersection on "can these two materials be merged". where the answer is only yes if it is yes for all material sets. Then you do whatever you do to determine which source slots get merged into which target materials (I haven't looked at what you do yet, but finding the connected components of a graph would work here if " material mergability" is transitive), and perform material merging for each material set.

The generated animation controller could then include an animator parameter (whose name is controlled by the user) that serves as an index into the material sets, and can be driven by the user.

It occurred to me as I was writing this that I'm approaching this as if it would be a VRCFury component/feature, which might make it not a very good fit here.

I'm also making an implicit assumption that you can avoid texture duplication in this process, which... might be a bad assumption, I don't know. Imagine two materials across, say, 3 material sets. They are mergable within each set. If one material has a texture that changes for every set, and the other material keeps the same texture in every set, is there a good way to avoid duplicating the texture that stays the same?

buzer2020 commented 1 week ago

Same issue here. I have a hair that is split into 8 different meshes (all use the same 1 material), so I slapped the d4rk optimizer on the avatar to quickly merge them into one. It worked great, but then I wanted to add some material swaps with VRCFury. I've added a bunch of swaps that change materials on all 8 meshes to a different one, but the optimizer has failed to merge them and it resulted in increasing material slots count by 7. avatar and hair pic material swap settings

(I see this is an old issue, so I have a question - can anybody recommend a tool that can quickly merge meshes in Unity as a workaround? even if it's "destructive")