Generated sphere surface texturing

4096x4096 cube-map texture

Hello guys,
I’m not a native English speaker so please excuse my grammar mistakes - I hope my sentences will be at least understandable :)) I’m programming in Python for quite a while but I’m fairly new in 3D programming and Panda3D. My ultimate goal is RTS game but for now I’m struggling with basics :)) The surface for the game should be procedurally generated planet which can be zoomed in/out as needed and obviously it should be without significant performance trade-offs.
So far I’ve got my head around procedurally generated sphere from icosahedron adding vertices such way that I can create several LOD models out of one vertex data array.
Because I would like the planet’s surface to look more natural than Perlin noise can provide, I tried the approach with tectonic plates and simulated collisions calculation, etc. After a lot of tweaking I was able to get more or less satisfactory results.
Then I was playing with texturing and hopefully figured out correct use of diffuse, normal, height and gloss maps, and properly calculated normals, tangents and bitangents.
My trouble now is that I need to texture the created planet based on some surface conditions and to apply different texture for mountains, beaches, forests, and so on.
I’ve tried several approaches but so far nothing was really working for me:

  1. simple UV mapping on triangles
    -> big texture deformation on many places
    -> in some places problem with seaming
    -> problem with different textures per triangle (necessary too many geom nodes)
    -> does not require high resolution textures

  2. using one texture wrapping whole planet
    -> big deformation on poles of the planet
    -> bigger tiles near equator and smaller tiles closer to poles (too complicated texture generation which would mitigate the deformation issues)
    -> needs high resolution texture

  3. using cube mapping
    -> smallest deformation
    -> smallest seaming issues
    -> needs high resolution textures and uses a lot of memory

Additionally I was thinking to replace my vertex calculations by simple 16-bit height map generation which would be applied in cube map (I do not know if this would achieve the effect I hope for). Here I hit the out of memory error (I guess the limit of GPU memory 4GB) for 8192x8192 16-bit normal&height mip-map texture (6x for cube map).
At this point I’m running out of ideas and I would like to ask some advice from you, more experienced fellow developers. Do you have experience with this kind of issues and do you know about some good solution? What would you recommend me to try?

Hello fellow procedural planet aficionado :slight_smile:

When it comes to procedurally generated surfaces, you have two major techniques :

  • Generate all the map on the fly using shaders
  • Generate all the map textures on demand (on CPU or GPU with a dedicated shader) and apply the texture on the relevant geom patch.

Using a global texture for a whole planet is not recommended, if you want to zoom

The former requires the surface to be calculated each frame again and again, but you can use any geometry you want and apply more complex lod and seaming algorithm. (Modern GPU have enough compute power to handle a dozen of perlin noise or other complex functions, but it can’t scale indefinitely ). Icosphere is well suited for that kind of rendering as it’s easy to do continuous LOD with it without complex seam fixing algorithm, though spherified cube works well too. It also easily support infinite zoom as the surface is generated only for the visible pixels and no texture is stored.

The latter have more constraints (the generated texture must match the geometry, you must have algorithm to resolve the seam between the patches, …) but you can have arbitrary complex terrain, cache the generated texture, progressively increase the complexity of the terrain and so on. Here icospheres are not well suited as you can’t easily assign one texture to a ico patch. Specified cube here are the best choice. Close zooming is also more problematic, you can’t use a global texture as you will quickly hit the maximum texture resolution. Instead you have to split your surface in patches or chunks and use a division algorithm to generate only the required textures at the needed resolution.

For the texture distortion, there is one simple trick to avoid them, generate your terrain surface using 3D noise and use spherical coordinates. Doing so you will compensate perfectly the distortion and when the texture will be applied there will be no visible distortion at all. (Though this increase the noise function complexity a lot and force you to generate the spherical coordinate for each pixel, which can increase the time spent to generate your surface, especially if you use the first solution).

Another possibility is to use a different kind of spherification algorithm for the cube to lessen the distortion at the edges, but you will still have some kind of distortion.

In Cosmonium I’m now using on demand texture generation for the surface and elevation (using a pool of render to texture buffers) and use a quad tree division algorithm coupled with frustum culling and distance culling to keep the number of patches acceptable.
I’m also using spherified cube for the planet as it is the easiest to use with square textures and the seaming algorithm is not too complex.

Here are some screenshots to illustrate how this behave :

thanks for your response and some insight to the topic. If I understand it correctly I should start to search for some literature about shaders :wink:

Is this Cosmonium your project? Nice :slight_smile: Maybe I will take some inspiration out of there :smiling_imp:

You don’t need shaders to do what you intend to do, unless you want to generate your surface, heightmap, … on the fly or really need performance.
The early version of Cosmonium used Python or C++ to generate the surfaces (though with Python it was quite slow…) Even the displacement can be done using a GeomVertexWriter or a memoryview.

I’ve just watched some tutorials on Cg shaders (in Unity) and it seems to be quite powerful. I will try some in Panda3D and see how it goes. Yea Python is not fastest and multi threading is limited there (even with numpy). Maybe shaders are not universal answer but it’s certainly quite useful tool :slight_smile: If I will be able to do mesh / texture changes on the fly then I’m quite free to do anything I need :+1: Also if I do not need to have really a sphere mesh and can generate it on the fly then I do not need to seam textures correctly everywhere - just on the visible part :slight_smile: but we will see how it goes…

I will report here when I have some news but I guess it will take me some time to play around with shaders…