Procedural Planets
Generating Deterministic 3D 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.
These are the high level steps involved in procedurally generating a 3D planet:
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: Unity Mesh Index Format
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