Procedural Planets

Procedural Planets
A procedurally-generated ice planet.

There seem to be many different approaches to creating procedural planets for a game. I’ve bought quite a few planet and atmosphere shader assets on the Unity Asset Store over the years, as well as studied quite a few planet-generating substances in the Adobe Substance ecosystem. I found that every approach had its advantages and disadvantages, so I tried to take the best of each approach to create my own.

Since the RTS game I’m creating takes place only in space (no landing on planets), I didn’t need to consider generating navigable planet terrain and transitioning between land and space. This allowed me to focus primarily on the view of planets from space.

A screenshot of a procedurally-generated ice planet up close, from a space RTS project.
Closeup of an ice planet.

My approach starts with using slightly customized octahedron mesh generation with separate cartesian and polar UVs that I found in an Asset Store asset as well as online. I blend both sets of UVs in the shader, but this gets fairly expensive as every texture needs to be sampled twice.

For textures, I created a large set of substances in Adobe Substance Designer which can generate all kinds of terrains, gas planet textures, clouds, city lights, etc. The Unity HDRP terrestrial planet shader I created is quite complex and heavy, but it allows customizing the layout of those substances. There are detail normal maps, water levels, moving water distortion normals (for shimmering water), ice cap levels (with associated detail normals), cloud detail normal maps, cloud shadows, moving clouds, various tiling options for closeup planets or far planets, and more. I also have another shader specifically for jovian (gas) planets, which have some slight movement on the surface.

For planets with atmospheres, I use three layers: The first is on the planet mesh and shader itself, with a way to color the planet surface using emission for a fresnel effect. For the second layer, I use another mesh and associated shader which allows me to color the horizon between the surface and space as well as provide airglow on the dark side. Finally, I use a third mesh with an unlit shader for Rayleigh and Mie atmospheric scattering beyond the planet surface.

Although the meshes and their shaders are quite performance heavy, these planets will take up such a large part of the background that I feel the cost is worth it. I figure that most space battles will take place right next to important places of interests like planets, moons, and space stations, and not out in the empty void of space, and so planets will be viewable fairly close, like in the above close screenshot. Thankfully, texture sizes don’t need to be that large as I tile some of the textures and use methods to break up the tiling.

While I haven’t created examples of them yet, the shaders and textures allow creating a wide variety of planet types such as cratered moons, lava planets, forest, gaia, and alien-looking planets. It took quite a long time to achieve all of this. It was even more difficult trying to get it all working for Unity’s High Definition Render Pipeline as I had to recreate a a lot of shaders in Shader Graph (no documentation for how to write HLSL shaders exist as of the time of this post). I’m finally done with it though, and now it takes me 2-3 hours to generate and customize a decent looking planet.

In addition to procedural planets, I also have a shader which allows using textures of actual solar system planets. Modders can use this shader to add their own 2:1 ratio planet textures, although the textures will need to be quite large to get good detail up-close.

Next up is to revamp the art pipeline for spaceships including concepting, modeling, texturing, shading, and loading at runtime. I’ll most likely be using a mid-poly workflow with mesh decal shaders, so let’s see how it goes!

A screenshot of a procedurally-generated desert planet from a space RTS project.
A full view of a procedurally generated desert planet.

A screenshot of a procedurally-generated desert planet close up, from a space RTS project.
Closeup of a desert planet.

Comments

The comments shown below are from visitors when I was using Squarespace for website hosting, but I've switched to cheaper hosting with a different CMS and currently have registering/commenting disabled. I've copy/pasted all past comments in case they may be useful for someone.

Murray 2023

Nice work, Sean.
I came here to check out your blog post about making a Unity game mod-able.
And thought I'd check out your other stuff!
Looking cool!

Sean Kumar 2023

Thank you for so much for stopping by!

Den Burg 2022

Hi, do u use sperical coordinates in input or 3d?

Sean Kumar 2022

Hey there! I'm not that familiar with spherical coordinates. Are you referring to the UVs? This is a 3d octahedron sphere mesh with a method taken from the following link:
https://web.archive.org/web/20171218054621/http://www.binpress.com/tutorial/creating-an-octahedron-sphere/162
In addition to the UV mapping shown in the link for UV0, there is also a polar projection done in the UV1 set, and then the two are blended in the shader. This is so that we don't get pinching in the poles, but then we do have to blend the two UVs for almost every texture. The mesh generation script was done in Unity using the Procedural Planets asset.

Marcus 2022

Awesome work! I would really like more details about the shader

Sean Kumar 2022

Thank you for the kind words! I just spent all this time typing up a reply, and it didn't get posted for some reason. Is there anything specific you'd like to know about? After studying many assets in the Unity Asset Store like Procedural Planets by Imphenzia, Forge3D Planets, AS3 Atmospheric Scattering, and many others, it took some months of experimentation, learning, and work trying to get all of this working in Unity's HDRP, so it's kind of hard to explain generally without going into the huge shader graph.