In the previous post I explained how to create the sphere geometry for the planet.
In this post I will explain how to add height data to the vertices which will create continents, islands and oceans.

The plan for this post is the create height data for each face of the sphere, displacing the positions to create land and oceans.
One important quality is that generation should be pseudorandom, allowing the creation of many different looking planets and also completely replicating the same generation by suppliying a unique seed to the random generator.
The current geometry consists of 6 grids collapsed into a sphere. This fact simplifies a lot of the work we have to do. If one wants to create a texture they can easily retain the UV mapping of a grid and attach a texture for each face or just use a cube map.

For future level of detail reasons I decided to split my geometry into 6 different vertex buffers, which allows me to completely cull invisible individual planes and implement LOD algorithms to each plane as if it was an isolated terrain chunk.
for ( int j = 0; j < numRows; ++j )
{
for ( int i = 0; i < numCols; ++i )
{
vertices[ j * width + i ].UV.x = (float)i / (float)(numCols - 1);
vertices[ j * width + i ].UV.y = (float)j / (float)(numRows - 1);
}
}
Now that we have UV mapping, color and height textures can be applied.
As I mentioned in the previous post, part of the reason I chose procedural content generation is to compensate for my lack of artistic skill. In other words the best way for me to create textures to apply to the planet is by creating a program that will generate them for me. And they said programmers are safe from AIs taking our jobs...
We have 6 grids each in need of height data, one special requirement is that the data will wrap back nicely along the edges of each face of the grid. Past experience with content generation had me Google for perlin noise terrain generation keywords which lead to this tutorial.
Libnoise is a portable, open-source, coherent noise-generating library for C++. This sounds good for my needs as I am running the code on my Nexus 5 Android phone and the library supports a SetSeed function so it fills the requirement of being able to replicate the same results given a seed.
The generated maps can be easily cut into a cube map or individual textures for each face of the sphere. This is an example of a generated map from the tutorial link above:
It uses Perlin noise in its tutorial on terrain generation. Perlin noise is a gradient noise generator known to be a good for generating fractals and is used to simulate elements from nature like clouds, smoke and terrain.
Unfortunately, after experimenting with it for a while I felt it is too slow to generate the data and I looked for alternative. This let me to Simplex Noise which is faster and delivers similar results to Perlin noise. It can also run on the GPU.
Now that I decided on a noise algorithm I needed an implementation that will satisfy our constraints. I found this implementation as a lightweight C++ solution and started to experiment for results.
The useful function in the simplexnoise.h file for our case is the scaled_octave_noise_3d which allows noise to be generated for 3D coordinates, satisfying our need for wrapped the textures along the intersections of the planes.
float scaled_octave_noise_3d( const float octaves,
const float persistence,
const float scale,
const float loBound,
const float hiBound,
const float x,
const float y,
const float z );
For each vertex after mapping the position to a sphere, I applied displacement using this function:
void CalculateHeight( Vector3& vPosition )
{
// Get the direction vector from the center of the sphere
Vector3 vNormalFromCenter = vPosition;
vNormalFromCenter.Normalize();
// Variables for the noise
static const float HEIGHT_MAX = 24.5f; // Planet Radius is 1,000.
static const float HEIGHT_MIN = -31.0f;
static const float NOISE_PERSISTENCE = 0.6f;
static const float NOISE_OCTAVES = 8.0f;
static const float NOISE_SCALE = 1.0f;
// Generate the noise for the position
float fNoise = scaled_octave_noise_3d( HEIGHT_OCTAVES, HEIGHT_PERSISTENCE, NOISE_SCALE, HEIGHT_MIN, HEIGHT_MAX, vPosition.x, vPosition.y, vPosition.z );
// Keep ocean level as base level
if ( fNoise <= -0.0f )
fNoise = 0.0f;
// Displace the position
vPosition += vNormalFromCenter * fNoise;
}
This led to the result shown in the first image on this page. I applied RGB(28, 107, 160) for all heights at 0.0f or below and RGB(61, 182, 29) for all land masses.
Note the values for minimum and maximum height. As the earth is about one third land and two thirds water I decided to experiment with values that will produce around 33%-40% land. After experimenting with the values I found -31.0 to 24.5 produced nice results. Feel free to experiment. Also, my planet has a radius of 1,000 so these values made somewhat sense on a relative scale.
These are quite satisfying as a fast solution to begin with. In the future I hope to increase the detail by applying a second noise map with less persistence and/or increased scale on heights above ocean level. This should generate additional mountains and less consistent land masses.
Here is an example of a planet with NOISE_SCALE = 2.5f:

As I mentioned at the beginning of the post, one of the requirements for the generator is to be able to replicate a result given a seed. While libnoise library offered a SetSeed function, SimplexNoise had no implemented method to use.
Luckily implementing one was quite easy. In the simplexnoise.h header there is an array of numbers used as a permutation table.
static const int perm[512] = { ... }
The array basically contains all numbers from 0 to 255 shuffled randomaly. The sequence is then duplicated once to fill the array.
By changing the array from a const and applying the following function you can easily set the seed and replicate the same results for a planet:
// Variables
// perm - SimplexNoise's Permutation table
void set_seed( unsigned int seed )
{
// Set the seed for random generator
srand( seed );
// Set up the random numbers table
for ( int i = 0; i < 256; ++i )
{
// Put each number in once
perm[ i ] = i;
}
// Randomize the random numbers table
for ( int i = 0; i < 256; ++i )
{
// Replace current value with random value from the table
int k = perm[ i ]; // current value
// Random table cell
int j = (int)random( 256 );
// Replace two values
perm[ i ] = perm[ j ];
perm[ j ] = k;
// The table repeats itself so just assign repeating values the same way
perm[ 256 + i ] = perm[ j ];
perm[ 256 + j ] = k;
}
}
This is all for this post. In following posts I will look into lighting, Atmospheric Scattering, generating of biomes and colors for the planets and level of detail.