Jump to content
  • Advertisement
Sign in to follow this  
toss-dev

LOD on a (cubical) voxel engine

This topic is 925 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, I'm optimizing my voxel engine rendering

I have implemented a 'greedy meshing' algorythm, and optimized the culling, which diubles my rendering performances. But still, this model doednt scale well, and I can't reach good enough performances while rendering with a high render distance

So I naturally was thinking of implementing a level of details meshing algorythm for my terrains

At first, I was thinking of using heightmaps with a decreasing precision (number of vertices depending on the terrain distance).
But as I am in a voxel world, I think the final result can look pretty ugly in some cases. (The height can be infinite, they can be 'floating terrains in the air', 'holes' in a moutains, these would lead to pretty brutal transition while changing from the heightmap to the standart mesh)

So I was thinking of implementing the marching cubes algorithm

What do you think about it? Do you have any advices / good links to give me on that topic? Am I missing a simpler solution?


Thank you for your reading

https://github.com/rpereira-dev/VoxelEngine

 

 

EDIT: 1 year later, I finally ended up implementing the marching cubes algorithm: 

 

Edited by toss-dev

Share this post


Link to post
Share on other sites
Advertisement

I fiddled with GPU-generated marching cubes not long ago, and had issues with color bleeding. Some polygons in a marching cube can belong to the neighbouring voxels, and thus bleeds the voxel color to surrounding voxels... Gave it up eventually :/

 

LOD with voxel terrains are not easy to solve and keep managable IMO, you have to stitch different LOD chunks together so there's no gaps, and that can result in a whole lot of headaches when terrain is updated etc..

Edited by vinterberg

Share this post


Link to post
Share on other sites

Even minecraft had some problems with this. Though there are some ways to speed it up. I have no idea what notch did, because just about every polygon is detached from each other.


1st method is better for all geometry that's closer to the user, though it can also work pretty well in the back. I see that you're already doing this so it's a moot point. However, it may be worth while to not stuff the entire chunk of terrain into a VAO buffer. You need to think about whats going on in the side lines.

Assuming you do have a texture atlas, you can reduce the number of times that the game needs to change the location of a UV. In fact, it's pretty common for a large amount of faes of the same type to be aligned together. Collect those faces that are in one contigious blob, batch them together (or instance, one or the other may be faster) and then send them to the GPU. Instancing might be better in this case.

From the looks of things, minecraft does not exactly use anything more than a frustrum culling algorithm, and draw the most visible face (Pretty much back face culling ontop of a Convex hull).

2nd Method, for more distant geometry, Combine and simplify the mesh of all simple rectangular regions of the SAME face type.

Still... I don't think the problem is the renderer. Minecraft had some shitty optimizations but it's performant.

Share this post


Link to post
Share on other sites
Hey thank you for your answer

The 'greedy meshing algorithm' I mentioned already combine faces with the same apparence (texture, lightning...) to a single quad :)

Also, I explored minecraft code: I didn't find anything to deal with LOD :(
However, they're not using a simple frustum culling algorythm! A Mojang dev wrote this article: https://tomcc.github.io/2014/08/31/visibility-1.html
I implemented mine based on this

But y, I think the best looking way would be to join distant chunks mesh, and simplify it. However I need to find a fast enough algorythm to do it in real time, because this would mean keeping far distant terrain's informations in memory... and so maybe to dynamically compress / decompress blocks data, which will slow down the whole process

This is why I also like the heightmap solution, as it is more 'memory-friendly'

Thank you for your interest

Share this post


Link to post
Share on other sites

You could use the heightmap, and write code to detect which chunks dont work well (overhangs, complex shapes...). Then either use a more expensive approximation for those (like proper 3D model), or enable the heightmap approximation later.

 

For example, imagine a heightmap, with a cliff of more detailed voxels blended in sitting in the middle (because they were deemed unfit for heightmap, and will be optimized at further distance only)

 

If such things are not the common case, you might be able to afford more expensive approach for those special cases.

 

 

Also, if theres known terrain features, like voxel trees, or houses, you could filter those out of the heightmap, and draw them separately as voxels or as billboard. I guess those can even be automatically detected with relative ease (as theyll be different materials, and probably hollow too...)

 

Or maybe you can just render the chunks into billboards from players current position, but that means you have to probably load them (maybe you can save minified version of each chunk, just enough data for this task, eg only save block colors for visible surfaces). Also means player cant move too fast or youll be updating those billboards too often for this to work. And lighting/shadows could be tricky if you dont use the minecraft style ones.

 

Also consider adding some visual effects to hide errors in the distant chunks, like fog, clouds, blur (from the atmosphere... a really blurry atmosphere). Maybe at a certain distance, the terrain is just a single color, so player can just see the skyline.

Share this post


Link to post
Share on other sites

One option that is an alternative to dealing with mesh LOD is to hybridize and use a combination of polygonal rendering for near terrain and actual voxel rendering for distant terrain.

 

 

Since your terrain is already made of cubes, it will be harder to notice a difference on the boundary.

Share this post


Link to post
Share on other sites


But y, I think the best looking way would be to join distant chunks mesh, and simplify it. However I need to find a fast enough algorythm to do it in real time, because this would mean keeping far distant terrain's informations in memory... and so maybe to dynamically compress / decompress blocks data, which will slow down the whole process

I browsed your code, and it doesn't look like you're storing terrain in an octree? An octree would make it simpler to mesh distant terrains together and use mesh optimizations over this bigger mesh. You don't need to calculate this at every frame, cache it in the octree node - only when a surface block is changed do you need to change this mesh.

 

Share this post


Link to post
Share on other sites
My terrain are in a hashmap (key is a vector 3 integer world index), but every terrain also has an array holding it neighbor-terrain for each face (see Terrain.java) (so it's actually more like a ... six-tree?)

Thank you for your answer guys

I didn't know about sparse voxel octree, I'm giving it a look

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!