Filtering approaches for Real-time anti-aliasing (SIGGRAPH)
On the siggraph of 2011, Nvida put forward FXAA3.1, this article mainly introduces FXAA realization idea, and provides some simple implementation code.
1.What is FXAA 3.11
- Fast approximate anti-aliasing
- Algorithms
-FXAA 3.11 Console (PS3)
-FXAA 3.11 Quality (PC)
- Fixed Set of Constraints
- One shader pass, only color input, only color output
- Run on all APIs (GL, DX9, through DX11, etc)
- Certainly better can be do under other constraints!
FXAA full name "fast approximate anti-aliasing", translated into Chinese is "fast approximate anti-aliasing."
FXAA3.11 has made some improvements on the basis of the previous fxaa1,2.
- FXAA1: The earliest and most basic version, is also the most widely used in PC games, has been used in "Crysis 2", "Land without the Lord."
- FXAA2: Designed specifically for Xbox 360 consoles.
- The fxaa3:quality quality version for the Pc,console console version is for Xbox 360, PS3.
FXAA is a one-way pixel shader that runs in the post-processing phase of the target game rendering pipeline as Mlaa does, but does not use directcompute like the latter, but simply a post-processing shader that does not rely on any GPU compute API. Because of this, FXAA technology has no special requirements for graphics cards, fully compatible with NVIDIA, AMD's different graphics cards (Mlaa only support a card) and DX9, DX10, DX11.
2.How FXAA Working
Take 4 directions and intermediate pixels, filter the values of 5 positions, and perform piecewise linear transformations outside the range. For pixels with a large difference, make a AA.
maxLuma = max(nw,ne,sw,se)contrast = max(nw,ne,sw,se,m) - min(nw,ne,sw,se,m)if(contrast >= max(minThreshold, maxLuma * threshold))
dir.x = -((NW+NE)-(SW+SE))dir.y = ((NW+SW)-(NE+SE))dir.xy = normalize(dir.xy) * scale
Use 2x2 regions to calculate pixel boundaries and do vector operations. Normalized length after getting dir.
Optional Extra 2 Taps
Scale Dir.xy, expand to 8 pixels
minDir = min(|dir.x|, |dir.y|) * sharpness
Compare 4-tap Filter Luma to Neighborhood Luma
Compares the values of Luma and adjacent luma in 4 directions,
// Use the min and max luma range of the original 4 samples * {NW, NE, SW, SE}// If 4-tap filter luma exceeds this range, * and2 taps
3. Simple implementation
I myself again Direct11 environment, refer to Fxaa idea, realized a simple version of the FXAA, compared with the D3D realized 4xMSAA, the effect is less obvious, only for the exchange of learning.
//--------------------------------------------------------------------------------------//File:FXAA.fx//--------------------------------------------------------------------------------------Samplerstate Samlinear:Register(S0); Texture2d TXFXAA:Register(t0);structps_input{FLOAT4 pos:sv_position; FLOAT4 posproj:position; FLOAT3 Norm:normal; FLOAT4 diffuse:color0; FLOAT2 Tex:texcoord; FLOAT3 tangent:tangent;}; FLOAT4 fxaaps (ps_input input): sv_target{float4 texcolor = txfxaa.sample (samlinear, input. TEX);//FXAA 3x3 take 9 pixelsFLOAT3 Luma = FLOAT3 (0.299,0.587,0.114);//luma = FLOAT3 (0.33, 0.33, 0.33); floatLumatl = Dot (Luma, txfxaa.sample (samlinear, input. Tex.xy + FLOAT2 (-1.0,-1.0). xyz);floatLumatr = Dot (Luma, txfxaa.sample (samlinear, input. Tex.xy + FLOAT2 (1.0,-1.0). xyz);floatLUMABL = Dot (Luma, txfxaa.sample (samlinear, input. Tex.xy + FLOAT2 (-1.0,1.0). xyz);floatLUMABR = Dot (Luma, txfxaa.sample (samlinear, input. Tex.xy + FLOAT2 (1.0,1.0). xyz);floatLumam = Dot (Luma, txfxaa.sample (samlinear, input. TEX.XY). xyz); Float2 dir; Dir.x =-((Lumatl + lumatr)-(lumabl + Lumabr)); Dir.y = (Lumatl + lumabl)-(Lumatr + LUMABR);floatFxaa_span_max =8.0;floatDirereduce =1.0/128.0;floatInversedir =1.0/(Min (ABS (dir.x), ABS (DIR.Y)) + direreduce); dir = min (Float2 (Fxaa_span_max, Fxaa_span_max), MAX (Float2 (-fxaa_span_max,-fxaa_span_max), Dir*inversedir)); FLOAT3 res1 = (1.0/2.0) * (Txfxaa.sample (samlinear, input. Tex.xy + (dir * FLOAT2 (1.0/3.0-0.5,1.0/3.0-0.5)). xyz + txfxaa.sample (samlinear, input. Tex.xy + (dir * FLOAT2 (2.0/3.0-0.5,2.0/3.0-0.5)). xyz); FLOAT3 Res2 = res1 * (1.0/2.0) + (1.0/4.0) * (Txfxaa.sample (samlinear, input. Tex.xy + (dir * FLOAT2 (0.0/3.0-0.5,0.0/3.0-0.5)). xyz + txfxaa.sample (samlinear, input. Tex.xy + (dir * FLOAT2 (3.0/3.0-0.5,3.0/3.0-0.5)). xyz);floatLumares = Dot (luma, res2);floatlumamin = min (lumam, min (min (Lumatl, Lumatr), Min (lumabl, LUMABR)));floatLumamax = Max (Lumam, Max (Lumatl, Lumatr), Max (LUMABL, Lumabr));if(Lumares <lumamin | | lumares > Lumamax) texcolor = FLOAT4 (Res2,1.0);ElseTexcolor = FLOAT4 (Res1,1.0);returnTexcolor;}
- Comparison of effects (left without FXAA)
Filtering approaches for Real-time anti-aliasing (SIGGRAPH)