Jump to content

Offline Light Propagation Volumes


Recommended Posts

  • Replies 67
  • Created
  • Last Reply

Top Posters In This Topic

I just did a push with some usability updates. I added a field flag so the gui inspector can display buttons instead of the hacked checkboxes:


If anyone wants to try it out you just place the volume around the area you want to use it on and then go through the steps from top to bottom.

voxelSize: size of each voxel in torque units. When you change this you need to regen volume.

regenVolume: voxelizes the area within the area and clears all the light and propagation grids. You can visualize it the editor with showVoxels.

injectLights: pulls the pointlights from the scene (pointlights only for now, will add spot and sun very soon), visualize in editor with showDirectLight.

propagateLights: propagates the lights through the grid. You can press this as many times as you want until you get a result you like. Visualize it in the editor with showPropagated.

exportPropagated: exports the results of propagation to the GPU to be displayed.

exportDirectLight: exports the results of injectLights to be used for reflections (optional). Check off renderReflection to enable the shader to display reflection within the volume. This property will save with the volume so you can turn it on/off.

Lastly, saveResults/loadResults. This exports the results from your propagation grid, and your direct light grid to the file path chosen in fileName. These results are loaded back in when the mission loads (or when you press the load button). These final results hold only what it needs to send to the GPU. You cannot propagate them further or work with them in the editor when you load from saved files. You have to start back at regenVolume and go through all the steps again. By doing it this way the final results are loaded straight to the GPU from temp buffers. This gives minimal memory usage when using them in a game.

Edited by andrewmac
Link to comment
Share on other sites

I spent the last few days experimenting with spherical harmonics. It seems like the natural progression people take when doing light propagation, and I see now why that is. With spherical harmonics you can store intensity of a color in a direction instead of just storing the color. You can also store more than one by adding them together. It's some neat math. I made this javascript demo while figuring them out:


What you see is a wall lit by two lights. As you press propagate it will propagate the light outward in the reflected direction. What's neat is it's a single row of voxels holding light data from both lights. As you propagate the two lights separate and go in opposite directions. My old propagation method was more or less a blur and would have just blurred those colors together into yellowish and pushed them outward in all directions.

This new propagation method produces much better results:


As shown in the video propagated light will show up on dynamic objects. They just can't occlude it, so if you stand in between the box and the wall the box will still be lit green from the wall. Also, the player will have green ambient light on sides not facing the green wall. It's not perfect, but it's plausible.

Link to comment
Share on other sites

@jay1ne : Not too much longer. I've gotta merge JeffR's improved voxelization, get it properly detecting material texture colors, sort out an issue with normals and then make sure my reflection angles are all correct. After that though, I think it'll be ready to be tested in some dev environments.

There's a ton of improvements and tweaks that can and will be done for awhile, but as far as being able to place a volume, generate some GI and use it in a game? Maybe a week away.

@buckmaster : I'm not personally diving in the PBR side of things, az has a handle on that. I did, however, lay all the groundwork and make material info available in the reflection shader, allowing az to shape the reflections in a more PBR-esque way. PBR really needs something to do glossy reflections that doesn't cost as much as dynamic cubemaps, and while this doesn't completely fill the void, it's a step in the right direction. I think the glossy reflections from this combined with a screenspace reflection shader should produce plausible glossy reflections for PBR, which is a HUGE part of PBR. PBR without reflections is like a sandwich without bread.

Link to comment
Share on other sites

Is this the sort of thing that could be run in a background thread for realtime updates? *strokes chin* Also, for a final solution, would the goal be to allow a handful of volumes to be active at a time so you can cover your level geometry more tightly in several smaller volumes, and select the ones that are most visible?

Link to comment
Share on other sites

The two most expensive parts of it, the voxelization and light injection, could not *easily* be multithreaded, but they certainly could. Problem is, both touch the geometry and light lists, and light injection relies on raycast. None of the above are thread safe. I personally don't believe we'll ever see this go real time. We could probably do something like relighting, where you can call a command to reinject the lighting and propagate again. This would help for scene lighting changes, and perhaps calling it per-tick during a time of day sequence would be acceptable, but I really don't think we'll see it happening per-frame and being worth the cost.

We won't know for sure until some artists start playing around with it but I do believe the best way to utilize these volumes would be as you said, placing multiple volumes around the level and positioning/tweaking them until you get a result you like. They aren't an exact science, and sometimes you'll really like the results in one spot, but not in another and artist placed volumes will alleviate that.

Link to comment
Share on other sites

JeffR's voxelization is in and we've got it detecting proper UV coordinates from the verts and pulling the color from the textures. Also, emissive materials are now actually emissive! They're injected into the light grid and propagated like any other light source:


Link to comment
Share on other sites

I've actually just recently added 4 new options for LPVs:

Light Intensity : multiplies the intensity of the lights injected into the grid

Emissive Intensity : same as light intensity only for emissive materials

Propagation Multiplier : multiplies the intensity of the light after each propagation step.

GI Multiplier : multiplies the intensity of the final result. This is useful if you like the spread but the overall result is too strong or too weak.

This allows a much greater degree of control over the final result. Also, while lighting rooms entirely with emissive I noticed a big missing piece. Ambient occlusion! We have SSAO, so I tossed it on. Unfortunately SSAO only applies to the sunlight, so I added support for it in the LPV shader:


All these changes have been pushed. I'm pretty much out of new things to add at this point. The only thing left to do is tweak the algorithms to see if we can reduce light bleed and improve propagation. It's my first time doing anything with spherical harmonics so I'm sure it could be better. My goal was to make an Offline Light Propagation Volume and it's getting close to complete. There's lots more than can be done (dynamic lights, voxel cone tracing, etc) but it starts going outside the scope of an offline light propagation volume. I've got to get back to working on other things though so I'm going to try to wrap this up in the next few days.

Link to comment
Share on other sites

Dude, that looks awesome, pretty soon we'll be close to Unreal Engine 4 level technology!


I hope that you mean Lighting wise because T3D looks awesome already but it will need some more work to get to Unreal Engine level of quality. :)

That said - I personally think after the graphics overhaul that we should focus on usability of T3D. But that is for another thread. :)

Link to comment
Share on other sites

  • 3 weeks later...


Unfortunately, I'm still unable to figure out what I'm doing wrong in getting this work in my build but I have faith it'll get figured out...Anyways I recall you saying that offline LPV would need an addition method to help things like shadows and what not. Then, I had a idea I recalled Lukas work with DSSDO a little over a year ago. Could this be added and solve some of the issues?

I was planning checking it out with my build once I get around this issues with why I can't get offline LPV working on any of my builds...Just something I figure I'd throw out there!


Link to comment
Share on other sites

Finally figure out what I was doing wrong..The following is the instruction on install/merging offline LPV with your project or running it:


  • If you are trying from the official branch, you'll need to download the zip

  • before compiling, you must add the directory into my Tools/CMake/torque3d.cmake file at around line 255:


    If you're using ProjectManager, add this line to Tools/ProjectGenerator/T3D.inc at around line 60:



Then compile and you should find it in the "level" tab..

If merging into your project, copy the following files into your project:



then you need the shaders from game/shaders/common:





Oh, and this script:


make sure you also do the steps above for Cmake and Project Manager also, or the icon will not show in your project...

I posted this for anyone that is interested, also because I ran into issues and figured it out and thought I'd share the steps to get it working...

Have fun!!!

Thanks to:

@andrewmac and @Gibby for the help!!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...