From d8ecd337b9c7587aae5b63c1c84fc54f1cccf1cd Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 7 Mar 2026 00:20:09 +0100 Subject: [PATCH 01/10] renderer: make r_FXAA a new-style cvar --- src/engine/renderer/tr_backend.cpp | 2 +- src/engine/renderer/tr_init.cpp | 9 +++++++-- src/engine/renderer/tr_local.h | 4 +++- src/engine/renderer/tr_shade.cpp | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index d8604cc632..253ea5659d 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -1603,7 +1603,7 @@ void RB_RenderSSAO() void RB_FXAA() { - if ( !r_FXAA->integer || !gl_fxaaShader ) + if ( !r_FXAA.Get() || !gl_fxaaShader ) { return; } diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 2885749bcd..59e40c90f9 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -285,8 +285,11 @@ Cvar::Cvar r_rendererAPI( "r_rendererAPI", "Renderer API: 0: OpenGL, 1: Vul Cvar::Cvar r_bloom( "r_bloom", "Use bloom", Cvar::ARCHIVE, false ); Cvar::Cvar r_bloomBlur( "r_bloomBlur", "Bloom strength", Cvar::NONE, 0.2 ); Cvar::Cvar r_bloomPasses( "r_bloomPasses", "Amount of bloom passes in each direction", Cvar::NONE, 2 ); - cvar_t *r_FXAA; + + Cvar::Cvar r_FXAA( "r_FXAA", "Fast approximate anti-aliasing", Cvar::NONE, false ); + Cvar::Range> r_msaa( "r_msaa", "Amount of MSAA samples. 0 to disable", Cvar::NONE, 0, 0, 64 ); + Cvar::Range> r_ssao( "r_ssao", "Screen space ambient occlusion: " "-1: show, 0: disabled, 1: enabled", @@ -1205,8 +1208,10 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_printShaders = Cvar_Get( "r_printShaders", "0", 0 ); Cvar::Latch( r_bloom ); - r_FXAA = Cvar_Get( "r_FXAA", "0", CVAR_LATCH | CVAR_ARCHIVE ); Cvar::Latch( r_ssao ); + + Cvar::Latch( r_FXAA ); + Cvar::Latch( r_msaa ); // temporary variables that can change at any time diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index c5570f8704..a93f3c5aa0 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2778,8 +2778,10 @@ enum extern Cvar::Cvar r_bloom; extern Cvar::Cvar r_bloomBlur; extern Cvar::Cvar r_bloomPasses; - extern cvar_t *r_FXAA; extern Cvar::Range> r_ssao; + + extern Cvar::Cvar r_FXAA; + extern Cvar::Range> r_msaa; extern cvar_t *r_evsmPostProcess; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index b2c95800e5..a10e45eb10 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -374,7 +374,7 @@ static void GLSL_InitGPUShadersOrError() gl_ssaoShader->MarkProgramForBuilding(); } - if ( r_FXAA->integer != 0 ) + if ( r_FXAA.Get() ) { gl_shaderManager.LoadShader( gl_fxaaShader ); From bf076bab847ba52dae9778e84a4e67b349f90854 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 7 Mar 2026 00:30:19 +0100 Subject: [PATCH 02/10] glsl: move FXAA control knobs to fxaa_fp --- src/engine/renderer/glsl_source/fxaa3_11_fp.glsl | 14 -------------- src/engine/renderer/glsl_source/fxaa_fp.glsl | 13 ++++++++++--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/engine/renderer/glsl_source/fxaa3_11_fp.glsl b/src/engine/renderer/glsl_source/fxaa3_11_fp.glsl index 0619da2d4a..dd3757b08d 100644 --- a/src/engine/renderer/glsl_source/fxaa3_11_fp.glsl +++ b/src/engine/renderer/glsl_source/fxaa3_11_fp.glsl @@ -20,20 +20,6 @@ DAMAGES. kangz: This code has been set in the public domain by TIMOTHY LOTTES -============================================================================*/ - -//Due to our shader system, we put the defines for the control knobs here -#define FXAA_PC 1 -#if __VERSION__ == 120 -#define FXAA_GLSL_120 1 -#else -#define FXAA_GLSL_130 1 -#endif - -#define FXAA_QUALITY_PRESET 12 -#define FXAA_GREEN_AS_LUMA 1 - -/*============================================================================ ------------------------------------------------------------------------------ INTEGRATION CHECKLIST ------------------------------------------------------------------------------ diff --git a/src/engine/renderer/glsl_source/fxaa_fp.glsl b/src/engine/renderer/glsl_source/fxaa_fp.glsl index 873c90144c..a3fd19f06e 100644 --- a/src/engine/renderer/glsl_source/fxaa_fp.glsl +++ b/src/engine/renderer/glsl_source/fxaa_fp.glsl @@ -33,9 +33,16 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT /* fxaa_fp.glsl */ -// The FXAA parameters are put directly in fxaa3_11_fp.glsl -// because we cannot #include in the middle of a shader -// ^This is no longer true, but I'm not touching that mess +// Control knobs. +#if __VERSION__ == 120 +#define FXAA_GLSL_120 1 +#else +#define FXAA_GLSL_130 1 +#endif + +#define FXAA_PC 1 +#define FXAA_QUALITY_PRESET 12 +#define FXAA_GREEN_AS_LUMA 1 #insert fxaa3_11_fp From e6c9f58aabf92732c1f80f411b47a86dce09bdde Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 7 Mar 2026 00:39:22 +0100 Subject: [PATCH 03/10] tr_backend: run FXAA after the camera shader (after tone mapping and color conversion) --- src/engine/renderer/tr_backend.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 253ea5659d..03dffb608e 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -1621,12 +1621,12 @@ void RB_FXAA() // set the shader parameters gl_fxaaShader->BindProgram(); - // Swap main FBOs gl_fxaaShader->SetUniform_ColorMapBindless( GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) ); - backEnd.currentMainFBO = 1 - backEnd.currentMainFBO; - R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] ); + + // This shader is run last, so let it render to screen. + R_BindNullFBO(); Tess_InstantScreenSpaceQuad(); @@ -1693,13 +1693,22 @@ void RB_CameraPostFX() { } gl_cameraEffectsShader->SetUniform_Tonemap( tonemap ); - // This shader is run last, so let it render to screen instead of - // tr.mainFBO - R_BindNullFBO(); gl_cameraEffectsShader->SetUniform_CurrentMapBindless( GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) ); + if ( r_FXAA.Get() && gl_fxaaShader ) + { + // Swap main FBOs. + backEnd.currentMainFBO = 1 - backEnd.currentMainFBO; + R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] ); + } + else + { + // Without FXAA this shader is run last, so let it render to screen. + R_BindNullFBO(); + } + if ( glConfig.colorGrading ) { gl_cameraEffectsShader->SetUniform_ColorMap3DBindless( GL_BindToTMU( 3, tr.colorGradeImage ) ); } @@ -2810,11 +2819,11 @@ static void RB_RenderPostProcess() TransitionMSAAToMain( GL_COLOR_BUFFER_BIT ); - RB_FXAA(); - // render chromatic aberration RB_CameraPostFX(); + RB_FXAA(); + // copy to given byte buffer that is NOT a FBO if ( tr.refdef.pixelTarget != nullptr ) { glReadPixels( 0, 0, tr.refdef.pixelTargetWidth, tr.refdef.pixelTargetHeight, GL_RGBA, From 60fc015f2f93a25d92512ebb8e98c381b9cd4fca Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 7 Mar 2026 01:31:08 +0100 Subject: [PATCH 04/10] renderer: implement luminance-based FXAA --- src/engine/renderer/gl_shader.cpp | 12 +++++++++++- .../renderer/glsl_source/cameraEffects_fp.glsl | 18 ++++++++++++++++++ src/engine/renderer/glsl_source/fxaa_fp.glsl | 6 ++++-- src/engine/renderer/tr_init.cpp | 4 ++++ src/engine/renderer/tr_local.h | 2 ++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index f23055feb4..0bc331d78d 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -795,6 +795,16 @@ static std::string GenEngineConstants() { AddDefine( str, "r_colorGrading", 1 ); } + if ( r_showLuminance.Get() ) + { + AddDefine( str, "r_showLuminance", 1 ); + } + + if ( r_FXAA.Get() ) + { + AddDefine( str, "r_FXAA", 1 ); + } + if ( r_highPrecisionRendering.Get() ) { AddDefine( str, "r_highPrecisionRendering", 1 ); } @@ -3066,4 +3076,4 @@ GlobalUBOProxy::GlobalUBOProxy() : u_Tonemap( this ), u_TonemapParms( this ), u_Exposure( this ) { -} \ No newline at end of file +} diff --git a/src/engine/renderer/glsl_source/cameraEffects_fp.glsl b/src/engine/renderer/glsl_source/cameraEffects_fp.glsl index 8b243fdb44..64bbf23ab1 100644 --- a/src/engine/renderer/glsl_source/cameraEffects_fp.glsl +++ b/src/engine/renderer/glsl_source/cameraEffects_fp.glsl @@ -111,5 +111,23 @@ void main() color.xyz = pow(color.xyz, vec3(u_InverseGamma)); + #if defined(r_FXAA) || defined(r_showLuminance) + { + // That luminance vector comes from a comment in fxaa3_11_fp.glsl. + vec3 luminanceVector = vec3( 0.299, 0.587, 0.114 ); + + float luminance = dot( color.rgb, luminanceVector ); + + #if defined(r_showLuminance) + color.rgb = vec3( luminance ); + #endif + + #if defined(r_FXAA) + // Encode luminance in alpha channel. + color.a = luminance; + #endif + } + #endif + outputColor = color; } diff --git a/src/engine/renderer/glsl_source/fxaa_fp.glsl b/src/engine/renderer/glsl_source/fxaa_fp.glsl index a3fd19f06e..bd1df7b334 100644 --- a/src/engine/renderer/glsl_source/fxaa_fp.glsl +++ b/src/engine/renderer/glsl_source/fxaa_fp.glsl @@ -42,7 +42,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT #define FXAA_PC 1 #define FXAA_QUALITY_PRESET 12 -#define FXAA_GREEN_AS_LUMA 1 +#define FXAA_GREEN_AS_LUMA 0 #insert fxaa3_11_fp @@ -56,7 +56,7 @@ out vec4 outputColor; void main() { - outputColor = FxaaPixelShader( + vec4 color = FxaaPixelShader( gl_FragCoord.xy / r_FBufSize, //pos vec4(0.0), //not used u_ColorMap, //tex @@ -74,4 +74,6 @@ void main() 0.0, //not used vec4(0.0) //not used ); + + outputColor = vec4( color.rgb, 1.0f ); } diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 59e40c90f9..e76e1baad8 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -286,6 +286,8 @@ Cvar::Cvar r_rendererAPI( "r_rendererAPI", "Renderer API: 0: OpenGL, 1: Vul Cvar::Cvar r_bloomBlur( "r_bloomBlur", "Bloom strength", Cvar::NONE, 0.2 ); Cvar::Cvar r_bloomPasses( "r_bloomPasses", "Amount of bloom passes in each direction", Cvar::NONE, 2 ); + Cvar::Cvar r_showLuminance( "r_showLuminance", "Show luminance", Cvar::CHEAT, false ); + Cvar::Cvar r_FXAA( "r_FXAA", "Fast approximate anti-aliasing", Cvar::NONE, false ); Cvar::Range> r_msaa( "r_msaa", "Amount of MSAA samples. 0 to disable", Cvar::NONE, 0, 0, 64 ); @@ -1210,6 +1212,8 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_bloom ); Cvar::Latch( r_ssao ); + Cvar::Latch( r_showLuminance ); + Cvar::Latch( r_FXAA ); Cvar::Latch( r_msaa ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index a93f3c5aa0..a22c57afdb 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2780,6 +2780,8 @@ enum extern Cvar::Cvar r_bloomPasses; extern Cvar::Range> r_ssao; + extern Cvar::Cvar r_showLuminance; + extern Cvar::Cvar r_FXAA; extern Cvar::Range> r_msaa; From a02cb5e0d318eb60db46601831f63b8850f29c16 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 7 Mar 2026 01:55:32 +0100 Subject: [PATCH 05/10] renderer: add r_showFXAA --- src/engine/renderer/gl_shader.cpp | 5 +++++ src/engine/renderer/glsl_source/fxaa_fp.glsl | 13 +++++++++++++ src/engine/renderer/tr_init.cpp | 2 ++ src/engine/renderer/tr_local.h | 1 + 4 files changed, 21 insertions(+) diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 0bc331d78d..942fcb2295 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -803,6 +803,11 @@ static std::string GenEngineConstants() { if ( r_FXAA.Get() ) { AddDefine( str, "r_FXAA", 1 ); + + if ( r_showFXAA.Get() ) + { + AddDefine( str, "r_showFXAA", 1 ); + } } if ( r_highPrecisionRendering.Get() ) { diff --git a/src/engine/renderer/glsl_source/fxaa_fp.glsl b/src/engine/renderer/glsl_source/fxaa_fp.glsl index bd1df7b334..885d501982 100644 --- a/src/engine/renderer/glsl_source/fxaa_fp.glsl +++ b/src/engine/renderer/glsl_source/fxaa_fp.glsl @@ -75,5 +75,18 @@ void main() vec4(0.0) //not used ); + #if defined(r_showFXAA) + { + vec4 originalColor = FxaaTexTop( u_ColorMap, gl_FragCoord.xy / r_FBufSize ); + + if ( color.r != originalColor.r + || color.g != originalColor.g + || color.b != originalColor.b ) + { + color.rgb = vec3(1.0, 0.0, 0.0); + } + } + #endif + outputColor = vec4( color.rgb, 1.0f ); } diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index e76e1baad8..727308169d 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -289,6 +289,7 @@ Cvar::Cvar r_rendererAPI( "r_rendererAPI", "Renderer API: 0: OpenGL, 1: Vul Cvar::Cvar r_showLuminance( "r_showLuminance", "Show luminance", Cvar::CHEAT, false ); Cvar::Cvar r_FXAA( "r_FXAA", "Fast approximate anti-aliasing", Cvar::NONE, false ); + Cvar::Cvar r_showFXAA( "r_showFXAA", "Show pixels modified by FXAA", Cvar::CHEAT, false ); Cvar::Range> r_msaa( "r_msaa", "Amount of MSAA samples. 0 to disable", Cvar::NONE, 0, 0, 64 ); @@ -1215,6 +1216,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_showLuminance ); Cvar::Latch( r_FXAA ); + Cvar::Latch( r_showFXAA ); Cvar::Latch( r_msaa ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index a22c57afdb..63b8609ff1 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2783,6 +2783,7 @@ enum extern Cvar::Cvar r_showLuminance; extern Cvar::Cvar r_FXAA; + extern Cvar::Cvar r_showFXAA; extern Cvar::Range> r_msaa; From 9c28bf5a93766cdafce59724030a7ca3c702be13 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 7 Mar 2026 16:10:16 +0100 Subject: [PATCH 06/10] tr_backend: fix FXAA sampling by using GL_LINEAR on currentRender - fix FXAA by using GL_LINEAR on currentRender, - restore GL_NEAREST after that to not break other effects. --- src/engine/renderer/glsl_source/fxaa_fp.glsl | 5 ++ src/engine/renderer/tr_backend.cpp | 56 ++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/engine/renderer/glsl_source/fxaa_fp.glsl b/src/engine/renderer/glsl_source/fxaa_fp.glsl index 885d501982..22b202b709 100644 --- a/src/engine/renderer/glsl_source/fxaa_fp.glsl +++ b/src/engine/renderer/glsl_source/fxaa_fp.glsl @@ -46,7 +46,12 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT #insert fxaa3_11_fp +#if defined(HAVE_ARB_bindless_texture) +uniform sampler2D u_ColorMap_linear; +#define u_ColorMap u_ColorMap_linear +#else uniform sampler2D u_ColorMap; +#endif #if __VERSION__ > 120 out vec4 outputColor; diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 03dffb608e..933089ec00 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -1625,11 +1625,67 @@ void RB_FXAA() GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) ); + bool greaterThanGL33 = std::make_pair( glConfig.glMajor, glConfig.glMinor ) >= std::make_pair( 3, 3 ); + + GLuint64 handle = 0; + + // FXAA expects GL_LINEAR for the sampling to work. + if ( greaterThanGL33 ) + { + GLuint sampler = 0; + glGenSamplers( 1, &sampler ); + glSamplerParameteri( sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ; + glSamplerParameteri( sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + + if ( glConfig.usingBindlessTextures ) + { + // Set a handler. + GLuint texture = tr.currentRenderImage[backEnd.currentMainFBO]->texnum; + handle = glGetTextureSamplerHandleARB( texture, sampler ); + glMakeTextureHandleResidentARB( handle ); + GLuint program = gl_fxaaShader->GetProgram()->id; + GLint location = glGetUniformLocation( program, "u_ColorMap_linear" ); + glUniformHandleui64ARB( location, handle ); + } + else + { + // Bind a sampler. + glBindSampler( 0, sampler ); + } + } + else + { + // Change the filter (requires a texture bind). + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + } + // This shader is run last, so let it render to screen. R_BindNullFBO(); Tess_InstantScreenSpaceQuad(); + // Make sure we didn't break other effects expecting GL_NEAREST. + if ( greaterThanGL33 ) + { + if ( glConfig.usingBindlessTextures ) + { + // Unset the handler. + glMakeTextureHandleNonResidentARB( handle ); + } + else + { + // Unbind the sampler. + glBindSampler( 0, 0 ); + } + } + else + { + // Restore the filter (requires a texture bind). + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + } + GL_CheckErrors(); } From f5707bfde86b64098dc7986c9bcda96f83547c21 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 8 Mar 2026 18:38:54 +0100 Subject: [PATCH 07/10] renderer: rename r_msaa as r_MSAA --- src/engine/renderer/tr_init.cpp | 4 ++-- src/engine/renderer/tr_local.h | 2 +- src/engine/renderer/tr_shade.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 727308169d..de69efdf20 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -291,7 +291,7 @@ Cvar::Cvar r_rendererAPI( "r_rendererAPI", "Renderer API: 0: OpenGL, 1: Vul Cvar::Cvar r_FXAA( "r_FXAA", "Fast approximate anti-aliasing", Cvar::NONE, false ); Cvar::Cvar r_showFXAA( "r_showFXAA", "Show pixels modified by FXAA", Cvar::CHEAT, false ); - Cvar::Range> r_msaa( "r_msaa", "Amount of MSAA samples. 0 to disable", Cvar::NONE, 0, 0, 64 ); + Cvar::Range> r_MSAA( "r_MSAA", "Amount of MSAA samples. 0 to disable", Cvar::NONE, 0, 0, 64 ); Cvar::Range> r_ssao( "r_ssao", "Screen space ambient occlusion: " @@ -1218,7 +1218,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_FXAA ); Cvar::Latch( r_showFXAA ); - Cvar::Latch( r_msaa ); + Cvar::Latch( r_MSAA ); // temporary variables that can change at any time r_showImages = Cvar_Get( "r_showImages", "0", CVAR_TEMP ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 63b8609ff1..fab84e6f2e 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2785,7 +2785,7 @@ enum extern Cvar::Cvar r_FXAA; extern Cvar::Cvar r_showFXAA; - extern Cvar::Range> r_msaa; + extern Cvar::Range> r_MSAA; extern cvar_t *r_evsmPostProcess; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index a10e45eb10..1bafa0a34e 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -181,14 +181,14 @@ static void EnableAvailableFeatures() } if ( std::make_pair( glConfig.glMajor, glConfig.glMinor ) >= std::make_pair( 3, 2 ) ) { - glConfig.MSAA = r_msaa.Get(); + glConfig.MSAA = r_MSAA.Get(); const int maxSamples = std::min( glConfig.maxColorTextureSamples, glConfig.maxDepthTextureSamples ); if ( glConfig.MSAA > maxSamples ) { - Log::Warn( "MSAA samples %i > %i, setting to %i", r_msaa.Get(), maxSamples, maxSamples ); + Log::Warn( "MSAA samples %i > %i, setting to %i", r_MSAA.Get(), maxSamples, maxSamples ); glConfig.MSAA = maxSamples; } - } else if ( r_msaa.Get() ) { + } else if ( r_MSAA.Get() ) { Log::Warn( "MSAA unavailable because GL version is lower than required (%i.%i < %i.%i)", glConfig.glMajor, glConfig.glMinor, 3, 2 ); } From 004318a55d902a115c7918bf86313306b70536ac Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 8 Mar 2026 18:48:42 +0100 Subject: [PATCH 08/10] renderer: disable FXAA when MSAA is enabled (prefer MSAA) --- src/engine/renderer/GLUtils.h | 1 + src/engine/renderer/gl_shader.cpp | 2 +- src/engine/renderer/tr_backend.cpp | 4 ++-- src/engine/renderer/tr_shade.cpp | 8 ++++++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/engine/renderer/GLUtils.h b/src/engine/renderer/GLUtils.h index e7a3a635ed..e88b099eba 100644 --- a/src/engine/renderer/GLUtils.h +++ b/src/engine/renderer/GLUtils.h @@ -155,6 +155,7 @@ struct GLConfig bool reflectionMappingAvailable; bool reflectionMapping; bool bloom; + bool FXAA; // automatically disabled when MSAA is not null int MSAA; // 0 == disabled, otherwise used as sample count bool ssao; bool motionBlur; diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 942fcb2295..49cb67c5c1 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -800,7 +800,7 @@ static std::string GenEngineConstants() { AddDefine( str, "r_showLuminance", 1 ); } - if ( r_FXAA.Get() ) + if ( glConfig.FXAA ) { AddDefine( str, "r_FXAA", 1 ); diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 933089ec00..d0702b745f 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -1603,7 +1603,7 @@ void RB_RenderSSAO() void RB_FXAA() { - if ( !r_FXAA.Get() || !gl_fxaaShader ) + if ( !glConfig.FXAA || !gl_fxaaShader ) { return; } @@ -1753,7 +1753,7 @@ void RB_CameraPostFX() { GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] ) ); - if ( r_FXAA.Get() && gl_fxaaShader ) + if ( glConfig.FXAA && gl_fxaaShader ) { // Swap main FBOs. backEnd.currentMainFBO = 1 - backEnd.currentMainFBO; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 1bafa0a34e..a025e1b655 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -192,6 +192,14 @@ static void EnableAvailableFeatures() Log::Warn( "MSAA unavailable because GL version is lower than required (%i.%i < %i.%i)", glConfig.glMajor, glConfig.glMinor, 3, 2 ); } + glConfig.FXAA = r_FXAA.Get(); + + if ( glConfig.FXAA && glConfig.MSAA ) + { + Log::Notice( "FXAA disabled because MSAA is enabled." ); + glConfig.FXAA = false; + } + glConfig.usingMaterialSystem = r_materialSystem.Get() && glConfig.materialSystemAvailable; glConfig.usingBindlessTextures = glConfig.usingMaterialSystem || ( r_preferBindlessTextures.Get() && glConfig.bindlessTexturesAvailable ); From 9eacf789320cf4c4eff5b1dea55420388f7df82a Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 8 Mar 2026 19:28:39 +0100 Subject: [PATCH 09/10] renderer: make FXAA configurable with cvars --- src/engine/renderer/gl_shader.cpp | 4 ++++ src/engine/renderer/glsl_source/fxaa_fp.glsl | 6 +++--- src/engine/renderer/tr_init.cpp | 9 +++++++++ src/engine/renderer/tr_local.h | 3 +++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 49cb67c5c1..a369e0bf73 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -804,6 +804,10 @@ static std::string GenEngineConstants() { { AddDefine( str, "r_FXAA", 1 ); + AddDefine( str, "r_FXAASubPix", r_FXAASubPix.Get() ); + AddDefine( str, "r_FXAAEdgeThreshold", r_FXAAEdgeThreshold.Get() ); + AddDefine( str, "r_FXAAEdgeThresholdMin", r_FXAAEdgeThresholdMin.Get() ); + if ( r_showFXAA.Get() ) { AddDefine( str, "r_showFXAA", 1 ); diff --git a/src/engine/renderer/glsl_source/fxaa_fp.glsl b/src/engine/renderer/glsl_source/fxaa_fp.glsl index 22b202b709..380093c46f 100644 --- a/src/engine/renderer/glsl_source/fxaa_fp.glsl +++ b/src/engine/renderer/glsl_source/fxaa_fp.glsl @@ -71,9 +71,9 @@ void main() vec4(0.0), //not used vec4(0.0), //not used vec4(0.0), //not used - 0.75, //fxaaQualitySubpix - 0.166, //fxaaQualityEdgeThreshold - 0.0625, //fxaaQualityEdgeThresholdMin + r_FXAASubPix, //fxaaQualitySubpix + r_FXAAEdgeThreshold, //fxaaQualityEdgeThreshold + r_FXAAEdgeThresholdMin, //fxaaQualityEdgeThresholdMin 0.0, //not used 0.0, //not used 0.0, //not used diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index de69efdf20..fc98b96157 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -289,6 +289,12 @@ Cvar::Cvar r_rendererAPI( "r_rendererAPI", "Renderer API: 0: OpenGL, 1: Vul Cvar::Cvar r_showLuminance( "r_showLuminance", "Show luminance", Cvar::CHEAT, false ); Cvar::Cvar r_FXAA( "r_FXAA", "Fast approximate anti-aliasing", Cvar::NONE, false ); + + // Values taken from comments in fxaa3_11_fp.glsl. + Cvar::Range> r_FXAASubPix( "r_FXAASubPix", "0: off, 0.25: almost off, 0.50: sharper, 0.75, standard, 1: softer", Cvar::NONE, 0.75f, 0.0f, 1.0f ); + Cvar::Range> r_FXAAEdgeThreshold( "r_FXAAEdgeThreshold", "0.063: overkill and slower, 0.125: high quality, 0.166: standard, 0.250: low quality, 0.333 too little and faster", Cvar::NONE, 0.166f, 0.063f, 0.333f ); + Cvar::Range> r_FXAAEdgeThresholdMin( "r_FXAAEdgeThresholdMin", "0.0312: visible limit, 0.0625: high quality, 0.0833: upper limit", Cvar::NONE, 0.0625f, 0.0312f, 0.0833f ); + Cvar::Cvar r_showFXAA( "r_showFXAA", "Show pixels modified by FXAA", Cvar::CHEAT, false ); Cvar::Range> r_MSAA( "r_MSAA", "Amount of MSAA samples. 0 to disable", Cvar::NONE, 0, 0, 64 ); @@ -1216,6 +1222,9 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_showLuminance ); Cvar::Latch( r_FXAA ); + Cvar::Latch( r_FXAASubPix ); + Cvar::Latch( r_FXAAEdgeThreshold ); + Cvar::Latch( r_FXAAEdgeThresholdMin ); Cvar::Latch( r_showFXAA ); Cvar::Latch( r_MSAA ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index fab84e6f2e..783f3427b6 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2783,6 +2783,9 @@ enum extern Cvar::Cvar r_showLuminance; extern Cvar::Cvar r_FXAA; + extern Cvar::Range> r_FXAASubPix; + extern Cvar::Range> r_FXAAEdgeThreshold; + extern Cvar::Range> r_FXAAEdgeThresholdMin; extern Cvar::Cvar r_showFXAA; extern Cvar::Range> r_MSAA; From c871c8e3cc822ae3cce72b712accd2548290508a Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sun, 8 Mar 2026 20:00:28 +0100 Subject: [PATCH 10/10] tr_init: reduce r_FXAAEdgeThreshold to 0.250 --- src/engine/renderer/tr_init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index fc98b96157..c8715693c6 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -292,7 +292,7 @@ Cvar::Cvar r_rendererAPI( "r_rendererAPI", "Renderer API: 0: OpenGL, 1: Vul // Values taken from comments in fxaa3_11_fp.glsl. Cvar::Range> r_FXAASubPix( "r_FXAASubPix", "0: off, 0.25: almost off, 0.50: sharper, 0.75, standard, 1: softer", Cvar::NONE, 0.75f, 0.0f, 1.0f ); - Cvar::Range> r_FXAAEdgeThreshold( "r_FXAAEdgeThreshold", "0.063: overkill and slower, 0.125: high quality, 0.166: standard, 0.250: low quality, 0.333 too little and faster", Cvar::NONE, 0.166f, 0.063f, 0.333f ); + Cvar::Range> r_FXAAEdgeThreshold( "r_FXAAEdgeThreshold", "0.063: overkill and slower, 0.125: high quality, 0.166: standard, 0.250: low quality, 0.333 too little and faster", Cvar::NONE, 0.250f, 0.063f, 0.333f ); Cvar::Range> r_FXAAEdgeThresholdMin( "r_FXAAEdgeThresholdMin", "0.0312: visible limit, 0.0625: high quality, 0.0833: upper limit", Cvar::NONE, 0.0625f, 0.0312f, 0.0833f ); Cvar::Cvar r_showFXAA( "r_showFXAA", "Show pixels modified by FXAA", Cvar::CHEAT, false );