Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How to override ambient light with a VolumeComponent?

Discussion in 'Universal Render Pipeline' started by ivarhill, Aug 10, 2023.

  1. ivarhill

    ivarhill

    Joined:
    Dec 20, 2012
    Posts:
    7
    Hi,

    I'm looking for some advice on how to manage lighting override volumes using URP. I posted this on Unity Answers a few days back but realized these forums may be a better place.

    We are using a fairly standard URP setup for game rendering and lighting:
    • Lighting is realtime only, using Forward+ rendering.
    • Ambient light is defined in a scene's Lighting>Environment settings, as a color.
    • There is a standard post-processing stack that handles both built-in and custom post-processing.
    What I'm now trying to do is set up a system for override volumes, so that parts of a scene can have different post-processing and lighting conditions.

    For the most part, this has worked pretty well. I can set up a volume under GameObject > Volume > Box Volume and position it as needed. Selecting the volume object, I can then add any override as needed, as is standard for URP. This works great!

    The issue I'm having is that I want to also override the level's ambient color using the same volume setup - in other words, the color set per-scene under Lighting > Environment > Environment Lighting > Ambient Color. My intended behavior is for this to work as a VolumeComponent so that it benefits from all the advantages of using the URP volume system.

    Somewhat surprisingly to me, there does not seem to be any kind of built in way to do this. So I attempted it myself by making my own VolumeComponent script, defining an override color as such:

    Code (CSharp):
    1. [VolumeComponentMenu("Lighting/" + nameof(EnvironmentLightingOverride))]
    2. public class EnvironmentLightingOverride : VolumeComponent, IPostProcessComponent
    3. {
    4.     //Color to override
    5.     public ColorParameter ambientColor = new ColorParameter(Color.black, false, false, false);
    6. }
    And then adding it as an override to my volume. This shows up as expected and lets me pick a color as expected.

    However, I'm now at a loss on how to actually apply this color as the new ambient color. I'm not sure where, how and when I'd actually call this - normally I'd just change the ambient color as such:
    Code (CSharp):
    1. RenderSettings.ambientSkyColor = ambientColor.value;
    But there's no obvious place to call this and I get the impression that this is not how a VolumeComponent is supposed to be integrated. Is there something I'm missing here? How would I actually set this up so that the ambient color blends, both at runtime and edit mode, between the chosen override and the default color based on whether you are within the volume or not? In other words, for the behavior to work exactly like the already included overrides.

    Would be grateful for any advice or direction here! Thanks!
     
  2. Kabinet13

    Kabinet13

    Joined:
    Jun 13, 2019
    Posts:
    57
    This is actually pretty complicated to achieve, you would need to implement a lot of the logic for reflection probes to pass a value to a shader spatially. You'd also need a custom shader to read said ambient value. I do wish this existed by default, but it is definitely possible, Outer Wilds implemented them (called "Occlusion Volumes") and show it off in this video.
     
  3. ivarhill

    ivarhill

    Joined:
    Dec 20, 2012
    Posts:
    7
    Thanks for your response, I will certainly look into this further!

    Given that changing the overall brightness of an area of a scene locally is something that's incredibly common throughout many games, is it possible this is an XY problem? Is there another approach entirely that is more commonly taken to achieve this, such as not using ambient light whatsoever and lighting a scene ambiently in a different manner?
     
  4. Kabinet13

    Kabinet13

    Joined:
    Jun 13, 2019
    Posts:
    57
    A staggering amount of games end up using baked GI, even if just to get rid of ambient lighting, I would bet that accounts for most areas of darkened light in games. Honestly, this is one of the things that bothers me most about fully realtime lighting. What outer wilds did was effectively write their own light type, which affected ambient as opposed to diffuse or specular, but doing so is a pretty involved process, and definitely comes with somewhat weaker shader performance, which is why I assume nobody at Unity has bothered writing one. (It's basically the cost of a second reflection probe system, since for it to look good, you would need spatial blending)