I’ve seen a few bug reports complaining about ‘flicker’ with HDR enabled. It took me a few tries to understand that the users were not actually reporting Z-Thrash (which is what I think of when someone says ‘flicker’, but were actually reporting temporal anti-aliasing of anisotropic meshes like roofs and roads.
Ants are alienating an icy tropical metro what now?!?
Sorry, graphics programmers have lots of big words for things that aren’t actually that complicated. (Seriously, we call a daytime texture an “albedo”. Who is Mr. Bedo anyway??) But basically the issue is this:
- We have something that appears long and thin on the screen, like the roof of a far off building (wide, but not tall, in pixels) or a road (again, wide, but not tall – a road might be 20 pixels wide but only 1 pixel tall on screen). Anisotropic just means different lengths in different dimensions, more or less.
- The road or roof will be rendered in a stair-step manner, as the graphics card tries to approximate a diagonal with pixels.
- As the camera moves, which pixels form the stair-step will change every frame, causing parts of the road or roof to flicker into and out of existence on a per frame basis.
Going for a Swim
In the old days, this effect used to be called ‘swimming’. A diagonal line would appear to ‘swim’ as the stair-step pattern changed as the camera changed. The swimming was annoying, but if you had a lame graphics card, you could live with it.
The problem is that in X-Plane 10, a lot of the meshes we draw are a lot smaller. As we build more 3-d detail and improve the engine to draw more detail on screen, the result is a lot of really small things. In X-Plane 9 we could draw 5-10k objects; now we can draw over 75k objects. That means that individual objects on screen may be 1/10th of their size (since there are more of them).
So instead of having big objects with big triangles that ‘swim’, we have tiny triangles that flicker out of existence entirely.
One reason I haven’t blogged about this before is because there are a ton of different full-screen anti-aliasing technologies out there and the prospect of explaining them was daunting. Fortunately Matt Pettineo did an awesome job with this post. Go read it; I’ll wait here.
The main idea is that full screen anti-aliasing draws everything bigger and then down-sizes it to get softer edges. Diagonals don’t look stair-stepped, and a tiny roof won’t flicker into and out of existence because relative to the larger size that it was drawn, the roof is no longer tiny. In other words, 4x MSAA makes everything 4x less tiny from a perspective of a triangle being ‘too small to not flicker’.
The second reason why I am getting bug reports about flicker (besides a larger number of smaller triangles) in v10 is that HDR mode doesn’t use conventional MSAA. For various technical reasons, MSAA works poorly with a deferred renderer, and HDR is a deferred renderer. So like many games today, X-Plane’s problem is to anti-alias without letting the hardware do it. If you’re used to 16x MSAA from your graphics card, HDR with no FSAA is a rude surprise.
Current Option Number One: FXAA
FXAA is an anti-aliasing shader written by Timothy Lottes at NVidia. FXAA is typical of a whole category of anti-aliasing solutions in that it is a post-processing solution – that is, it takes an aliased, jagged image and attempts to smooth out the image after the fact. (MLAA is also in this category.)
FXAA has a few things going for it that are good:
- It’s very fast. The cost of enabling FXAA is very low compared to other anti-aliasing algorithms.
- It doesn’t consume any extra memory or VRAM.
- It produces smooth diagonal lines, more so than lower-levels of FSAA.
It does, however, have one major down-side: because it doesn’t actually draw the scene at a higher resolution, any mesh that is so small that it is flickering is still small, and thus it will still flicker. On any given frame, the roof will have no jagged edges, but the roof may simply not exist in some frames. If the roof isn’t drawn at all, FXAA can’t fix it in a post-process.
So FXAA is fast and cheap and makes still images look nice, but it can’t deal with temporal artifacts, that is, flicker between frames.
Current Option Number Two: SSAA 4X
4x SSAA simply means we draw the entire world at double the resolution in either dimension, and then down-size it later. Jagged edges become blurred in the down-size and thus aliasing is reduced. (Nerd note: when technical papers talk about OGSSAA, they mean ordered grid super-sampled anti-aliasing, which just means the image is bigger. 🙂
The up-side to SSAA is that it reduces flicker. Because the drawn image is bigger, very small elements won’t flicker (since they are bigger when drawn).
The down-side is the cost: 4x SSAA is the same as doubling your screen res in both dimensions. And if you’ve experimented with monitor resolutions, you know that once you are GPU bound, doubling the resolution in both dimensions uses 4x the VRAM and cuts your framerate to a quarter of what it was.
So the big problem with 4x SSAA is cost. Since we’ve improved HDR performance in 10.10r3 I’ve seen more users reporting the use of 4x SSAA. But it’s not cheap.
Newer, Better Options
I have two new tricks for HDR FSAA that I’m hoping to roll into 10.20. (They’re new to X-plane; I am sure someone else has coded these things in other games before.)
First: FXAA and SSAA can be used at the same time in the engine, for better quality than either can provide on their own. SSAA does better at fixing temporal artifacts like flicker (because it makes things ‘4x bigger’ relative to the size at which they flicker) but FXAA does better at making diagonals ‘less jagged’. Now you can have both. (10.20 features a newer version of FXAA.)
Second: I realized that our aliasing is anisotropic (there’s that word again) meaning it’s not the same in both directions. X-Plane’s worst aliasing comes from long thin horizontal screen elements like roads, and roof tops. Therefore having more anti-aliasing vertically than horizontally is a win.
So rather than just have SSAA 4x (which is twice as big horizontally as vertically) we can now do 2x (only vertical) and 8x (2x horizontal, 4x vertical). This provides a range of options; 2x SSAA will be affordable to some users who can’t run 4x SSAA at decent framerates. 8x SSAA will provide anti-flicker that should be as similar to non-HDR with 16x MSAA for urban scenes, for those who have a big new graphics card.
I posted a set of technical test pictures here.
What about TXAA?
NVidia has announced a new anti-aliasing technology, called TXAA. At this point there isn’t enough technical information published about it for me to comment meaningfully on it. My understanding is that TXAA is not yet available for OpenGL based games.
I can say that in the future we will continue to try to adopt the best anti-aliasing technology we can find, and the problem X-Plane faces (anti-aliasing for a deferred renderer) is not at all unique to X-Plane, so it is likely that there will be good solutions forthcoming. Far smarter minds are working on this problem at ATI and NVidia as we speak.