Procedural Planets

3D planets may be procedurally generated to provide an infinite amount of planets to explore. This article will detail an algorithm used to procedurally generate planets in a deterministic manner.

Procedurally generating planets utilizes a seeded deterministic random source which is used to control all of the parameters and steps in the algorithm. Everything from the height of the deformations, the color of the surface, the rotational speed are all based on seed supplied to a deterministic random generator.

Algorithm

The general algorithm for creating a procedural planet is as follows:

  • Create seeded random source (spatial / non-spatial)
  • Set planet parameters
  • Create surface texture using a Fracture Algorithm:
    • Create triangles and raise points inside triangle up
    • Iterate 1200 times
  • Create heightmap and normal map from surface texture
  • Create sphere
  • Deform sphere according to heightmap and normal map
  • Color sphere based on surface texture
  • Done!

Parameters

Here’s a small sample of parameters used to control the planet generation. These may be set by the seeded random source so they are deterministic and always produce the same planet for a given seed.

Deform: 60
Radius: 12
Ocean Height: 0.502
Terrain Modifier: 23
Color Lightness: 0.57822
Color Type: Earth
Rotation Rate: Y-Axis = 12

Fracture Surface

The fracture idea here is inspired by the GDC talk Classic Game Postmortem: Star Control, specifically the Generating Surface Topography segment. The idea is to randomly place a triangle and raise the points inside the triangle up. Any triangle placed over and edge of the texture should wrap to the other side to keep the edges seamless.

The size and shape of the triangles are important. The deterministic random function can set long thing triangles, more uniform shaped triangles, rotated triangles, etc to make different styles of planets.

Here’s an example of placing the triangle, raising the points inside up, and then repeating 1200+ times.

200 Iterations:

400 Iterations:

600 Iterations:

800 Iterations:

1000 Iterations:

1225 Iterations:

After the texture is generated, the top and bottom values are smoothed slightly to reduce the jitter near the pole edge seams. The amount of smoothing falls off based on distance to the top/bottom of the texture. Also, oceans may be added by clamping the texture to a min height.

Heightmap Map

The resulting texture from fracture is not actually a nicely colored map as seen above, it’s actually a single color height map that looks more like this texture (red channel is height).

Normal Map

The normal map shows the direction that each point is facing. To generate the normal map, iterate over the pixels of the height map texture and sample the NSEW neighboring points to calculate the normal for each point.

Colorization

An HSL color to height map is created and then used to color each pixels of the the texture based on the corresponding height map value.

Create Sphere

Next, create a 3D sphere. This planet generator creates a octahedron sphere, where the sphere is created through subdivision. Note, older versions of Unity were limited to 64k vertices, but has been lifted in 2017.3: https://docs.unity3d.com/ScriptReference/Mesh-indexFormat.html

After the base sphere has been generated, the vertices of the sphere are deformed based on a sampling of the heightmap that corresponds to a UV for each vertex.

Note, the mesh edge seam will need to be welded together to ensure that heightmap variations are exactly the same. Specifically, the overlapping vertices are found and set to the same value to ensure there are no gaps. The color for each triangle based on an average sampling of the surface texture for that triangle’s UVs.

Animated Example

Here’s an animated example of a procedurally generated planet, along with the surface, height map, and normal map textures.

Atmosphere

The planet’s atmosphere may be generated using the same idea used to generate the planet surface. The atmosphere has a smaller range for the height map than the planet, and uses a transparent shader and more uniform color palette.

Crystal Planet

A crystal planet may be generated using a heightmap with greater height variation and an ocean threshold near 0, which provides a spiky surface.

Ringed Planets

Instead of creating a sphere for the atmosphere, the triangles can be randomly scattered along an axis of rotation to make up the planet’s ring.

In Closing

I have a lot of fun seeing the planets created by the procedural planet generator and look forward to continuing to improve on the algorithm.

Hope you found this article on procedural planet generation interesting,

Jesse from Smash/Riot