Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Anti aliasing - FXAA GLSL

[ Original blog post battleworldrpg.net Mar 17 2013 ]

The biggest reason for re-factoring the rendering engine is to make room for the new shader system.

Today I managed to set up the 3D skybox system once again and added a few render buffers, particularly one that is used for post-processing, a handy technique for mangling your rendered scene so it can look pretty.

One such feature is anti-aliasing and the current popular technique for image enhancement is fast-approximate anti-aliasing, FXAA.

Anti-aliasing is the technique of smoothing out a 3D render so the pixels on the screen are less noticeable, FXAA is a quick approximation of how the smoothing should look like.

Here is Battle World's FXAA (Click open in full size).



On the left is no anti-aliasing, on the right is FXAA. Look at the corners where the darker ceiling meets the lighter walls.

FXAA is often praised for it's performance, it comes with no memory cost (Unless you count the frame-buffer, but I have it there anyway for other special effects) and can be slapped over any scene, in fact, you can see I only lose ~4 frames-per-second in this scene.

I have experienced problems with FXAA on mobile devices, their GPUs are pretty weak compared to the AMD HD 6970 on my primary development machine, so the speed hit is more apparent on devices such as iPhone, iPad and Tegra 3 chips, so far only the Adreno 320 can churn out over 60 frames with FXAA and that is probably due to it's unique chip layout.

So what's going on? In FXAA the processing is offloaded directly onto the GPU's fragment shader and runs across the entire resolution of the buffer, this is quite a lot of work. On a 1920x1080 buffer the GPU has to traverse 2,073,600 fragments (Fragments are essentially pixels), and reading a pixel is the slowest action of this process, FXAA reads pixel data 9 times for each pixel, that's 18,662,400 read operations! Good job PC GPUs are powerful enough to handle this.

Improvements to FXAA would be to somehow offload the calculations to the vertex shader, there are 6 vertices for the frame buffer (2 pairs overlap), much less than over 2 million fragments to traverse, at the moment there is no obvious parts of FXAA's operations that can be offloaded to the vertex shader.

Here's a download of the shader as a function for GLSL, remember to define the precision settings then just drop this function above your screen-shader and then run as "gl_FragColor = vec4( fxaa( INPUT_TEXTURE, TEXTURE_UV_VARYING, INVERSE_SCREEN_RESOLUTION ), 1.0 );"

FXAA GLGL Fragment Shader

The INVERSE_SCREEN_RESOLUTION is simply 1.0 / screenResolution[width/height], it is the rough size of the fragment on the open gl window.

The original source kept these as constants:

float FXAA_SPAN_MAX = 8.0;

float FXAA_REDUCE_MUL = 1.0/8.0;

float FXAA_REDUCE_MIN = (1.0/128.0);

But I highly recommend you equate them and move them directly into the shader source once you've experimented with changing their values.

Just plug those 3 lines at the top of the shader file to put them to use.
 
Nice work, I don't know about the maths though, so enlighten me.
How CPU intensive is regular AA (2x2 max) compared to FXAA?
 
Tomas":3h5l3ngb said:
Nice work, I don't know about the maths though, so enlighten me.
How CPU intensive is regular AA (2x2 max) compared to FXAA?

There's so many different anti aliasing algorithms, I'm presuming you mean 2xMSAA? Multi sample anti aliasing basically stores some shapes that are checked against the area of pixels in question and then smooths out the edges that match the shapes, 2x is a list of 2x2 pixel shapes, 4x is 4x4, 8x etc.
The checking against the shapes is quite expensive as it has to check the shape and the area of pixels, so you parse, say, 16 shapes across an image, you then need a 16x16 pixel check area, so each colour check is 16x16x16x16xwidthxheight, massively expensive with high quality anti aliasing.

The original "normal" anti aliasing is to render the scene in high resolution then scale it down with a jpeg style compression to add smoothing, it makes things a bit blurry and doubles the memory usage of the frame buffer and doubles the intensity of all other fragment shaders, making everything run at half the speed, but itself is cheap on the fragment shader (pointless when it's just slowed down everything else on the scene).

All real-time anti aliasing methods are on the GPU so costs nothing on the CPU, generally it's a trade off between memory usage and fragment shader utilisation for quality and speed, FXAA concentrates on speed so the quality isn't great in some situations, alpha edges comes to mind.

There is a newer technique called SMAA which is faster and better than FXAA, but there are not many implementations out there. It's called sub pixel morphological anti aliasing, if you want to Google it.


To answer the question, theoretically a 1920x1080 image with 2xMSAA is 2x2x2x2x1920x1080, that's 33,177,600 pixel lookups, as I said above FXAA is just over 18 million so you can guess the difference in performance.

Now remember that games these days use 4xMSAA and 8xMSAA!
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top