After the strenuous trials of of the basics of
planetary generation I decided that I've had enough math for a bit and it was time to work on something shiny instead.
Coincidentally, while I was banging my head against the planetary wall, Neil was learning the basics of atmospheric scattering. He, like many before him, started with the
GPU Gems 2 article by Sean O'Neil from over a decade ago. It certainly seemed promising. No need for texture lookups or any kind of pre-generated data not only means the planetary atmospheric properties can be easily modded by players, but also gives the possibility of terraforming planets over time. Who's to say that without a concentrated player effort it shouldn't be possible to terraform Mars from its CO2 atmosphere into a Nitrogen-Oxygen mix? Doing so would certainly change its reddish hue to a blue one. Would be nice to make it change gradually over time, wouldn't it?
Anyhow, I digress... So Neil started with the GPU gems approach... and quickly ran into several limitations. First, the shader assumes that the atmosphere's radius is always going to be 2.5% of the planet's radius, and I thought it would be much nicer to not have this limitation. 5% looks better, and I'm still not fully committed to a 1:1 scale of planets -- but that's something I'll delve into in a later post.
Another limitation is that Eric's approach uses several shaders: one set for inside the atmosphere, and another for observer being outside the atmosphere. While not a big issue to swap between the two, there are enough differences between the shaders to make the change noticeable. That, to me, is unacceptable. All transition must be completely seamless.
The last limitation was something I discovered when I've delved into the task of atmospheric rendering myself -- the inability to control the colors properly -- especially during the sunset. In the screenshots on the GPU Gems page it shows a proper sunset, but no matter what I tried I couldn't get it to look quite like that.
Of course I've also purveyed the available assortment of similar solutions on the Asset Store. The most promising of them -- AS3 atmospheric scatter -- was broken in Unity 5, used per-vertex shading along with pre-generated textures, and looked even worse than the GPU Gems approach. It also still suffered from the visible shader transition from the outer to inner atmosphere. Worse still, adjusting the light properties at run-time had no effect on how the planet looked. Apparently light's color and intensity gets baked into whatever lookup textures it uses. So in other words -- scrap:
Years ago I also picked up
FORGE3D's planets. I'll admit, it was -- and still is -- a nice pack. It has a nice assortment of beautiful planets with thoughtful little details, such as having separate cloud maps for the sides of the planet and top/bottom to avoid the visual artifacts. I'm sure I'll be able to use some of the textures from it in the future. The way the shaders are structured also makes them quite suitable for procedurally generated content -- just specify the textures to use for the shader, and you've got a beautiful planet. The downside? Their planets are all external-view only, and everything is very art-side -- meaning lots of
very high res textures.
Other kits were less useful. Etherea1 is completely broken in Unity 5. Space Graphics Toolkit is also partially broken in Unity 5. The Blacksmith atmospheric scattering is planet-side only, is not realistic, and overall rather unwieldy... I can go on, but needless to say, I was not able to find anything that actually does the job I was looking for, so I had to give it a go myself.
So far I've spent just over a week on it. I continued what Neil started with the GPU Gems approach as it's the one that was "almost" there and got it to a state that both simplified the code and also made it more robust. I was able to eliminate the 2.5% limit I mentioned and fix the outer-inner transition issue (in fact, only one shader is needed to draw the atmosphere now, not two)... and I got it all looking moderately acceptable. The most challenging part for me was getting my head around the whole "scattering" deal -- and that was because it was difficult for me to visualize. I had to resort to writing a shader to show me what happens:
At the time of this writing, the atmosphere is still very much a work in progress. Unfortunately from my experience the GPU Gems shader-based scattering is not very flexible. There is still a matter of discontinuity between the atmosphere and surface shaders that I want to eliminate (I want one shader to "just work" for both), and it's rather difficult to get the effects I want. I've also not been successful in getting the sunset to look realistic. I am not seeing an orange sky until after the sun has set, and even then it's limited to the horizon where the sun disappeared, while the rest of the sky remains completely black. I will keep at it and see if I can improve it still, but for now it does look acceptable enough to move forward.
One thing's for sure though... I'm going to need to get some better textures.