godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.07k stars 69 forks source link

Implement semi-dynamic resolution for reflection probes #3045

Open BastiaanOlij opened 2 years ago

BastiaanOlij commented 2 years ago

Describe the project you are working on

This came up discussing using many reflection probes in games like racing games or similar where the environment is often reflected in each vehicle for added realism.

Describe the problem or limitation you are having in your project

If you have a racing game with 20 cars on the grid, you end up with 20 reflection probes all required to be updated every frame. As reflection probes are implemented as cube maps this can become very taxing on the system.

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

Currently reflection probes are rendered at a set resolution and then mipmap levels are updated to allow for rendering reflections at the proper roughness and reflectiveness values of the material.

For instance this results in the following mipmap levels:

  1. 512x512x6 <- original texture we render into
  2. 256x256x6
  3. 128x128x6
  4. 64x64x6
  5. 32x32x6
  6. 16x16x6

What we can do is assign LOD distances to these levels. A reflection probe that is close to the camera renders into level 1 and the other 5 mipmaps are generated. A reflection probe that is far away from the camera renders into level 4, mipmaps 5 and 6 are generated as normal, 1, 2 and 3 become upscaled version of 4 (just in case the GPU decides to use a higher level). A reflection probe that is very far away gets disabled (see proposal #2784 which would work nicely in combination with this)

Finally we may want to introduce a method that determines which LOD level of the meshes are being used. We don't want to render high detailed meshes when we're rendering into our level 5 reflection probe. Whether that is possible will need to be seen as the LOD levels here work on distance from the probe.

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

This will need to be worked out further but this can either be enabled automatically for reflection probes that are set to update every frame or become a new option added to the reflection probes properties.

There is an argument for the latter when multiple cameras are involved. Again taking the racing game as an example, I'll have a camera facing forwards, but i may also have a camera facing backwards to render the cars mirrors. I do not want all the reflection probes being rendered twice just because I have two cameras. We may want to introduce a method to identify which active camera is used to determine the LOD level we're applying.

We'll also need to experiment if we can determine the LOD level distances automatically or whether these need to be settings as well.

Code wise seeing the mipmaps are in place we need the following changes:

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

No, this has to happen inside of the render engine

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

No, this has to happen inside of the render engine

Calinou commented 2 years ago

Finally we may want to introduce a method that determines which LOD level of the meshes are being used. We don't want to render high detailed meshes when we're rendering into our level 5 reflection probe. Whether that is possible will need to be seen as the LOD levels here work on distance from the probe.

We have a Lod Threshold property in ReflectionProbe which should do that already. Its default value is 0 – we can probably increase it to be more aggressive.