SEGI (Fully Dynamic Global Illumination)

Well, I’ve been working hard on cascades and directional voxel data lately. Here’s how that’s going. I’ve included some technical details for the nerds who are curious about them :slight_smile:

So, the core functionality of cascades is working now. So, instead of having one volume at 256x256x256 resolution, there are 8 cascade levels, and each level is 128x128x128 resolution. Overall it uses about the same amount of memory as before (around 500 mb at “high” resolution, even with the direcitonal voxel data that I’ll explain below). Only one cascade is revoxelized per-frame, so the overall work of voxelization is reduced when compared to not having cascades. Each cascade’s volume covers an area twice the size of the previous cascade.

Voxelization with cascades works like this. First, the lowest level cascade (the smallest one) is completely voxelized. Then, on the next frame, the next highest cascade is voxelized, but voxelization is skipped in the area inside this cascade that the previous one overlaps. Instead, the data from the previous cascade is filtered and injected in this overlap area. This means that there’s still somewhat of a “mipmapping” going on in areas where cascades overlap. This saves a bit of work, too. The process is repeated for each cascade level and starts over when the last cascade has been updated. Voxelization is also super-sampled x4 (x16 effective SSAA) to ensure smooth results in areas that don’t overlap.

Cone tracing is still rather naive to cascades at this point. I’m pretty much tracing in the exact same way as before (since the distribution of data is much like what you get with mipmaps, where each higher level cascade is half the resolution spatially). Though, for whatever reason, I got very incorrect results without tweaking the cone width calculations, which still puzzles me. I’m still struggling to get the cone tracing to look like it did before cascades (which, again, is very strange since the data layout is so similar spatially).

So, here’s the result of some tests with the Courtyard scene. Direct sunlight injection is still a little buggy, so the scene is only lit by skylight for demonstrative purposes. Here’s how the scene looks up-close.

8 levels of cascades yields some pretty insane render distance, as you can see here. And for clarification, I did not adjust the Voxel Space Size property between these two images.

You can see that the cone tracing itself doesn’t look as good (which I’m still trying to figure out), but cascades are really doing their job at improving the render distance of GI so far.

So, I had a few options regarding directional voxel data. With other voxel-based GI solutions out there, representing directional light data is done by storing separate light values for each of the 6 “faces” of each voxel. I saw two problems with this.

First, this requires storing 6x the amount of data when compared to non-directional light data. That’s a pretty big price to pay, considering that memory usage is usually a constraint with voxel-based GI. I’ve seen solutions where, with classic mipmaps, only the lower levels have directional data, saving memory in that regard, but this doesn’t translate to cascades.

The second problem is that whenever you have a surface that is perfectly aligned to an axis in the volume, directionality is represented perfectly, but if it’s even a little bit off, directionality becomes pretty inaccurate. I’ll try to whip up a diagram to explain why.

When light is represented in discrete directions like this, perfectly aligned walls will work well, but even slightly misaligned walls would leak quite a bit.

So the solution that I came up with was to use Spherical Harmonics instead. 2nd-order Spherical Harmonics requires 4 coefficients per color channel. That’s less data than the above method, and it has the benefit of representing arbitrary light directions.

So, how does it look? For comparison, here’s the Sponza Atrium without directional voxel data. The colored curtains are being lit by sunlight, and light is bouncing incorrectly behind the curtains due to a lack of directional data. This is a classic problem I see all the time with voxel-based GI solutions.

Here’s how it looks with directional voxel data enabled.

The drawback is that cone tracing becomes more expensive since 4 color values have to be fetched instead of 1 (for the SH coefficients). That’s a pretty big drawback.

So, overall the cost of voxelization has decreased, but the cost of tracing has increased. Of course, I’m not happy with the results yet, both visually and performance-wise. I don’t really know how all this is going to turn out. Maybe Spherical Harmonics voxel data is the future! Maybe I’ll have to look for another solution. All I can say is that I’ll keep working on it and let you guys know how it goes!

29 Likes

Third time.

Pointless.

“Minimum possible voxel size”.

Hey Sonic,
any tips on using SEGI in procedurally generated interior scenes? No luck with SEGI so far.

That’s great progress to me… :slight_smile:

2 Likes

Pretty awesome update and thanks for the detailed information! I always like to read about those things :smile:

Sounds like great progress is being done on SEGI.

I have a few questions, but i think i already know the answers.

  • Will we be able to set the number of cascades? (8 might be a bit too much if we want less memory used)
  • Can we adjust the scale ratio for the cascades? (instead of double we could set another value)

