First of all, I want to say great job with Outerra! It's one of the best, if not the best 'planet engine' out there.
It's been a dream of mine to make a procedural planet for the web. At least something that allows me to build a simple game. I successfully created a very simple procedural planet in ActionScript 3.0 by using a lot of AGAL shader magic. Writing shaders in a low level language was painful, so I moved to WebGL. Thankfully WebGL supports GLSL, which is like a dream compared to AGAL.
Anyway, to the point! I've seen a few threads in this forum where people discuss technical issues with their planet engines, and you've given some really good answers, cameni. I'm amazed that you even have time to answer these questions!
There are few things that caught my attention that I would like to ask you about.
First questionIn OT the individual cube face coordinates u,v (in range -1..1) are mapped to the sphere by normalization of vectors made from <u, v, ±k> set (order depends on the face), where k is:
k = 1 + 0.2071067812 (1 - u²)(1 - v²)
With 0.2071067812 ~= 0.5/(sqrt(2) - 1) - 1, which is creating most regularly sized tiles.
Most people are using an algorithm from Philip Nowell to map a cube to sphere -
http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html As you described, your method gives more regular result. After briefly looking at both of the algorithms, it seems like your algorithm could also perform better. Especially if you can pre-calculate the sqrt.
I'm also curious if you've implemented a sphere to cube mapping version of your algorithm, and are you willing to share the solution if you did?
I think most people would move to your solution if one created a good example on how to use it. You'll be the next John Carmack!
Second questionProcedural noise. I've been thinking about this topic way too much. I'm never satisfied with the performance. I've tried both Perlin and Simplex noise, all of them take some time. Currently I'm using Simplex noise in the GPU to generate heightmap. Eventually this data needs to be moved to the CPU for calculating the collision and other things. JavaScript/WebGL is not quite there yet, but sooner or later it'll support threads and other cool things such as WebAssembly.
Again, to the point, I'm pretty sure I could improve the performance many times by re-thinking how the heightmap is generated and re-using resources.
The main issue that I'm running into is that I'm using about 10-14 octaves to have the terrain more interesting when the camera is close to the surface of the planet. For each quadtree node/patch I'm generating a 1024x1024 heightmap. When that node is split, each children will generate a 1024x1024 heightmap, and so on. I'm not re-using the heightmap from the parent, and I'm pretty sure that could be a game changer in terms of performance.
Now, my question. Could I reduce the number of octaves if I somehow re-used the noise or heightmap from the parent? If so, how exactly would I do that? I can't think of any 'seamless' method.
I've also been wondering if it's possible to use a fractal algorithm like mandelbrot. It repeats interesting patterns as you zoom in, and is super fast, but has repeating patterns that could be hidden with combination of other algorithms. Do you know if there has been any attempt to use fractal algorithms to generate a terrain?
Yet another thought, using 2D noise instead of 3D noise. I assume this would probably improve the performance slightly (I haven't measured the speed difference yet).
Absolute value of face coordinates summed (give the same number on the edges), and inherited height from parent (it's the same on the face edges as well) to break the patterns.
As I understand it I could use some tricks to make the noise seamless between cube faces, though there would always be some seam that would be visible, or at least a break in the pattern. I would like to simply ask, would you say it's worth changing to 2D noise for the added performance?
And the last... question. I promise! (for now).Faces are indexed using signed 32b integers from -2^30 to +2^30, leaving space for overflows.
I think integers can be used in case of Perlin as well, by computing auxiliary coordinates first that are kind of floating with level. In each level you would shift the integer coordinates to the right by 32-8-level bits and mask out the bits above eight lowest bits. Then you compute floating-point coordinates by multiplying with 1.0/256 and pass them further on. Could that work with that algorithm?
With all kinds of coherent noise one is basically computing an interpolated value between some discrete points in space when computing the value for given level, and the coordinates just have to change twice as fast with each level.
Also, we are not using a simple GetNoiseForPosition(int x, int y, int z) function as it has many disadvantages, slowness being just one of them. We are accumulating the noise and caching it so that we can also modify the values or to use height maps for certain levels etc.
Basically it is indeed more or less like that, and we are also using a couple of techniques to speed it up - like caching the generated values at certain levels to be used as the basis for finer details, so that the more detailed levels do not have to compute all octaves of noise. The system is designed so that it can handle external data or generated noise almost transparently.
Here's an old screenshot from one of predecessors of the algorithm (from 2003), the colored profile curves seen on the right defined how various properties of noise generator changed with the level (X-axis corresponds to the level but the markings show the level size in meters instead). That version didn't handle existing terrain data, it was a pure fractal generator.
Can you share some more information on that fractal generator, was it not related to perlin noise at all? How did you solve the seams between cube faces, etc?
I know these are many questions, and some of them are very general. It would be highly appreciated if you could answer some of them!
Thank you! P.s. I promise to include some pictures and links to my WebGL planet generator.