Skip to content

Add light volume nodes as a fast way to render global illumination #11448

Open
@Arazalera

Description

@Arazalera

Describe the project you are working on

Projects involving procedural buildings and open world, focused on realism

Describe the problem or limitation you are having in your project

I've noticed that various Godot games often look subar is because the lighting is too flat, because global illumination is not used
But GI in godot seems to be difficult

  • LightmapGI is physically accurate, but requires UV2, and can only work on one mesh, and builtin UV2 unwrap only works on 1 mesh, can't really be used on moving objects
  • VoxelGI seems to be embarrassingly useless as light phases through everything
  • SDFGI looks good, but can have artifacts, expensive, and cannot work for moving objects

The first 2 in total amount to nothing, and 3 seems unnecessary

I was inspired by a trip to Wellington, and with overcast weather, and frequency of shopfront roofs, I've noticed how the light gradually gets darker as it goes deeper into the building

Image
141 Manners St, Wellington, Google Earth

While it can be expected of raytracing, but it visually resembles a gradient, so it's far easier to make a 3D gradient of sorts that modifies the lighting in it

It can also be noted in other games like DayZ, where no form of GI is used, and interiors look unusually bright and dull

Image
Image
by TopeREC on youtube

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Light volumes, being volumes that modify meshes' ambience/radiance and reflection panorama, color, and intensity should be added

A light volume would be one or multiple SDF-like shapes that have an intensity from 0 to 1 at a point and a color of the shape, and the ambient lighting of a mesh would be mixed with it's color, and would have an order in which volumes are applied

ambient = lerp(ambient, volume.ambient, sdf_intensity)

It could also be able to modify the ambient and reflection panorama for more precision

While less physically accurate, It would have an advantage over SDFGI by being easy to use for buildings in an open world, destructible buildings, and moving objects (vehicles for example), and having fast performance, physical accuracy doesn't really affect how realistic it looks, it's more important to just have global illumination without artifacts

It would also be resistant to artifacts, and a volume could also ignore directional lights, avoiding shadow artifacts and light leaking, and is really reliable way to making something look interior than directional shadows

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

A LightVolume would be a Node3D to do that, it's properties would be:

shape : the shape of the volume of a LightVolumeShape class

color : the color by which the ambient and reflective lighting would be multiplied by

intensity : the brightness of the volume multiplies color by intensity

order : the order in which the volume is applied, volumes of a lower node index are applied first, and volumes of a lower order are applied first
the calculated color is calculated by
ambient = lerp(ambient, volume.ambient, sdf_intensity)

The LightVolumeShape class is inherited by different shapes:

LightVolumeShapeBox : an SDF box

LightVolumeShapeSphere : an SDF sphere

LightVolumeShapeCapsule : an SDF capsule

LightVolumeShapeCylinder : an SDF cylinder

LightVolumeShapePolygon : an extruded 2D polygon, also has an option to only calculate intensity in 2D

There could also be a Mesh shape

All shapes also have an inflate parameter, which adds or subtracts to the distance, a bevel parameter, corresponding to SDF bevel, and a bevel_scale parameter, which also scales the distance by a vector

Volumes are sampled per-probe (LightVolumeProbe), per-vertex, or per-pixel

LightVolumeProbe is a Node3D that samples the GI at it's origin and applies it to all child meshes

For example ambient lighting has a color of (1, 1, 1), then we add a box volume with color (0, 0.5, 0), this would be the volume's intensity

Image

And this is the total color

Image

Then a second volume is added, with this intensity

Image

The second volume has a higher node index and is applied after the first volume

Image

Also note that the intensity of volumes is passed through a smoothing function like builtin smoothstep(0, 1, x)

Image
The volume intensity is also smoothed

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, it requires modifying built-in lighting

Is there a reason why this should be core and not an add-on in the asset library?

It likely needs to be core, as it requires modifying built-in lighting

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions