So, I’ve been working on some performance and rendering improvements.
If you remember earlier versions of Scatterer, they used used the depth buffer to apply the main scattering effect. This was a big source of issues, low depth-precision, no anti-aliasing support, depth artifacts etc… Let me just jog your memory with this one image:
A few versions back I switched to using a “projector” and got rid of the depth buffer. It’s essentially just a way to re-render all opaque objects in the scene with a different shader, in this case, the scattering shader. This fixes aliasing and depth related issues, but it is wasteful of CPU and GPU power (re-rendering opaque objects is expensive, this was one of the things I fixed in EVE-redux that boost performance) and couldn’t handle special cases, like terrain scatters/trees and Parallax displaced terrain causing them to not have scattering on them or only partly:
While trying to fix these issues, I decided to re-visit the depth buffer approach as it doesn't have those issues and could help improve performance.
First attempt using the depth buffer came out as broken as expected:
I won’t get too deep into the technical details but there is two main methods to reconstruct the world position from the depth buffer and both have issues with large distances.
If you’ve ever seen this issue in EVE-Redux:
This is the same issue. I work around it in EVE-Redux by fading out shadows in the distance, but this can’t really be done here.
At first I thought it must be the depth buffer precision that just sucks, as it always has. But how could this be? Unity switched to reverse-Z buffer recently which is renowned for good precision, and used in pretty much every large open-world or planetary rendering engine.
I decided to take a closer look at the depth buffer, and it looked completely fine, precision looked good, so the position reconstruction methods must be flawed somehow. Initially I came up with two over-engineered reconstruction methods, one involving an iterative search, and the other involving emulated double precision in the lossy operations. One of these worked very well (I’ll let you guess which one). However I later thought of just combining the two original methods from above, simply using one to get the direction and the second for the distance. This ended up working perfectly and being very simple and cheap.
So now we have precise positions reconstructed from depth, this means that the main scattering shader will get much cheaper, and won’t have to re-render god knows how many objects, reducing both CPU and GPU usage. Added bonus is it now works with Parallax and the terrain scatters so they get correct scattering as long as they write correctly to depth:
It also gets rid of these z-fighting artifacts which sometimes appear in the distance with the current method:
Tested it with RSS and Rescale and it seems to hold up as well.
For long-distance shadows also there is the partial depth buffer which I was rendering to cover the areas where depth reconstruction precision of the old method degraded for shadows, though in practice that was relatively fast, we can get rid of it now as well. This method can also be used in EVE-Redux as well so cloud shadows can cover the whole scene and not just ~5 km around the camera.
Another advantage is that we can now use the same method as EVE-Redux’s volumetrics: Render the scattering effect at ¼ the screen resolution for performance.
On the left is is how it is really rendered at low resolution, on the right is the final result after doing depth-aware upsampling and compositing with the rest of the effects:
This approach (1/4 resolution scattering) is however incompatible with godrays (at least for now), so it will auto-disable when using godrays, I’d also argue that if you can afford godrays you probably won’t need this.
Now there remains the issue that the depth buffer can’t be anti-aliased, while the main scene does, resulting in these lines around the scattering effect if AA is used:
Unity doesn’t expose a multi-sampled depth buffer, and while I managed to find a way to force it to render to one, and to resolve it manually in my shader, this pretty much broke other mods that use depth effects or image effects. The only other solution available was to disable hardware MSAA and use a post-processing AA. If you care about MSAA though don’t worry, depth-buffer mode can be disabled and you can keep the old MSAA-friendly mode, though that means giving up on the performance and compatibility improvements.
So, my first choice was to go with temporal Anti-aliasing. TAA is pretty good these days, in some cases better than MSAA because it offers temporal stability which MSAA does not. I got it working pretty well and was happy with how it looked, however due to a bug in unity when setting custom projection matrices (which TAA needs for slightly offsetting temporal samples) with a high far/near ratio such as in KSP, shadows flicker from some angles:
So that makes TAA not really usable, until Unity fixes this at least, though I will keep the option available for those who want to try it anyway.
My second choice was Subpixel Morphological Anti-Aliasing (SMAA). It is quite good and has different quality levels, in some regards it is better than TAA, and in every regard better than FXAA as it never blurs over details or textures. Overall I feel it looks very similar to 2x MSAA, which is mostly sufficient if you play at high resolution.
Here are two screens, one using the new method with SMAA, and one using the old method with 2xMSAA, can you tell which is which?
The second one is SMAA, and in this particular instance the SMAA image looks cleaner:
May be it would be better compared with 4xMSAA, though it varies a bit in motion.
An added bonus is that it also fixes the aliasing that the volumetrics of EVE-Redux introduce around crafts (if you’ve ever noticed that).
So now we can put it all together and see how it runs.
Let’s test something really low-end, here we have a weakly i3-3217U @1.8 Ghz and and its integrated HD graphics 4000, this is an old laptop, and it struggles just loading up KSP. Though it has a gt 740m (which is a bit faster but still slow) I'm going to test it on the integrated graphics.
Testing with just the scattering shader + sunlight extinction (which isn’t expensive), everything else disabled. Stock terrain at low. Running at 720p with no AA (because let’s be honest here we can’t afford much with integrated), running with these settings (hard shadows and all):
Stock gets ~30 fps with these settings, so we’re off to a bad start.
Previous release of scatterer gets 23 fps
New version gets ~24 fps (though I forgot SMAA enabled here but it barely removes 0.5-1 fps)
That's barely an improvement over last version. However now we can enable 1/4 res scattering and get 27 fps, that's already much closer to stock's 30 fps, and a 17% improvement over last version.
So there you have it, much closer performance to stock on the low-end settings.
Alright now something faster
On a GTX 1080 at 1440p and everything enabled, we go from 85 fps to 108 fps on the ocean surface with no AA, a 27% improvement
84 fps to 102 fps when zoomed out, a 21% improvement
And although it’s not a completely fair comparison, let’s look at 2x MSAA on the old version, and SMAA on the new one: 75 fps to 106 fps, a 41% improvement. MSAA is expensive
Oh and also, I tested with OpenGL on my main PC and it went from 35 fps to 64 fps (makes sense since this frees up some CPU overhead as well and OpenGL KSP is running on a single core for some reason), but I didn't take screens so the two guys playing on OpenGL will just have to try it for themselves :p
Now with all these new settings, it can become complicated to pick and tune your settings, so I’ve added the ability to load quality presets from config files:
I defined a few logical presets, each one tries to aim for the best quality/performance ratio, in increasing quality. The mod will default to “Low” from now on, which is just the ocean (with transparency and foam), the scattering at 1/4 res, and the non-expensive effects. Feel free to pick the preset that suits you best from the UI, you can go lower or higher, and a restart is no longer needed when changing some settings like ocean or terrain shadows. A few effects like long-distance shadows might be completely fine with stock but scale badly with with other mods, so keep that in mind.
Thank you for everyone who read this wall of text, I still have a few things to fix/test but I will be posting a build on Patreon soon, and making a public release as soon as this is all polished and ready
Check the links in the OP, there is a section about the Config Tool you can use to export atmosphere files, and the rest is in the wiki.