Aliasing and Anti-aliasing Comparison Tool

ss_2013-12-24_20-32-42This is a tool for illustrating the various types of aliasing which can occur in computer graphics, and how many common methods of anti-aliasing interact with them. I wrote it to accompany an article which will be published some time in the future, and which contains a rather detailed treatment of the topics of aliasing and anti-aliasing.

A main point is to also show aliasing (that is, flickering and image instability) in motion, which is insufficiently captured by the common screenshot or (compressed) video comparisons.

There are 6 types of aliasing shown (transparency aliasing, geometry aliasing (2D and 3D), sub-pixel aliasing, texture aliasing and shader aliasing), and many methods of anti-aliasing are available.

ss_2013-12-24_20-44-07The 1-8 keys are mapped to presets which show some common anti-aliasing methods:

  1.  none
  2. 4x MSAA
    multisampling, generally sparse grid
  3. 2×2 OGSSAA
    ordered grid supersampling with 4 samples
  4. 4x SSAA
    turns the 4 multisamples into supersamples, thus 4x SGSSAA on most HW
  5. FXAA
    just post-processing, see sub-pixel effects
  6. SMAA
    as above (note better motion stability)
  7. 1.5×1.5 OGSSAA + SMAA
    similar to what can be achieved via injection in most games, often decently playable
  8. best
    maximum number of SGSSAA samples plus 2×2 OGSSAA. Close to the “ground truth”, that is the perfect representation of the scene on the pixel grid

Let me know if anything breaks. I do know that the PXAA and TPXAA PPAA methods don’t work on AMD, if anyone wants to help fix it (and has the time) contact me and provide some means of synchronous communication (e.g. Steam ID).

Source code release soon.

Download here!

(If you encounter an error about missing some .dll when running the program, get the Microsoft C++ redistributable here)

(Edit 2014-1-14: updated to fix an issue which could occur with some AMD drivers)

PXAA in PtBi

PtBi has had the option of running FXAA in realtime on captured frames for a while. This has great results on edges (as long as they aren’t sub-pixel sized) and is very fast, but the disadvantage of also inadvertently affecting non-edge elements, particularly text and 2D GUI elements in general.

I’ve thought about how to prevent this for years, and finally implemented some of my ideas now. I call the result PXAA (Predicated FXAA), and it worked out rather well.

The general idea is this:

  1. From the original input frame luminosity, calculate 6 true/false values representing the following: horizontal rising edge start/end, horizontal edge, horizontal falling edge start/end, vertical rightward edge start/end, vertical edge, vertical leftward edge start/end
  2. Use these values to detect horizontal and vertical aliasing artifacts by following along an edge from one start/end to the next start/end, and store these edges in a predicate buffer
  3. (optional) Accumulate this predicate over several frames (I call this TPXAA)
  4. Use that predicate buffer to select whether or not to enable FXAA for each pixel

In terms of implementation, part (2) was challenging for a while since I could not think of a way to implement this efficiently without the ability to write multiple locations in a pixel shader. I toyed with the idea of implementing it in OpenCL, but that introduces more dependencies for my application and lots of boilerplate code. Luckily, the somewhat recent GL_ARB_shader_image_load_store extension does exactly what I needed.


The images below show some results of applying the process:

Test image 1 - NOAA

Test image 1 - FXAA

Test image 1 - TPXAA

To clearly illustrate the differences, here’s the result of a subtraction of the results of FXAA and PXAA from the Non-AAed images:

Test image 1 - FXAA/NOAA difference image

Test image 1 - PXAA/NOAA difference image

This gallery shows more comparisons + difference images:


Currently, performance results look like this on my GTX460 (naive measurement, from/to a glFinish) :

  • noaa (this is a copy operation): 0.2 ms
  • FXAA: 1.3 ms
  • PXAA: 2.3-3.2 ms (depends on number/length of edges)
  • TPXAA: 2.8-3.6 ms (as above)

A prototype without the image_load_store extension takes > 8 ms.


Because I (have to) use analog input for now, horizontal edges are slightly blurred, reducing the general effectiveness and accuracy of the method. For digital input, I could tighten the threshold and further reduce the amount of false positives.