In the last journal, I was explaining that one of the main benefits of working on the GPU instead of the CPU is the ability to create normal maps. Of course, it would be technically possible to generate them on the CPU too, but it would be far too costly, even with multithreading ( which the engine already supports ).
How does it work ? Well, each time the terrain quadtree gets subdivided ( as the viewer zooms in ), I'm rendering to a temporary F32 2D texture the heightmap for the new terrain patch. The shader generates, for each pixel of this heightmap, procedural height values that are a function of the XYZ position on the spherical surface. Then for each terrain node, I create a unique RGBA8 texture and render the normal map into it by deriving the heightmap of the previous step's temporary buffer.
The resolution of the per-patch normal map is depending on the depth level of the patch in the quadtree. At the top-most level, the map is 1024^2. For levels 1 and 2, it uses 512^2. Finally, for all other levels, the resolution is 256^2.
To maximize precision, I wanted to use lighting in tangent space, but due to various lighting artifacts and the tangent space not matching on the planet's cube faces, I ended up using object-space normal maps / lighting. It looks pretty good except on the very last depth levels ( it looks very noisy ), but I'm not sure yet if the bad lighting is coming from lack of precision in the XYZ inputs of the planet ( remember: it's using relatistic scales, and on the GPU I cannot use fp64 ), the lack of precision in the procedural heights generation, or the lack of precision in the object-space normals. Or maybe a combination of the 3...
In the coming week(s) I'll continue to try to increase the precision in the last depth levels, and reimplement diffuse texturing ( still lacking in the following pictures ).
I've finally been able to produce a decent crater noise function, based on the cell noise ( see previous journal ). Each crater has a perfectly circular shape but then is deformed by a few octaves of fBm, to make it more natural. In the following pics, I'm combining some fractals for the land base and 3 octaves of crater noise. I'm still not 100% happy with it though, as I think the craters's distribution is too uniform, so I will probably continue to play with it a bit.
For the fun, here's the final procedural function that generates all the pics in this journal:
float height(in vec3 world)
float land = gpuFbm3D(6, world * 2.0, 2.0, 0.7);
float land2 = gpuMultiFractal3D(16, world * 5.18, 0.8, 2.0, 0.05) * 0.5 - 2.5;
land = (land + land2 * 0.5) * 4.0;
float n0 = gpuFbm3D(10, world * 8.0, 2.5, 0.5) * 0.05;
vec2 c0 = gpuCellCrater3DB((world + n0 * 2.0) * (4.0 + n0 * 16.0) * vec3(1, 1, 1), 3.0, 0.5);
land += c0.x * 3.0;
c0 = gpuCellCrater3DB((world + n0 * 1.0) * (16.0 + n0 * 1.0) * vec3(1, 1, 1), 3.0, 0.5);
land += c0.x * 2.0;
c0 = gpuCellCrater3DB((world + n0 * 0.5) * (64.0 + n0 * 1.0) * vec3(1, 1, 1), 3.0, 0.5);
land += c0.x * 1.0;
return land + 1.0;