Procedural Planets and Stars
I got started on a VR space flight sim project and derailed immediately, spending a day doing procedural planets and stars instead. Here's a quick rundown of how I did them!
I’ve been playing a fair bit of Microsofts new Flight Simulator 2020 lately, and I love it. Another game I’ve been finally getting into recently is Elite Dangerous in VR.
One thing led to another and now I’m trying to replicate the intrecacy of FS2020 in a sci fi environment. Once I had some basic controls up and running (which I’ll need to do another post on) I needed an environment, and ended up putting 3 things
- Very cheap atmospheric rendering
- Procedural star environment shader
- Offline procedural planet generation in Houdini - Will be covered in a later post
Simple Planet Atmospherics
To be clear, this is not using UE4s new atmospherics system, since I needed something very cheap for VR. I figured there’s two key components to how atmospheres get their color: and sorry to anyone who actually knows anything about Rayleigh scattering or any other scattering I’m disregarding.
- How much atmosphere did the sunlight penetrate on its way towards the planet
- How much atmosphere did it penetrate on its way towards the camera
Luckily, both of these can be approximated reasonably well for spheres just using dot products!
So I got started with just a sphere and by grabbing the directional light vector we can get the dot product of that and the surface normal to find what is in light and what is in darkness. This is essentially lambert shading.
From this we can also extract specifically the area that is barely getting any sunlight, which also happens to be where the most amount of penetration and so scattering is happening, resulting in the red color.
Next up is how much scattering is going on on the way from the surface to the camera, which we can simplify to the dot product of the surface normal and the camera vector, which is essentially fresnel.
Now to get that subtle glow I have a slightly larger sphere on top of the planet but with its normals inverted running a very similar shader except that anything pertaining to the planet surface itself is removed and it’s changed to an additive shader.
I wanted to see if I could remove the need for textures for the stars because I’m trying to use "real" light values and auto exposure, meaning I’ll need a very high dynamic range available to me in the stars. Secondly to make it high res you need quite lot of pixels.
They are mostly done using 2D signed distance fields. A great resource for this sort of maths is Inigo Quiles’ website. To avoid pinching at the poles when doing shader math based on UVs I chose to start out with a cube which is smoothed and then projected onto a sphere. This gives me very clean topology and UVs!
Then in a shader I multiply and frac those UVs to get a higher density grid of UVs going 0-1. Within each of those grids I draw a little circle. To get the chaotic look of the night sky I introduce a little hash function at every level in terms of color, brightness and position.
There are some issues though. I’m using smoothstep() to "render" the circle distance field, which doesn’t have the nicest looking falloff, but smoothstep makes it easier to ensure I don’t render the dots outside their grid square.
You could have it render outside of its square, but that would increase the render cost as you’d need to sample all neighbouring square as well, which I wanted to avoid. So I’ve simply limited how close to the edge of ones grid a circle can be randomly placed.
Here’s an overview of what the final star shader looks like:
You can right click and open in new tab to see a slightly bigger version
One node I keep using is one I’ve called Hash21. It’s a very basic implementation of a hashing function and you can find much better versions online, this is just one I put together quickly. Here’s my implementation:
The reason it’s called 21 is because it takes in an vector 2, like UVs, and returns a random float between 0-1. This is not a great hash and is far from uniform. It doesn’t take much studying of the sky to start seeing some patterns, but it looks good enough if I jumble some numbers around.
Overall I’m happy with the look of the stars and atmosphere together. I’m planning to do another post later about how I do procedural texturing in Houdini, like I did for this planet.
Here’s a little sneak peak of the space ship sim where I put these features in, together with some not so great looking ice asteroids.