From what I see, most avatars use Mobile Toon Standard, lilToon or Poiyomi Toon shaders. I’ve seen worlds mostly use Mochie shaders. Both may sometimes use Standard or Standard Lite too.
I’m not a shader developer, there’ll be always someone who can give a better answer. There may also be several inaccuracies in this post, while I tried to verify my statements before posting.
Is it even possible to compare? Yesn’t. You’d have to be extremely picky about each shader version to compare against, because of different feature sets that may not have options to be disabled, e.g. VRC Light Volumes 3 feature support. And even then, there may be no general solution for what you want to do or how a shader may perform in a different situation, and how far does a shader allow you to optimize it.
(World/Photo: Building Worlds for VRChat by Triforceguard)
I’ll have to generalize concepts a bit, and I may not be able to give concrete performance data.
For example, lilToon is a shader library. The shaders used for a 2 materials lilToon 2.3.4 avatar (Rusk by Komado, with optimized/atlassed UVs) with both opaque and transparent materials are:
ltspass_opaque.shader (127.1 kb)
ltspass_transparent.shader (114.6 kb)
lts_o.shader (45.7 kb)
lts_trans.shader (43.3 kb)
This totals to 337.2 kb of lilToon 2.3.4 shader code for the whole avatar, but the shaders can be reused. (Aside: Another one of my lilToon avatars with 7 materials consists of 686.2 kb of lilToon 2.3.4 shader code, increased file sizes in all shader files.)
Poiyomi Toon is the opposite end, where every material (after hashed deduplication) is its own dedicated shader, stripped of unused code at build time. The shaders used for a 3 materials Poiyomi Toon 9.3.64 avatar with both opaque and transparent materials are:
OptimizedShaders/Rusk_Atlas (Original Rusk) - PoiToon/Poiyomi Toon.shader (296.4 kb)
OptimizedShaders/Rusk_Atlas_Transparent (Original Rusk) - PoiToon/Poiyomi Toon.shader (280.3 kb) - ignore this if comparing closer to 2 materials lilToon above.
OptimizedShaders/Rusk_Alpha_PoiToon/Poiyomi Toon.shader (99.2 kb)
(The Poiyomi Toon avatar in my scenario has an additional UV1 for an alpha map which lilToon only supports on UV0 and isn’t used in the lilToon variant, so this is not a feature-for-feature comparison.)
That’s 675.9 kb of shader code for Poiyomi Toon, individual shaders per material. The memory requirements grow fast for avatars with many materials with Poiyomi Toon.
But perhaps ironically, because Poiyomi Toon supports UV1 alpha map and lilToon doesn’t, I am gaining ~4-5 MB texture memory savings by using a 1024x1024 alpha map on UV1 instead of baking a 2048x2048 alpha channel into an atlas PNG on UV0 with lilToon. That ~4-5 MB texture memory saved makes more difference than 337.2 kb vs 675.9 kb shader code in VRAM, and a more noticeable difference in the Avatar Performance Ranking System. Call it gaming the Avatar Performance Ranking System for lower numbers visible to the end-user, if you’d like.
For the following profiler graph, I’ve removed the Rusk_Atlas_Transparent (Original Rusk) - PoiToon material from the avatar for roughly the same feature parity: 2 materials, transparent front hair foregone on both lilToon and Poiyomi Toon variants.
The GPU frametimes are roughly ~0.050 ms (!) better per frame with Poiyomi Toon in my scenario compared to lilToon on the same hardware configuration, despite larger memory requirements.
This result baffled me a bit.
I tried making sure this result wasn’t a fluke and re-ran the profiler on both scenes, because earlier I was seeing only a ~0.009 ms lower frame time with Poiyomi Toon with more draw calls in the scene - I got the same result. The comparisons aren’t 1:1 (e.g. baked vertex color data for rim light masking and packed texture masks on Poiyomi Toon; lilToon uses mask texture files), but I guess it shows how much further Poiyomi Toon can go with optimization with additional shader features.
(Editor’s note: The GPU frametimes for Mobile Toon Standard (Outline) here are incorrect, see the post below for corrected results.)
Here’s a quick profiler graph of Mobile Toon Standard (Outline) from VRCHat SDK - Avatars 3.10.4, with 1 material for the whole avatar. Because there’s no transparency support in MTS, I also removed the Rusk_Alpha material slot. I used the lilToon (PC) FBX from above and replaced all lilToon materials with Mobile Toon Standard (Outline). The material is only 2.3 kb, the ToonStandard.shader is 77.7 kb in file size.
There’s no feature parity on Mobile Toon Standard (Outline), there’s actually less features, but it gets close to what I want the avatar to look like. Yet, it seems to perform the worst of these examples in the profiler. I don’t know why? I ran the profiler three times and got the same results.
I know you asked for a Poiyomi Toon vs Mochie Shaders comparison. I didn’t have an avatar with Mochie shaders available, and I’m not familiar with Mochie shaders in general.
So I made one, for this post. A new Unity Project, a new scene.
A simple one using Mochie’s Free Shader Package v1.75 for this post, plugging in only an albedo texture into a Mochie Standard shader and leaving the rest of material settings at default. (The lilToon and Poiyomi Toon avatars used above aren’t using normal maps, metallic, roughness, occlusion, height map or emissions either.) 1 opaque material for the entire avatar.
And with 2 materials, using a 2nd Mochie Standard material with Base Color Alpha for alpha source for the Rusk_Alpha material:
Unfortunately, Mochie’s shaders do not support my use case of having an alpha mask/map on UV1, so I’m unable to use my existing projects for 3 materials comparison.
I should also be mindful that Mochie Standard is very far off from the toon avatar style seen in lilToon and Poiyomi Toon, and thus the result may not be comparable.
As for GPU execution performance, 337.2 kb vs 675.9 kb file size won’t make a difference. It’s about memory access patterns and the number of instructions. I think the shader file size could make a difference for cache performance in the real-world? But I believe the GPU cache is going to “get rekt” anyway, because avatars and worlds can have so many different variations and versions of user-generated shaders.
Finally a small correction for you OP: Shaders are compiled on the CPU.
(Editor’s note: The results for Mobile Toon Standard (Outline) here are incorrect, see the post below for corrected results.)
So in my testing with a highly optimized Rusk avatar, for GPU frametimes:
- Poiyomi Toon 9.3.64 (0.127 ms)
- Mochie Standard v1.75 (0.144 ms)
- lilToon 2.3.4 (0.181 ms)
- Mobile Toon Standard (Outline) SDK 3.10.4 (0.197 ms).
Results are not directly comparable, but maybe it gives you some idea.