You’re multiplying the L1 contribution vectors by 2, so your lumaConv should be divided by 2 for energy conservation.
Good catch! I think I had it in my head that L1 was in the range [-.5, .5] in unity_SHA but that doesn’t… really make much sense.
You can get the dominant direction value with
normalize((unity_SHAr.xyz + unity_SHAg.xyz + unity_SHAb.xyz) + FLT_EPS);
Not sure why that didn’t occur to me actually. Let me give that a shot!
You mention that the case where you have a single, realtime directional light is quite rare, have you actually checked?
Specifically, on Android content yes - I checked a couple dozen maps and didn’t see any using them. I can dig again though!
If we’re expecting this to conflict with realtime lights, I could potentially make it dynamic based on whether there’s any lights - you’d only get the specularity in worlds without it.
if it overlaps with reflection probe highlights you get an ugly double highlight effect
This is the case for existing specular highlights - they come from realtime lights, whereas reflection probes can have the same light in a slightly different place since it’s baked. This frequently results in a subtle double-lighting if your reflection probe highlights are based on emissive objects. Another method we were considering to mitigate this (on the creator side) was to integrate something akin GitHub - zulubo/SpecularProbes: Bake specular highlights into Unity Reflection Probes, allowing baked lights to cast sharp specular highlights for free into the SDK - it’s basically the baked version of the above.