Skip to content

Add FXAA support to the Compatibility renderer#113763

Open
Calinou wants to merge 1 commit into
godotengine:masterfrom
Calinou:compatibility-add-fxaa
Open

Add FXAA support to the Compatibility renderer#113763
Calinou wants to merge 1 commit into
godotengine:masterfrom
Calinou:compatibility-add-fxaa

Conversation

@Calinou

@Calinou Calinou commented Dec 8, 2025

Copy link
Copy Markdown
Member

This adds FXAA support to the Compatibility renderer, making it have parity with Godot 3.x GLES3/GLES2 on this aspect.

When attempting to use SMAA in Compatibility (which isn't currently implemented), it will now fall back to FXAA to provide an experience as close as possible.

SMAA support could be added in a future PR (OpenGL ES 3.0 and WebGL 2.0 can support it), but it's more involved.

Testing project: test_screen_space_aa.zip

Preview

No glow, no SSAO

The first image has the separate tonemap pass disabled, as we don't use any effect that requires it (and scaling_3d_scale is 1.0). There is a slight color shift as soon as the separate tonemap pass kicks in, but this also happens in master with no FXAA.

Disabled FXAA
Screenshot_20251208_195625 Screenshot_20251208_195630

Glow + SSAO

Disabled FXAA
Screenshot_20251208_195601 Screenshot_20251208_195606

Glow + SSAO + AgX tonemapping

Disabled FXAA
Screenshot_20251208_195734 Screenshot_20251208_195739

TODO

@Calinou Calinou added this to the 4.x milestone Dec 8, 2025
@Calinou Calinou requested a review from a team as a code owner December 8, 2025 19:03
@Calinou Calinou force-pushed the compatibility-add-fxaa branch from 1aed91c to 6bd74b3 Compare December 8, 2025 19:07
Comment thread drivers/gles3/shaders/effects/post.glsl
@allenwp

allenwp commented Dec 8, 2025

Copy link
Copy Markdown
Contributor
  • Check order of operations (should FXAA be before or after tonemapping and/or glow)?

I believe the order is the best it can be for the same reasons as described in my earlier comment.

  • Check if the luminance exposure multiplier is correctly applied. It's possible that I got it wrong, or that I'm doing the operation for no benefit.

At first glance, this looks right to me (I see that you've inverted it to match the style of the Compatibility renderer). I don't know FXAA well enough to know if there are implications to applying the luminance multiplier to color and all of the other samples after FXAA, which would obviously save quite a few multiplication operations.

Also, I notice that you're passing in exposure, but this is not used in post.glsl. I believe this is a bug(?) but I haven't looked too much into this.

Comment thread drivers/gles3/shaders/effects/post.glsl Outdated
}

float rgb2luma(vec3 rgb) {
return sqrt(dot(rgb, vec3(0.299, 0.587, 0.114)));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the old NTSC/PAL luminance weights. They should probably be the Rec. 709 luminance weights. I recommend labelling them as such so that they will be easy to adapt to other colour primaries in the future (godotengine/godot-proposals#12783):

Suggested change
return sqrt(dot(rgb, vec3(0.299, 0.587, 0.114)));
const vec3 rec709_luminance_weights = vec3(0.2126, 0.7152, 0.0722);
return sqrt(dot(rgb, rec709_luminance_weights));

(I understand that Mobile and Foward+ use these incorrect weights as well. Eventually, I plan to open a PR to fix up all of these, but you're welcome to change over whichever you'd like in the mean time.

@Calinou Calinou Dec 9, 2025

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done for Compatibility. Should I also change them in Forward+/Mobile in this PR, or wait for a separate PR?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the tonemap.glsl and tonemap_mobile.glsl files are being touched to introduce the combined_luminance_multiplier optimization, I'd say you might as well go ahead and update the luminance weights there so that all files will stay in-sync with each other.

@allenwp

allenwp commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

Additionally, all three copies of do_fxaa should probably be updated in this PR to remove some math; I'm not a shader compiler expert, but I don't see the harm in helping out the compiler a bit as follows:

In post.glsl:

float combined_luminance_multiplier = exposure / luminance_multiplier;

In tonemap.glsl and tonemap_mobile.glsl:

float combined_luminance_multiplier = exposure * params.luminance_multiplier;

And then in all three files, replace all exposure * luminance_multiplier with combined_luminance_multiplier.

@Calinou Calinou force-pushed the compatibility-add-fxaa branch from 6bd74b3 to 9063d02 Compare December 9, 2025 17:49
@Calinou Calinou requested a review from a team as a code owner December 9, 2025 17:49
@Calinou

Calinou commented Dec 9, 2025

Copy link
Copy Markdown
Member Author

I've applied the changes/optimizations above and tested it on all renderers.

Comment thread drivers/gles3/shaders/effects/post.glsl
@allenwp

allenwp commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

Also, I notice that you're passing in exposure, but this is not used in post.glsl. I believe this is a bug(?) but I haven't looked too much into this.

I just tried a bit more with this: it seems that exposure is simply never applied with Environment Background Mode Canvas. Also, exposure is applied in earlier passes during 3D rendering in Compatibility, so in these cases it doesn't need to be a part of FXAA. It appears that there are a few things that need cleaning up before the use of exposure can make any sense in this new FXAA.

@Calinou Calinou force-pushed the compatibility-add-fxaa branch from 9063d02 to 2f66d2e Compare December 9, 2025 21:40

@allenwp allenwp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you've set apply_color_adjustments_in_post to true, but it does not seem to be active with 2D rendering, even when an Environment has been added with a background mode of Canvas

compat-fxaa.zip

Is this intentional? (I haven't looked into whether this is normal for Godot or not, so maybe this makes sense?)

Comment thread drivers/gles3/shaders/effects/post.glsl Outdated
Comment thread drivers/gles3/shaders/effects/post.glsl Outdated
Comment thread drivers/gles3/shaders/effects/post.glsl Outdated
@moonjank

Copy link
Copy Markdown

EDGE_THRESHOLD_MIN, EDGE_THRESHOLD_MAX and SUBPIXEL_QUALITY should be customizable. Not sure about ITERATIONS. Here is a customizable FXAA for those who want to customize these values. I believe customizable FXAA is especially important for compatibility due to not having many AA options.

@Calinou

Calinou commented Feb 20, 2026

Copy link
Copy Markdown
Member Author

Rebased and tested again, it works as expected. Thanks @allenwp for the feedback 🙂

I see that you've set apply_color_adjustments_in_post to true, but it does not seem to be active with 2D rendering, even when an Environment has been added with a background mode of Canvas

compat-fxaa.zip

Is this intentional? (I haven't looked into whether this is normal for Godot or not, so maybe this makes sense?)

This is probably intentional. We generally don't want FXAA to apply to 2D rendering, as it'll make it look very blurry (small text becomes almost unreadable). SMAA doesn't hurt 2D rendering as badly, but it's still not ideal.

PS: I can't download the project you linked (Not Found). It seems you're running into the same issue I was running into recently, where files uploaded can only be downloaded by the uploader.

EDGE_THRESHOLD_MIN, EDGE_THRESHOLD_MAX and SUBPIXEL_QUALITY should be customizable. Not sure about ITERATIONS. Here is a customizable FXAA for those who want to customize these values. I believe customizable FXAA is especially important for compatibility due to not having many AA options.

Being able to adjust FXAA (or SMAA) parameters should be discussed in its own proposal. If it's implemented, it should also be done in Forward+ and Mobile.

@Calinou Calinou force-pushed the compatibility-add-fxaa branch from 2f66d2e to 0272d2c Compare February 20, 2026 01:11
@Calinou Calinou force-pushed the compatibility-add-fxaa branch from 0272d2c to 3f2b574 Compare April 2, 2026 01:40
@Calinou Calinou force-pushed the compatibility-add-fxaa branch from 3f2b574 to 126655e Compare April 2, 2026 01:41
@BlueCube3310

Copy link
Copy Markdown
Contributor

Tested locally, it works as expected on desktop hardware
(Windows 10 (build 19045) - Multi-window, 2 monitors - OpenGL 3 (Compatibility) - NVIDIA GeForce RTX 4080 (NVIDIA; 32.0.15.9186) - AMD Ryzen 9 5900X 12-Core Processor (24 threads) - 63.91 GiB memory)

Testing project:
new-game-project.zip

The shader fails to compile on web (or any OpenGL ES 3 backend) with the following error:
error
It looks like the compiler is complaining about the QUALITY function comparing ints to floats:

float QUALITY(float q) {
	return (q < 5 ? 1.0 : (q > 5 ? (q < 10 ? 2.0 : (q < 11 ? 4.0 : 8.0)) : 1.5));
}

This next part isn't inherently related to this PR, just something I've noticed.
When using a tonemapper with non-default settings, for instance:
tonemap
The colors will become much less saturated when FXAA is enabled.

No FXAA FXAA
nofxaa wfxaa

I personally don't consider this a blocking issue, since the same effect happens on the master branch with SSAO enabled. Just something to keep in mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenGL: FXAA antialiasing is not reimplemented yet

5 participants