Wednesday 17 August 2016

Dissection of a Rendering Choice in No Man's Sky

Update: please note that this is now a historical post provided for educational value alone. The patch on 18/8 for PC removed the strong blur pass and fixed the AA settings.

So there has been lots of talk about internal render resolutions and game output this console generation. Is this game a 900p one, does the XB1 get forced down to 720p and then upscales it? It's a good topic for people who care about technical quality (say, all us render engineers who write the often boring code to throw polygons at screens via GPUs) and an endless swamp of people intent on having "heated debates" about their favourite consoles and which is best.

Anyway, No Man's Sky has come out and lots of people have mentioned that it looks muddy or low res, even on PC. Some people are speculating on it being rendered at a lower internal res and upscaled to explain what they are seeing. From everything I can see, this isn't correct but it's an amazing opportunity to dissect what is really going on and why it looks like that might be the case.

Straight off, how the game is running for me just in case this isn't true for you. SSAAx4 (rendering at 4x res and downsampling from inside the game) in the settings straight isn't working at all. No effect. I'm not the only one who has noted this so I'll call it either widespread or a feature that's not actually implemented yet. The other two options are FXAA or no AA. My experience is that FXAA, if it does anything when turned on, isn't the implementation you should have built into this game to make it actually fix aliasing issues. I also assert that anyone using SweetFX or drivers to inject SMAA/MLAA/FXAA into their game at the end of the render chain is also doing next to nothing for their game in the same way that doesn't work when you upscale a game and then apply it. (FXAA looks for the typical shapes [eg L shapes] of aliasing in high-contrast areas and selectively blurs them, but this only works when you've got those shapes as pixel-wide features to find.)


The reason why and the reason why lots of people seem to think this game is rendering at a lower res than stated or is just "really muddy" (as the pros have called it): because there's a 1px Gaussian blur being applied to this game before output. I would explain this is part of a HDR/bloom solution; only it isn't, it eagerly blurs everything, not just highlights. It's a blur on everything that weights significantly from the non-central pixel in the neighbourhood; a strong blur compared to what you normally see in real-time graphics.

And here's the major issue with that: it blurs the scene without any anti-aliasing being done first. This gives a bloom (light for highlights, dark for low features) to every bit of severe aliasing including the thin line geometry and shader aliasing going on. It does soften the aliasing, but this means FXAA can't find it and clean it up because it's no longer a hard line but a blurred one.

"But doesn't the blur fix everything wrong so what's the issue?"

Glad you asked - this is where slicing up what we see in screen captures of NMS really pays off. We do complex anti-aliasing (when rendering, even though it's often pretty expensive and comes with technical limitations that tie our hands) and not a blur because a blur doesn't work right.


Above is an example I generated to show anti-aliasing. It's zoomed up somewhat to make the pixels clearer but that was a clean zoom so each pixel edge is preserved (unlike how you'd normally blow up an image that also blurs it - the same is true of the zoomed in bits of the top image below). Take an aliased line (1) and blur it (2) and you get a bloom around an aliased line. This is a very clear visual and you'll be spotting it in No Man's Sky all over the place. But if you run anti-aliasing on that first line (3) and then blur that (4) we can see how that line looks good under the simple Gaussian 1px blur.

This is why you can't just use a blur: it leads to something that's still very much a stair-stepped but not with clean edges you can fix (it's a right pain to make line 2 into line 4 and AFAIK totally impossible to do that fast enough for real-time rendering; however making line 1 into something very much like line 3 is much cheaper/easier). If you want to run a blur for artistic reasons on your scene then anti-aliasing first will give the blurred line a really great and clean profile. The blur works with the anti-aliasing to give a result that's hard to deny.


A really weird thing I noted when finding this: the blur is always a 1px blur; same when running at 1080p and 4K. But there are twice as many pixels per inch of screen with a 4K render (outputting to the same display) and the scene being rendered is the same for both. The game-distance from any point to any other is the same but the pixel count to get there has doubled.

Why does that matter? It means the higher the resolution you set NMS to, the smaller (in scene size) the blur radius used and so the less annoying (for me*) it is. This is not how you should do a blur if you want it for an artistic effect and means anyone playing at 720p is being coated in a much larger radius blur than high-res players. I find that high res really helps (to recover the "sharpness" of the scene) so rendering at 4K and downsampling to 1080p leads to a much nicer result than using 1080p native, just because there is less blur to muddy the scene.

* And I like soft rendering - if it was a good blur that improved the scene not drew glows around every bit of aliasing, I'd be all for it and the artistic justification behind wanting a blurry final scene for the visuals of this game). I'm one of the few people who thinks TXAA was actually an ok AA solution despite it being very soft. I will take soft and stable (my eyes really don't like visual instability) over sharp and flickering every time.