Devblog

Devblog. Part 3 — Making GI responsive to scene changes

Not so long ago we released the HD Renderer with the intent to provide modern realistic graphics capabilities. One of the main factors adding to realism is global illumination, which in EdenSpark was taken from the Dagor Engine.

Upon its integration we faced a problem: when adding new static objects to the scene, they get almost no GI on them unless you do full GI recomputation.

So that's how the Sponza scene would look after spawning:

And after GI invalidation and full recomputation:

We could simply do invalidation, but it wasn't smooth:

Although it could be fixed, making full GI invalidation on any change would be impractical.

The reason for this is that GI receives new data only from the screen (like geometry info, albedo, lighting).

For context, that's how the scene is seen by GI

In the image below, the scene surface is represented by SDF with the lit scene applied to it.

The balls are the 1st cascade of the radiance grid.

It's a good approach when your scene is prebuilt and you need to catch just some relatively small destructions during the game.

But in EdenSpark the scene can change in runtime arbitrarily and we needed to account for that.

Preferably in a way that could be sufficient both for scene editing and gameplay (dynamic lighting, moving structures).

Basic improvements

At first we just added the ability to revoxelize changed parts, so at least GI's scene would always be in sync.

We also removed the lit scene that was caching detailed screen-space GI in world space because it blocked global light propagation.

Because of that removal, we also got stronger light leaking which we addressed by adding some biasing hacks by offsetting irradiance sampling away from walls (light leaking is still a major issue though and we are working on that).

Now you could see GI updating:

Yet it took about 20 seconds to fully converge. This isn't suitable for any dynamically changing scene.

The reason for such a wait is the very low weight with which radiance probes receive new samples.

Once a probe is initially traced with just one sample per each of 64 sections (8x8 texels) the new samples are added in a way that a section would gradually converge to the mean between all samples, meaning that i-th sample would contribute with 1/i weight clamped by minimum of 1/32.

Also, after initial sampling, a probe gets updated once per 16 frames on average in our setup - probes are selected randomly.

Assuming the surrounding lighting doesn't change, this is a proper Monte-Carlo integration which switches to a moving average once we hit a limit. But our lighting *is* changing and, besides, probes contribute to each other.

As a result, not only are the surrounding probes slow to catch light disappearance itself, but they also constantly propagate old illumination into each other, making the update extremely slow.

Accelerating radiance update

In order to fix it we added a new state for probes within which N new samples contribute much more with the 1st contributing with a preset maximum and the N-th with a preset minimum weight.

Within that state, the starting sample index is determined by proximity to the area where a static mesh or a light has changed, so that probes farther away remain undisturbed because they have much less contribution from this area.

To address the low update rate of probes (which is done to amortize the expensive radiance tracing across frames) we gave probes in this state priority over other probes, meaning that with the same amount of selected probes the "hastened" ones can be updated every frame.

 

Finally we get this:

Now GI reacts to lights/geometry movement instantly with a couple of seconds delay for full convergence (10x speedup on the same scene).

There's still visible noise when lighting changes. We tried to find a balance between the speed of refresh and the noise.

Improvements here would imply making more traces per frame with a performance hit, which we can probably provide as a setting once we finish with changes to GI.