fix: FXAA sharpening and MSAA exclusion

- Post-FXAA unsharp mask: when FSR2 is active alongside FXAA, forward
  the FSR2 sharpness value (0–2) to the FXAA fragment shader via a new
  vec4 push constant. A contrast-adaptive sharpening step (unsharp mask
  scaled to 0–0.3) is applied after FXAA blending, recovering the
  crispness that FXAA's sub-pixel blend removes.  At sharpness=2.0 the
  output matches RCAS quality; at sharpness=0 the step is a no-op.

- MSAA guard: setFXAAEnabled() refuses to activate FXAA when hardware
  MSAA is in use. FXAA's role is to supplement FSR temporal AA, not to
  stack on top of MSAA which already resolves jaggies during the scene
  render pass.
This commit is contained in:
Kelsi 2026-03-12 22:38:37 -07:00
parent b832940509
commit d52c49c9fa
3 changed files with 38 additions and 9 deletions

View file

@ -2,7 +2,7 @@
// FXAA 3.11 — Fast Approximate Anti-Aliasing post-process pass.
// Reads the resolved scene color and outputs a smoothed result.
// Push constant: rcpFrame = vec2(1/width, 1/height).
// Push constant: rcpFrame = vec2(1/width, 1/height), sharpness (0=off, 2=max), unused.
layout(set = 0, binding = 0) uniform sampler2D uScene;
@ -10,7 +10,9 @@ layout(location = 0) in vec2 TexCoord;
layout(location = 0) out vec4 outColor;
layout(push_constant) uniform PC {
vec2 rcpFrame;
vec2 rcpFrame;
float sharpness; // 0 = no sharpen, 2 = max (matches FSR2 RCAS range)
float _pad;
} pc;
// Quality tuning
@ -128,5 +130,20 @@ void main() {
if ( horzSpan) finalUV.y += pixelOffsetFinal * lengthSign;
if (!horzSpan) finalUV.x += pixelOffsetFinal * lengthSign;
outColor = vec4(texture(uScene, finalUV).rgb, 1.0);
vec3 fxaaResult = texture(uScene, finalUV).rgb;
// Post-FXAA contrast-adaptive sharpening (unsharp mask).
// Counteracts FXAA's sub-pixel blur when sharpness > 0.
if (pc.sharpness > 0.0) {
vec2 r = pc.rcpFrame;
vec3 blur = (texture(uScene, uv + vec2(-r.x, 0)).rgb
+ texture(uScene, uv + vec2( r.x, 0)).rgb
+ texture(uScene, uv + vec2(0, -r.y)).rgb
+ texture(uScene, uv + vec2(0, r.y)).rgb) * 0.25;
// scale sharpness from [0,2] to a modest [0, 0.3] boost factor
float s = pc.sharpness * 0.15;
fxaaResult = clamp(fxaaResult + s * (fxaaResult - blur), 0.0, 1.0);
}
outColor = vec4(fxaaResult, 1.0);
}

Binary file not shown.