godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.15k stars 21.19k forks source link

Light attenuation is incorrect in VoxelGI (values above 1.0 are too dark) #80101

Open SenhorPatolino opened 1 year ago

SenhorPatolino commented 1 year ago

Godot version

v4.1.stable.official [970459615]

System information

Godot v4.1.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1050 Ti (NVIDIA; 31.0.15.3598) - Intel(R) Xeon(R) CPU E3-1230 V2 @ 3.30GHz (8 Threads)

Issue description

Light attenuation greatly affects VoxelGI, way more than it should, depending on the value it won't even show up, neither increasing the range solves it:

Light attenuation set to 3.14 image image

Light attenuation set to 1.0 image image

Steps to reproduce

Add any kinds of 3D light, set the attenuation to a value bellow 1 and it will start showing up incorrectly, range and intensity will start to have no effect over the light, and it will have a hard cut

Minimal reproduction project

VoxelGIAttenuation.zip

Calinou commented 1 year ago

Can you reproduce this with GIProbe in 3.5.2?

SenhorPatolino commented 1 year ago

3.5.2 tested and it works fine

This is an omni light with attenuation set to 3.14, I made the light intensity low and increased indirect light contribution to showcase the actual GIprobe image

Calinou commented 1 year ago

Note that light attenuation in 3.x uses a different algorithm than 4.x: https://github.com/godotengine/godot/pull/44941

You can use the 4.x light attenuation formula in 3.x by enabling Use Physical Light Attenuation in the Project Settings then restarting the editor. Remember to bake GIProbe again after doing so, though I don't remember if physical light attenuation affects GIProbe.

SenhorPatolino commented 1 year ago

I tested in Godot 4 with that option and it worked, although range and Intensity still have a "clamped" functionality, and by clamped I mean that the intensity lumens actually controls the range and intensity. So the parameters range and intensity act more like a "mix factor".

Calinou commented 1 year ago

I tested in Godot 4 with that option and it worked, although range and Intensity still have a "clamped" functionality, and by clamped I mean that the intensity lumens actually controls the range and intensity. So the parameters range and intensity act more like a "mix factor".

I was referring to an option which does not exist in Godot 4: physical light attenuation, not physical light units :slightly_smiling_face:

SenhorPatolino commented 1 year ago

Oh, huh, that was my bad, I'll test that again, though it is curious how enabling physical light units actually helps.

I tested Physical Light Attenuation in Godot 3.5.2 and it does work completely fine image

takdew commented 2 weeks ago

Any updates on this? It still doesn't work in 4.4 dev3

Calinou commented 2 weeks ago

Any updates on this? It still doesn't work in 4.4 dev3

I've taken a look at the code that updates VoxelGI lighting and couldn't find anything of note.

takdew commented 2 weeks ago

I've taken a look at the code that updates VoxelGI lighting and couldn't find anything of note.

It would seem, that removing the attenuation check in line 281 from the file you linked fixes VoxelGI completely cutting off light, that should propagate otherwise.

-       if (attenuation < 0.01 || (length(normal) > 0.2 && dot(normal, light_dir) >= 0)) {
+   if ((length(normal) > 0.2 && dot(normal, light_dir) >= 0)) {
        return false; //not facing the light, or attenuation is near zero
    }

This is the testing setup without VoxelGI and with attenuation 2.0 and indirect energy 16.0:

att_2_novoxel

This is with VoxelGI currently (note that there is no difference at all):

att_2_voxel_prechange

The same setup after removing the check:

att_2_voxel_postchange

For reference, here's the same setup with SDFGI enabled (default config):

att_2_sdfgi

Another reference - attenuation 1.0 with VoxelGI (before and after look the same in this case):

att_1_voxel_postchange

Removing the check, from my understanding, might degrade performance due to computing lighting that might actually have near zero attenuation.

On the other hand, changing it to a lower value, e.g. 0.0001, introduces unexpected colors where light is nearing zero attenuation (at least in my production scene).

When compared to SDFGI, you can clearly tell that there is a huge difference between how attenuation is computed for VoxelGI.