Scenario Blending for Day/Night with Physically-Based Sky

Hi,

I’ve been trying to use scenario blending in an HDRP scene with physically-based sky and APVs for all indirect lighting. I immediately ran into the challenge of lerping between scenarios causing the indirect lighting to be way too bright as the direct lighting dramatically & non-linearly falls in intensity during sunset.

Luckily, Unity put out a fantastic demo from @maximeg_unity, @DavidLlewelyn and Rémi Chapelain that discusses how to solve this with really useful illustrations:
New lighting features and workflows in Unity 6

However, I’m not sure how to actually implement it. The presenters suggest storing the sun intensity and then checking the current intensity to curve-match the indirect scenario blend %. With the default HDRP setting, the sun’s intensity is always 130k lux but what makes it to the scene/skybox is modulated by atmospheric scattering and planetary occlusion… so what would be a good approach to sampling/storing the “scene light intensity” for lack of a better phrase?

So far I got ok results from manually blending and jotting down the blend % that looks ok but it would be cool to have a less tedious & more scalable and correct process

Thanks!!

Hey,
The goal is to find a reference value that’s easy to store when baking and can be retrieved at runtime for comparisons. It needs to be relatively stable and consistent. There are a few options for this, and we’ve tested a couple :

1) The Ambient Probe

  • This is simple to get and represents the sky’s diffuse lighting, so it makes a lot of sense.
  • The downside? If you’ve got moving clouds, the ambient probe at runtime might not match the conditions during baking, making it less reliable.
var ambientProbe = RenderSettings.ambientProbe;  
float R = ambientProbe[0, 0];  
float G = ambientProbe[0, 1];  
float B = ambientProbe[0, 2];  

var globalIntensity = (R + G + B); // This could be done differently, but the main idea is to get a stable value that roughly represents the sky.
  • Since you we are using C# to manually trigger an ambient probe update, we set it to Static instead Dynamic in the settings

2) The Sun Intensity

  • You could also use the sun’s attenuated intensity based on the sky settings. But if you’ve got multiple lights, like a sun and moon, you’ll need to combine their contributions. If you only rely on the sun, it’ll fail when the sun goes below the horizon and its intensity drops to zero.
  • As you mentioned, you need to take the Sun attenuation from the PBR sky into account. Unity has a function for this :

internal virtual Vector3 EvaluateAtmosphericAttenuation(Vector3 sunDirection, Vector3 cameraPosition);

  • However, it’s internal, so using it isn’t straightforward. Here are some workarounds:
    Fork HDRP and make it public (not ideal).
    Use C# reflection to access it.
    Or try accessing it through asmdef: Unity asmdef documentation.

Example :

float globalValue = 0f;

Vector3 atmosphericAttenuation;

atmosphericAttenuation = PhysicallyBasedSky.EvaluateAtmosphericAttenuation(sun.transform.forward, Vector3.zero, null);

globalValue += atmosphericAttenuation.x * l.intensity * l.color.r / 3f;

globalValue += atmosphericAttenuation.y * l.intensity * l.color.g / 3f;

globalValue += atmosphericAttenuation.z * l.intensity * l.color.b / 3f;

return globalValue;

In the demo, we went with the ambient probe solution since it was simpler than accounting for both the Sun and Moon at night, and we didn’t have to deal with moving clouds. However, it might be worth testing both approaches depending on the case.

1 Like

@maximeg_unity thank you for the detailed reply, that is exactly the info I was looking for.