At one point in our game, we want to turn down the lights all the way on the background and focus on the characters. Obviously this is easy to do with light objects in the scene (we can use the Culling Mask to have different lights for background vs characters). But it’s nowhere near enough, because the Environment Lighting (i.e. ambient light) is still lighting up everything.
Is there any way to specify different ambient (environment) light for different layers?
I even tried adding a script to some objects that changes RenderSettings.ambientIntensity in OnPreRender (and changes it back in OnPostRender), but this has no apparent effect.
The best we can come up with at this point is to use custom shaders on all the background objects, that apply a global multiplier to the final color. But that seems heavy-handed and quite limiting.
Any other ideas?
P.S. This is on mobile, so we need a solution that is as efficient as possible.
Hi!
Afaik, no in-built way to do this.
I would recommend extending Unity’s shader. Add an “Ambient Light Layer” (int) property. And add an “Ambient Light Intensity” (float array) property. Use it to attenuate environmental lighting. Then, set the ambient light intensity float array from a scene-level Monobehaviour. Iterate the array like a light loop.
Alternatively, you can write a post-process effect. In the effect, you could stencil the characters. Then, fade the rest of the geometry to black. Might have challenges with transparent materials.
You could use a custom shader on your characters instead, a shader that either ignores ambientIntensity value or can be fed a custom environment reflection cubemap. Then you could turn down ambientIntensity without it affecting your characters.
If you put a reflection probe in your scene, that is low importance, only samples the sky and covers the whole level, you can basically rebuild a custom ambient probe. I’d suggest doing that at least during development, you can more easily see the cubemap texture it produces, bake whenever, etc. The Sky Managers internal probe (unity_SpecCube0) is kind of hidden. You could also use a similar kind of probe with zero size (not covering any objects) to sample the original environment reflections even though ambientIntensity is turned down.
The most efficient way I think would be the character shader that ignores the ambientIntensity value, in which case you don’t actually need any of the aforementioned probes, but I they can be useful visualization while building such a shader.