godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Allow changing the anisotropic filter level at run-time #4673

Open Calinou opened 2 years ago

Calinou commented 2 years ago

Related to https://github.com/godotengine/godot-proposals/issues/3134.

Describe the project you are working on

The Godot editor :slightly_smiling_face:

Describe the problem or limitation you are having in your project

The anisotropic filter level used in material rendering cannot be changed while the project is running. This can be too limiting for graphics settings menus, which generally allow changing the anisotropic filtering level to improve performance on low-end GPUs (or improve quality on high-end GPUs with memory bandwidth to spare).

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

Allow changing anisotropic filter level at run-time. This includes setting it at 1× to disable anisotropic filtering on all materials within the project, even if their sampling mode is set to anisotropic.

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

Similar to what https://github.com/godotengine/godot/pull/51679 did with mipmap LOD bias, the max anisotropy should be separated from the sampler state creation process so it can be adjusted at run-time.

Max anisotropy is currently defined here: https://github.com/godotengine/godot/blob/68b86220c806fa02d0d2b21d6561e7ea871e840e/servers/rendering/renderer_rd/storage_rd/material_storage.cpp#L1338-L1388

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

Anisotropic filtering can be disabled on a per-material basis (per-texture basis in 3.x), but this requires a lot of code to consistently apply throughout an entire project at run-time. Also, this does not allow using a lower or higher level of anisotropic filtering than the default while leaving it enabled.

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

Anisotropic filtering level can't be overridden by an add-on.

clayjohn commented 2 years ago

You should be able to update the default samplers in the same way that the custom samplers are updated. Then when Anisotropy is changed you just update both.

Calinou commented 2 years ago

You should be able to update the default samplers in the same way that the custom samplers are updated. Then when Anisotropy is changed you just update both.

By the way, I noticed mipmap LOD bias is not set on the default samplers, yet it still worked in https://github.com/godotengine/godot/pull/61953 on StandardMaterial3Ds.

wagnerfs commented 9 months ago

I got here to check if something was done about the proposal but it seems to be staled. I found a "loop hole" within the code that pretty much allows you to change anisotropy at run-time, should be pretty straight forward to add a method to Viewport and RenderingServer.

Basically, once you change texture_mipmap_bias on the viewport, it triggers update_samplers() which will clear and reallocate all samplers in the material storage, so by doing something like:

ProjectSettings.set_setting(
    "rendering/textures/default_filters/anisotropic_filtering_level",
    16.0)
get_viewport().texture_mipmap_bias = 1.0

You can slide in the new anisotropy level to be added to all materials with the anisotropy flag set, so current engine code doesn't need to be changed, just need to add a new method to both RenderingServer and Viewport that changes the global rendering/textures/default_filters/anisotropic_filtering_level and call update_samplers()

Calinou commented 9 months ago

@wagnerfs That's an interesting discovery – it should be relatively easy to add a method to set the anisotropic filtering level in this case. Perhaps it can even be made per-viewport like the texture mipmap bias (which is now correctly handled if it differs between multiple viewports in 4.3).

PS: Remember to set texture_mipmap_bias to 0.0 after a frame, or textures will look blurry:

ProjectSettings.set_setting(
    "rendering/textures/default_filters/anisotropic_filtering_level",
    16.0)
get_viewport().texture_mipmap_bias = 1.0
await get_tree().process_frame
get_viewport().texture_mipmap_bias = 0.0
wagnerfs commented 9 months ago

@Calinou I currently run a custom build of 4.2, so I just actually added a method to Viewport to handle it, I could do a PR for it if anything

Calinou commented 9 months ago

I currently run a custom build of 4.2, so I just actually added a method to Viewport to handle it, I could do a PR for it if anything

Feel free to open a pull request for this :slightly_smiling_face:

Note that this should be exposed as a property if possible, like texture_mipmap_bias. The documentation in ProjectSettings should also refer to that Viewport property for users wanting to change the anisotropic filtering level at runtime.