Anti-Aliasing comparison tool, MK2

3 years or so back, I wrote a tool to compare anti-aliasing methods. It was designed to accompany my Beyond3D article on the topic.

The tool is still useful, but it has a few issues:

  • It’s based on raw OpenGL code, which means that it’s hard to extend, and somewhat likely to break on driver updates.
  • For the same reason, it’s slightly more difficult to ship without dependencies.
  • It doesn’t offer any temporal anti-aliasing technology, which is currently where much of the most interesting research is happening.
  • Its user interface is terrible, and it doesn’t guide people in any way in terms of interpreting what they see.

To solve these issues, I implemented a very similar tool in Unity.

You can get it here.

It features a whole lot of information about the various AA types it supports in tool-tips, and also includes the currently-in-development Unity temporal anti aliasing.

aatest_2016_10_08_21_22_34_955 aatest_2016_10_08_21_23_02_960 aatest_2016_10_08_21_22_48_516If anyone is interested in the sources I can release them, it’s pretty basic and mostly boring UI stuff.

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)

More TPXAA Comparisons

What better way to compare staircase artifacts than with a staircase? Here we see that for classic aliasing artifacts, TPXAA smoothing performance is as good as FXAA. Looking at the grass texture in the upper left corner the undesirable overall blur of the FXAA image is faintly visible.

In this purely 2D comparison, TPXAA does nothing while FXAA deforms the straight red geometric shape and diminishes the text outline.

Finally, this mixed comparison shows sume HUD deformation with FXAA that is prevented by TPXAA.

Full source images:

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.

Results

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:

Performance

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.

Limitations

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.