godotengine / godot-proposals

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

Add an option to use smooth pixel texture filtering in BaseMaterial3D #9106

Open Calinou opened 6 months ago

Calinou commented 6 months ago

Describe the project you are working on

The Godot editor :slightly_smiling_face:

Describe the problem or limitation you are having in your project

Games with a pixel art style exhibit noise in the distance, even if mipmaps are enabled. This occurs regardless of anisotropic filtering level, and MSAA won't affect it either (by design). FXAA only has a limited effect on this kind of aliasing, as it can't smooth out temporal aliasing that occurs in motion.

Comparisons courtesy of https://github.com/andrei-drexler/ironwail/pull/61:

image

Nearest-neighbor filtering Smooth pixel filtering
image image

There are two alternatives available, each of them with their downsides:

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

Add an option to perform smooth pixel filtering in BaseMaterial3D, also known as antialiased point filtering. This was originally proposed in https://github.com/godotengine/godot/issues/20023.

Note that this is not the same as https://github.com/godotengine/godot-proposals/issues/6995, which is about scaling the entire viewport while this proposal is about handling texture filtering on 3D materials.

This proposal can also be implemented in 2D, but it's arguably not needed as often there as dedicated shaders like Rotsprite tend to be more commonly used for 2D.

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

We can either add 3 new filter options at the end of the Filter property enum in BaseMaterial3D, or add a checkbox below Filter that enables smooth pixel filtering regardless of filter mode, with the current mipmap/anisotropic mode preserved.

A MIT-licensed implementation by CptPotato can be found here: https://github.com/CptPotato/GodotThings/tree/master/SmoothPixelFiltering

Internally, linear filtering is always used when this shader is enabled, as it relies on linear filtering to work (even if the final result looks like nearest-neighbor, it technically isn't).

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

This can be worked around with a custom shader, but this makes the 3D pipeline a lot more complex if you have to use it for every material in your level (as opposed to simply ticking a checkbox in BaseMaterial3D). You'll generally want this option to be enabled on most of your materials (if not all).

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

This can be provided by an add-on, but until shader templates are implemented, usability will suffer. Also, I'd wager this is a common enough use case to warrant being in core. There are a lot of 3D pixel art games out there that have noisy pixels at a distance with no cheap way of resolving it :slightly_smiling_face:

Mickeon commented 6 months ago

While I do want this, that enum is enormous already and contains some very verbose options. I feel like reading/discovering what each one of these does is tedious. It does not feel right to add three more options like this.

So, I am okay with the checkbox myself.