Will Volumetric Lightmaps Ever Support Streaming Levels?

When they were introduced in 4.18 two years ago, I had figured the lack of streaming level support was going to be a short term issue given how many games rely on streaming levels to handle loading transitions and build bigger worlds. But in the last two years, there hasn’t been a peep from the Epic development staff about this or if it’s even on the docket (haven’t seen anything on Trello).

The volumetric lightmaps can produce gorgeous results, especially when paired with Distance Field Indirect Shadows for interactable props, but only allowing games that use single levels at a time (like small multiplayer maps) or smacking the player in the face with a loading screen between level loads is a serious limitation.

I’m just interested in hearing if this is even being considered or worked on, or if the development staff considers it a dead end that won’t receive any further support.

I have nothing useful to add other than the fact I’m very much interested also in knowing whether this will ever be supported.
For now, we’re relying on sparse indirect lighting volumes for our streaming levels, and I do worry that if this tech is deprecated, and eventually removed, we’ll have no options.

@Nick! one quick question for ya, you mentioned you’re using Distance Field Indirect Shadows for interactable props, much as we are, have you found a way to resolve the shadow bleed through occluded surfaces? it appears to completely disregard occlusion in our case, resulting in shadows from a prop that could not realistically create a shadow in that location. Just curious!

From what I’ve heard in the discord channel, it’s being worked for 4.24 by @Luoshuang himself.

Wow, thank you for sharing. That seriously just made my day. I can’t imagine not using volumetric lightmaps, but it’s really difficult to make a proper game without level streaming.

Just want to point out that it’s not so much smacking them with a loading screen as it is a blank/frozen screen, since it is impossible to make a proper loading screen in current engine versions without level streaming.

Sadly I haven’t. We get around the issue by using it mostly for pretty small props, usually up against larger objects (tables and walls) so the bleed isn’t noticeable. In some instances we’ve had to relight areas to avoid casting shadows that would have issues. In some ways it reminds me of the modulated shadows from early UE3 stuff that would bleed through surfaces (like Gears of War where you could see characters’ shadows through floors).

This is fantastic news! Do you have any more info on it or if Epic is picking up the code to roll into 4.24 officially? This would definitely be a huge win.

Confirmed issue on 4.24 release. VLM does not works properly through streaming levels.
It possible to reproduce. Just create additional 15-20 levels with persistent level. Place VLM volumes, geometry and build light with cell size 100 (200 default) for overflow summary cells through all levels. On distance more than 20 km VLM cells starts glitches, sometimes breaks self shadows on character (ThirdPersonCharacter). VLM cells for all levels keep like one huge array in memory and does not streaming with levels (does not supported with async loading as part of sub levels). Thats why.

Hope future release will support loading VLM volumes cells as streaming data…

There seem to be multiple issues going on. Most of our lighting features don’t work with world size >= WORLD_MAX = 2097152.0cm, so it’s kind of expected if you start to see weirdness for > 20km scenes.
However the (most detailed level) cells are supposed to be streamed. Are you sure your sublevels are properly unloaded? The cells will only be unloaded when the corresponding level UObject is unloaded. Also when in editor the sublevel’s VLM CPU data is not discarded because of multiple editor operations we need to support - you need to test in a standalone build (Development/Test/Shipping). When in game there’s supposed to be only one copy of the cell data - on GPU. You can verify memory consumption by using console command ‘stat mapbuilddata’. Let me know if you have any new findings so I can try to fix potential bugs. :o

Btw VLM works so amazing if look it as Quality/Performance side. Looks like amazing fake GI. Just look how character looks in light environment here and so cheap performance:

But it works like “no warranty”. That what i mean. So I try to explain what happened.

Every release from 4.18 (include betas ‘preview’) until current release i have learned how to reproduce that glitches and i know how they works. Few month ago I knew some methods how to catch glitches and how to avoid (i could explain if need) but its bad way on practice side and pipeline in real projects and still very experimental.
Also a year ago I checked on ‘windows’ builds (last time in 4.23, sure now in windows 4.24 same situation).
I know VLM cells works different than in PIE as well.

Note: I wrote simple plugin (wrap for Engine/LevelStreaming.h) for checking statuses for levels (each level has 7 different states). For me ok if all necessary levels are loaded.
And yea. I never dive to VLM source yet.

Prefer i work on macos, xcode, etc. 16 Gb Ram, tested on mac RX 580 , Vega.

For example this is simplest way for explanation:


Environment static GI is off (off for black), only lights. Cell size is 100 (half of height of character). Memory for bricks 30mb to 250mb. Loaded levels count are 1-3 (one place has 4-5 for tests).

Levels with different scenarios (SL, LM importance, VLM density volumes sizes; light type and light count; volumes overlaps; and etc. for tests):
Note: Yellow boxes are “Streaming Level Volumes”

Catched glitches on character looks like on this 4 screenshots:

And last levels (5-b,5-1,5-2) where VLM stop works:

Cells representation absent even do another levels are off in Editor. (limitations?)

Note1: Levels in list not sorted properly by engine (created or added later).
Note2: Each level in build has few simple geometry. Build size is 220 mb (20 levels of geometry, static lightmap data etc - around 50-60 mb of data for all levels). So levels load and unload very fast.

Sometimes if move around glitch area 30-40m a minute then glitch will gone (depends how far you go and back repeatedly). Magic?

Its just few examples. I discovered tens strange situations specially for VLM.
So if need more information about how bugs and glitches “works” in VLM i could explain more and more methods. Maybe it will help to make it perfect feature.

Example project video:
0:42 - how to glitches gone if load and unload previous level !
2:00 - another glitch but still bcoz no levels operations
3:14 - glitch and later it gone again (next level loaded/unloaded operations through LSV)
4:42 - black hole (no levels operations, just something happends)
6:18 - good example how it gone
7:54 -
10:54 - VLM cells stop working. No GI …
Note: 7 moments timestamped in description of this video on youtube. If rebuild light in project , count of situations various 5-15 and in another places of levels.

Sometimes people ask how engine calculate VLM cells on ‘build light’ stage.

  1. VLM dots fills like one big cube (on packaged build it parsed on bricks linked to levels) even do 90% space has no static meshes.
  2. Limitation for maximum distance.

Engine generates one big rectangle filled by VLM cells (waste 80% of free space).
Would be great if ‘build light’ will do more effective methods based on “clustering” of VLM density volumes for each level.

hoping this gets fixed :slight_smile:

and once we’re past that, we need a new thread: "Will Reflection Captures Ever Support Streaming Levels?"

Reflection captures works in streaming levels. Even do far distances

a cooked game with reflection captures in streamed levels will show “reflection captures need to be rebuilt” and the only way to fix it is by moving them all to the persistent level. I’ve seen other reported errors by other users but I have yet to verify if they still occur.
on top of that there’s a limit of 341 captures, which could become virtually infinite if reflection capture streaming would re-arrange the reflection cubemap array
and even if you might not fill all 341 captures, the reflection environment shader iterates through all captures to determine if each captures is needed - so reducing the reflection cubemap array by properly streaming reflection captures would mean a small performance gain

Im sure it works on macos packaged builds. Checked on ios metal as well. I never checked amount of captures for any limits, but 4-5 captures on each level works fine for me.
Maybe on another platforms has issue with it as you described.
You could try inspect with command ‘stat mapbuilddata’ how streamed refl.captures loads/unloads.

can we build multiple VLMs in multiple sublevels?

Yes. But it still not efficient - ‘build light’ creates one huge box for all VLM volumes (white dots)