1
\$\begingroup\$

Consider an huge terrain that has a lot polygons, to render this terrain I thought of following techniques:

  • Using height-map instead of raw meshes: Yes, but I want to create a lot of caves and stuff that simply wont work with height-maps.
  • Using voxels: Yes, but I think that this would be to much since I don't even want to support changing terrain..
  • Split into multiple chunks and do some sort of LOD with the mesh: Yes, but how would I do that? Tessellation usually creates more detail not less.
  • Precompute the same mesh in lower poly version (like Mudbox does) and depending on the distance it renders one of these meshes: Graphic memory is limited and uploading only the chunks won't solve that problem since the traffic would be too high.

IMO the last one sounds really good, but imagine the following process:

  1. Upload and render the chunks depending on the current player position. [No problem]
  2. Player will walk straight forward
  3. Now we maybe have to change on of the low poly chunk with the high poly one
  4. So, Remove the low poly chunk and load the high poly chunk [Already to much traffic here, I think]

I am not very experienced in graphic programming and maybe the upper process is totally okay but somehow I think it is too much.

And how about the disk space it would require.. I think 3 kind of levels would be fine but isn't that also too much?

(I am using OpenGL but I don't think that this is important)

\$\endgroup\$
  • 3
    \$\begingroup\$ When talking about traffic, are you talking about networking? Or are you talking the CPU->GPU bus? \$\endgroup\$ – MichaelHouse Jul 4 '13 at 17:17
  • \$\begingroup\$ @Byte56 by traffic I mean the traffic between CPU->GPU \$\endgroup\$ – Aurus Jul 4 '13 at 18:12
  • 6
    \$\begingroup\$ I see. I may be misunderstanding, but you appear to be worrying about a problem you don't have (at least not yet). Pick one of your options and implement a first draft of it. Profile it if you're running into performance problems. \$\endgroup\$ – MichaelHouse Jul 4 '13 at 18:28
  • \$\begingroup\$ Implement, Test, Profile, Repeat. You will probably answer your own question, as it stands its substance is speculation, and is just begging for discussion. Seems to be another "best" question formatted differently. --- With that said, your 4th option sounds just fine, and if you are worried about bandwidth spikes because your meshes are HUGE, transfer small chunks of the most likely useful buffer every frame preemptively. \$\endgroup\$ – MickLH Sep 3 '13 at 18:28
2
\$\begingroup\$

The chunks approach is very common. Almost every large-scale outdoor terrain renderer does this. Even with voxels, you need chunks of voxels in order to properly cull and optimize the rendered scene. Spatial partitioning is vital to graphics, physics, AI, almost every part of the game, and uniform chunks are one of the easiest for outdoor scenes. More complicated approaches like quadtrees or the like work too; you'd have to profile and test to see if they improve things at all for your specific game.

Split your map into largish chunks. This typically will not produce too many new triangles as you'll only be clipping them near the edges. Now you can programatically create lower-poly versions of each chunk. Use LOD to select the right version. Use frustrum culling to completely avoid drawing chunks outside of the view frustrum. You can even use various forms of occlusion culling to hide invisible chunks in the frustrum, such as those occluded by hills or mountains.

For caves and other indoor-ish areas, consider a completely different rendering approach. You can render indoor areas using BSP trees or a portal engine very efficiently, and you can seamlessly rendering indoor/outdoor areas using two different renderers easily enough. Again, this is what almost every major game engine does. The problems are different enough that a single solution is not really a best fit.

Voxels can also work, but the looks may not be what you're going after. Smoothly rendering highly-detailed worlds with a voxel representation underneath is not a task for the feint of heart. The few engines I know that do this cheat pretty heavily at it, too. EverquestNext seems to have a pretty high-quality look with voxels underneath, but I don't know what approach they're using.

\$\endgroup\$
  • \$\begingroup\$ +1 Having worked on a very large map title, chunks as described here is exactly what we did (with a couple tweaks based on specific need). You can't go wrong breaking a big problem down into manageable pieces. \$\endgroup\$ – Patrick Hughes Nov 2 '13 at 23:49
0
\$\begingroup\$

You should use voxels. In your question you explained that you don't want to change the terrain. I guess that's not totally true. Even if you don't want to support realtime editing, there is a point where the terrain have to be created first. This might be done with an editor application and for that, a voxel representation would become very handy.

The get a smooth polygon mesh out of your voxel data, I suggest using algorithms like Marching Cubes. Before implementing such an algorithm, you could just create a mesh with cubes for each voxel, like Minecraft does, for testing.

When it comes to rendering, you should first implement a draft, as already suggested in the comments. Then improve if it truly is too slow. If so, you would have to divide the terrain. Therefore you could use chunks or octree data structure. Note that this is a must if your terrain would be infinite, which for you seems to not be the case because you spoke about a hand crafted world. By the way, reducing the view distance of chunks would significantly improve performance.

If that is still to slow, which is very unlikely I think, then you'd need an level of detail system. Provide low detail meshes for far away chunks and more detailed meshes for nearer chunks. You said that you think changing a chunk with a more detailed version would cause too much traffic to the GPU. This is not true. At some point you have to load the most detailed version which a lot of vertices anyway, right?

In other words, you already know about the needed techniques, they just had to be ordered. Additionally, I think you problem is to imagine how much data you actually have, which isn't easy. Maybe you should estimate the expected amount of data by calculation. For example, a float is sized 4 bytes (thanks to MickLH's comment). For a vertex, you need 3 floats for the position and depending on your requirements, 3 (or at least 2) floats for the normal vector and 2 for the texture coordinate. In this example case, we'd have 32 bytes per vertex.

Update: Of course there are ways to even speed this up, but I think this is too much for the start and you should consider that later and only if truly necessary. Mesh compression is your keyword then. For example, detailed smooth meshes can be stored in very small size by backwards calculating subdivision. This way, your mesh becomes a weird shape that results in the desired terrain when being heavily tessellated. This would also speed up rendering because you could cull away lot of the terrain and only tesslate data in the player's view.

\$\endgroup\$
  • \$\begingroup\$ In OpenGL a "float" is 32-bit, or 4 bytes, not 2. So the vertex size is actually 32 bytes. Although a HALF_FLOAT format would come out to 2 bytes, and could help alleviate bandwidth concerns. But IEEE 754 explicitly says 16-bit half floats are optional, and realistically not all hardware supports it. \$\endgroup\$ – MickLH Sep 3 '13 at 18:40
  • \$\begingroup\$ @MickLH Good to know. I corrected that. \$\endgroup\$ – danijar Sep 3 '13 at 19:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.