Maybe these would lead to inconsistent results, but it’s always good to know.
For example, we could use 4 cascades and 4x scale ratio to get the same area as 8 cascades and 2x scale ratio. Less detail but also less memory used, faster voxelization and faster render.

Keep doing that awesome work @sonicether :slight_smile:

3 Likes

Thank you for the update @sonicether . Is great to see what is going on and this was a pretty big one.

1 Like

@sonicether , would you mind sharing info about how performance is with cascading + directional voxel data, relative to the version 0.81 we have right now? Seems like it would be a shame to abandon your spherical harmonics implementation without letting us try it out. :slight_smile: And if the overall performance cost of what you’ve developed is comparable to what we’re dealing with currently, it seems like most/all of us would gladly accept the increase for cone tracing.

Pretty much all of us want to have bigger scenes and less light bleeding right meow. :stuck_out_tongue:

You know, since we’re now all a part of the beta process, is there any problem with releasing a SEGI 0.82b like Unity does?

Regardless if there are issues (it IS beta after all), I’d love to see how the changes/additions affect my work, even if merely incremental, and even if the feature ends up being removed.

That being said I’m a proponent of SH lighting and would love to see it in action, never mind the cascades (yay!)

Thanks Cody

4 Likes

This is one of the most fundamental improvements in real-time GI in any game engine in the past 10 years.

I played with the demos on an Nvidia 950M 2GB GDDR3.

I cannot, just cannot believe what I’m seeing.

Once you implement baking…

If you are an investor I recommend you hook up with Sonic Ether before one of the big boys snaps up his IP.

In Unity and say UE4, and even in the offline rendering world the absolute speed of SEGI previz/iterative/final lighting - being able to use this in Blender/ Cinema4D/ Max/ Maya where it need not be realtime…

Wow.

8 Likes

Maybe it’s just that SEGI is ahead of its time, and hardware needs time to catch up haha :smile:

Keep up the good work! Looking forwards to the next update.

3 Likes

That was my opinion. Wouldn’t be the first time; both games in the I-War series were like that.

–IronDuke

2 Likes

Hey man! Not to add to the stress, but I’ve been getting this error every time I turn SEGI on in my project:

material.sharedMaterialData->smallMaterialIndex != 0
UnityEngine.Camera:RenderWithShader(Shader, String)
SEGI:OnPreRender() (at Assets/SEGI/SEGI.cs:797)

This looks like its due to the fact that at the start of the scene I’m creating about 30 or so materials dynamically, but sometimes it ends up working itself out after a while and running properly, so I’m not sure :S. I think its being called for each object that uses the dynamically made mats.
Any help would rock! No rush of course!

1 Like

My first testing the Sponza demo @1366x768 (@1440x900) Fantastic quality:
L: 87 FPS (80), M: 69 (60), H: 51 (46) U: 43 (38)
With U preset : 63 (55) with low voxel resolution, 47 (41) off infinite bounces, GPU load 99%, about 769MB VRAM allocated
My GPU: Sapphire HD 7950 Boost (= R9 280).
Noticed after some testing with the settings the effect become inconsistent and I need to switch off and on GI to reset it.
Beautiful results in any case!

1 Like

This looks great! Does it work with Alloy shaders? What about 3rd party sky and water packages?

Thanks.

1 Like

No skybox support for now, and forward shaders are not supported yet either, only deffered ones sorry.

Also just a quick question sonic, how are cascade handled if the voxels center is determined by an other mesh, away from the camera?

1 Like

Alloy also has deferred shaders as well.

2 Likes

Then I think you should be fine using the deffered ones :wink:

Also reading it back I guess I’ve been a little harsh on my response. You can’t use a skybox for now (probably because Forward) However you can choose a (one) color for the sky, and change it at runtime. So if you manage to make a script that get the dominant color of your dynamic sky, you should be able to make SEGI roughly match it!

Same for the ocean, it probably won’t work if it’s forward (it probably is) however you can use an invisible plane mesh matching it’s color/specularity that will be used by SEGI as a replacement to illuminate objects on it!

1 Like

Not sure if this is possible, but it would kick ass. I have 2 GTX 980 Tis. Would it be possible to offload SEGI to the idle GPU, and use the full power of the 2nd GPU for crazy good GI? That could really turn Unity into a production renderer.

Pretty sure that’s not possible, or at least, it’s very infeasible. Developers have a hard enough time just distributing graphics workload evenly between two GPUs, let alone having them perform different tasks. Not to mention the multi-GPU setup is far less common.

2 Likes


Indoor lighting experiment with SEGI.

15 Likes