Thursday, November 8, 2018

c++ - Which is the best LOD method for planet rendering?


I'm currently working on my thesis, it is an engine to render terrains of planetary size.



I'm still finishing my research and I have encountered a lot of stuff about this subject, the problem is that I can't decide on which Level of Detail (LOD) method I should use.


I know about geomipmapping, geometry clipmaps (GPU) and chunked LOD by Ulrich that work good on large terrains and can be used to render 6 faces of a cube and then "spherify" the cube by this method and I understand how to implement all of these methods on GPU using C++/OpenGL/GLSL (using methods like ROAM or any other method that doesn't use a cube is out of my reach because of texturing is a pain). Also I recently got into a tutorial of rendering terrains using tessellation shaders here


So, I don't have the time to implement ALL the methods and see which one is the best and more suitable for a planetary scale and I'm asking here to see if someone has made this kind of comparison and help me decide which method should I implement and use (my tutor is kind of crazy and wants me to do something with an icosahedron, but I can't understand that method unless using ROAM)


Anyways, if you can help me decide or have any other suggestion or method I really will appreciate. One condition is that the method should be able to implement GPU side (at least most of it) to prevent CPU bottleneck.


Another request is that I know there are numerical problems about precision with floats when getting a lot of detail in the terrain, I don't know how to solve it, I read a solution in a forum but can't get to understand how to implement, I lost track of that thread and I would like to know how to solve this precision problem.


I'm currently reading about some matrix transformations to solve the float precision, z-fighting issues, frustum culling with dynamic z-values, and data representation for chunks (using patch space with floats and its position in the world coordinates as double) so I think I can solve the precision problem easily. I still need a comparison between LOD methods with your opinions and suggestions to decide which is better for this project. Take in count difficulty of implementation vs visual quality vs performance, I want the best.


Something I forgot to mention is that the generation is hybrid, I mean, I should be able to render the planet entirely using GPU (heights calculated on the fly) and/or using a base height-map image and add details with GPU (vertex shader). Texturing will be a side part I will trouble latter, right now I'm happy using just colors depending on the height, or maybe using some kind of noise texture generated on the fragment shader.



Answer



Finally, after a lot of researching I can conclude that, as some one said before, There is not universally "best" method. But my research led me to the knowledge of the following things:


Depending on the mesh you will finally use:




  • Spherified Cube: any LOD method with quadtree implementation will work just fine, you just have to take care on special cases like borders between faces, in wich case, your quadtree has to have a pointer to the neighbor in the adyacent face in each level.

  • Any other: I think that ROAM (newer version 2.0 or any other extension as BDAM, CABTT or RUSTIC) will do well, however, these algorithms are hard to work with, require more memory and are a bit slower than other aproaches with cubes.


There are many LOD methods that can fit well, but my personal top 5 are:



  1. Continous Distance-Dependent LOD (CDLOD)

  2. GPU Based Geomety Clipmaps (GPUGCM)

  3. Chunked LOD

  4. Rendering Terrains with OpenGL GPU Tessellation (Book: OpenGL Insight, Chapter 10)


  5. Geometrical MipMapping


Each one offers an unique way to render terrains, for example, CDLOD has a very easy implementation using shaders (GLSL or HLSL) but is also capable to be implemented on CPU (for legacy hardware) however the goal on Planet Rendering is to explode the best on moderns GPUs, so GPUGCM is the best when you want to squeeze your GPU. They both work very well with data-based, procedural or mixed (terrain based on fixed data or heightmaps and detail added with procedural work) rendering of large terrains.


Also Spherical extension to the basic Geometrical Clipmaps method exists but has some problems because the planar samples of the heightmap has to be parametrized using spherical coordinates.


Chunked LOD, in the other hand, is perfect for legacy hardware, doesn't need any GPU side calculations to work, it's perfect for large datasets but can't handle procedural data in real time (maybe with some modifications, it could)


Using Tessellation shaders is another technique, very new, since OpenGL 4.x came out, in my opinion it could be the best, but, we are talking about Planet Rendering, we encounter a problem that other methods can handle very easy and it is about precision.


Unless you only want your precision to be 1Km between verticies, go for Tessellation shaders. The problem with really big terrains with this method is that jitter is kind of hard to solve (or at least for me, since I'm new to tessellation shaders).


Geomipmapping is a great technique, takes advantage of the quadtree and has a low projected pixel error, but, for planetary rendering you will need to set at least 16+ levels of details, that means you will need (for stitching pourposes) some extra patches to connect different levels and take care of your neighbor's level, this can be tedious to solve, especially using 6 terrain faces.


There is another method, very particular in its own: "Projective Grid Mapping for Planetary Terrain" excellent for visualization, but has its disadvantages, if you want to know more, go to the link.


Problems:





  • Jitter: Most of today’s GPUs support only 32-bit floating-point values, which does not provide enough precision for manipulating large positions in planetary scale terrains. Jitter occurs when the viewer zooms in and rotates or moves, then the polygons start to bounce back and forth.


    The best solution for this is to use "Rendering Relative to Eye Using the GPU" method. This method is described in the book "3D Engine Design for Virtual Globes" (I'm sure you can find it on the internet aswell) in where basically you have to set all your positions with doubles on CPU (patches, clipmaps, objects, frustrum, camera, etc) and then MV is centered around the viewer by setting its translation to (0, 0, 0)T and the doubles are encoded in a fixed-point representation using the fraction (mantissa) bits of two floats, low and high by some method (read about Using Ohlarik’s implementation and The DSFUN90 Fortran library).


    Although the vertex shader requires only an additional two subtractions and one addition, GPU RTE doubles the amount of vertex buffer memory required for positions. This doesn’t necessarily double the memory requirements unless only positions are stored.




  • Depth Buffer Precision: Z-fighting. As we are rendering very large terrains, in this case: planets, the Z-buffer has to be HUGE, but it doesn't matter wich values you set for znear and zfar, there will always be problems.


    As the Z-buffer depends on a float point interval, and also it is linear (although perspective projection is non linear) values near the eye suffer from Z-fighting because the lack of precision 32-bit floats have.


    The best way to solve this problem is to use a "Logarithmic Depth Buffer" http://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html



    A logarithmic depth buffer improves depth buffer precision for distant objects by using a logarithmic distribution for zscreen. It trades precision for close objects for precision for distant objects. Since we are rendering with a LOD method, far objects require less precision because they have less triangles.




Something important to mention is that all the methods listed (except for the projective grid) are very good when doing physics (collisions mostly) because of the Quadtree base, that is something mandatory if you plan to make a game.


In conclusion, just check all the options available and go for the one you feel more confortable, in my opinion CDLOD does a great work. Don't forget to solve the jitter and Z-buffer problems, and most important: have fun making it!


For more information about LOD check this link.


For a complete demostration about spherifying a cube check this link.


For a better explanation about solving jittering and Z-Buffer precisions, check this book.


I hope you find this little review useful.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...