godotengine / godot

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

LightmapGI: Lightmap bounces increase indirect light energy too much #73295

Closed jcostello closed 10 months ago

jcostello commented 1 year ago

Godot version

v4.0.beta17.official [c40020513]

System information

Ubuntu with Nvidia 2060

Issue description

Lightmap bounces increase indirect energy too much. Here is a comparison (2 bounces vs 5 bounces)

2 bounces 2-1 5 bounces 5-1

2 bounces 2-2 5 bounces 5-2

2 bounces 2-3 5 bounces 5-3

2 bounces 5-4 5 bounces 2-4

2 bounces 2-5 5 bounces 5-5

2 bounces 2-6 5 bounces 5-6

Steps to reproduce

Bake light with 2 bounces Bake light with 5 bounces

compare!

Minimal reproduction project

No needed

clayjohn commented 1 year ago

We should compare against a ray traced result using something like Blender Cycles. It's very hard to tell at a glance how much indirect light is "too much" without comparing to ground truth.

jcostello commented 1 year ago

@clayjohn

Blender Irradiance Bake, 2 bounces Screenshot from 2023-02-14 13-04-08

Blender Irradiance Bake, 5 bounces Screenshot from 2023-02-14 13-05-28

jcostello commented 1 year ago

I will create more comparisons

jcostello commented 1 year ago

Another one

blender 2 bounces image

blender 5 bounces image

blender 2 bounces image

blender 5 bounces image

Calinou commented 1 year ago

It's possible that Blender divides indirect light energy by the number of bounces to compensate for a greater number of bounces.

Does a similar behavior occur in 3.x's CPU lightmapper? I remember high levels of bounces looking much brighter there too.

jcostello commented 1 year ago

Cycles with 2 bounces image

Cycles with 6 bounces image

clayjohn commented 1 year ago

It's possible that Blender divides indirect light energy by the number of bounces to compensate for a greater number of bounces.

Does a similar behavior occur in 3.x's CPU lightmapper? I remember high levels of bounces looking much brighter there too.

Each bounce should have a smaller impact than the previous bounce (by a factor of 1/PI if I remember correctly). So it is not a matter of taking the total energy and dividing it by the number of bounces. Additional bounces should add light, but the additional amount should be very small once you go above 1-2 bounces

jcostello commented 1 year ago

It's possible that Blender divides indirect light energy by the number of bounces to compensate for a greater number of bounces. Does a similar behavior occur in 3.x's CPU lightmapper? I remember high levels of bounces looking much brighter there too.

Each bounce should have a smaller impact than the previous bounce (by a factor of 1/PI if I remember correctly). So it is not a matter of taking the total energy and dividing it by the number of bounces. Additional bounces should add light, but the additional amount should be very small once you go above 1-2 bounces

Exctly. Seems that in some point each aditional bounce add a considerable amount of energy. Aditionaly, bounces should travel less distance, right?

clayjohn commented 1 year ago

Exctly. Seems that in some point each aditional bounce add a considerable amount of energy. Aditionaly, bounces should travel less distance, right?

I don't think they travel less distance, but light attenuates over distance so the impact of faraway points becomes very small

solitaryurt commented 1 year ago

I am experiencing the same thing with 4.0.2

2 bounces: image

5 bounces: image

atirut-w commented 1 year ago

Each bounce should have a smaller impact than the previous bounce (by a factor of 1/PI if I remember correctly). So it is not a matter of taking the total energy and dividing it by the number of bounces. Additional bounces should add light, but the additional amount should be very small once you go above 1-2 bounces

Could they mean dividing by bounce count so that it simulates infinite bounces? I'm a noob in light transport, though.

DarioSamo commented 12 months ago

So I took a look at this problem and there's a lot of factors at play here.

First there's the whole matter of what the bounces actually do here. Like many at first I figured the lightmapping algorithm was actually doing bounces by tracing, storing the hit position and tracing again from that. Turns out that's a bit far from what it actually does.

As far as I can tell and after talking to Juan about it, it seems the current algorithm goes something like this:

Naturally, since there's not enough attenuation during each pass for other reasons, it seems like the algorithm only ever increases the accumulated light in intensity. Juan identified a few key points where attenuation could be introduced (multiplying by albedo and surface normal), and that might very well be a solution that approximates the result closer to what it should be.

At no point does the algorithm actually trace rays from a new origin, so it can't exactly ever reach occluded light sources (from every point in the mesh) by bouncing no matter how many bounces are added. On top of that, it seems the nature of these bounces will be further or closer to the ground truth based on how much the mesh itself covers and how much self-intersection can happen. If I understand it correctly, it's very possible a user could see a much more reduced impact on the amount of indirect light each bounce if the meshes are more split.

Right now I don't have a good proposal on how to fix this other than looking at the factors Juan has recommended and seeing if we can achieve an attenuation closer to what the ground truth is, but it's worth noting it might not get close to something like Blender outputs due to how the algorithm works.

jcostello commented 12 months ago

@DarioSamo is changing the algorithm a posibility?