Given a fairly static voxel array, what is more efficient: using the CPU to pre-generate a VBO to render the voxel faces (ignoring more advanced forms of rendering like marching cubes for now) or using a geometry shader on the GPU to generate the faces on the fly?
I'm not that worried about updating changing voxels but of course that is a benefit of the GPU-version since you don't have to rebuild the VBOs. Also, the GS approach feels a bit more modern :)
On the other hand, I haven't looked at the details on how a GS actually works with the rasterization pipeline in modern GPUs. Does it output the vertices into a sort of stream-cache or is the vertices written to the normal GPU memory in between? If it's the latter, then on-the-fly generating could reduce the available bandwidth and processing power from the rest of the GPU tasks I guess and then it would be more beneficial to do it on the CPU..
Answer
I'm thinking of a minecraft type scene, where by voxel you mean a world of blocks that are actually rendered using polygons:
If you use a geometry shader it will be difficult to avoid having exactly three faces (or whatever) per voxel.
If you have lots of adjacent blocks that are of the same texture then you can use tiling of the textures to have much less triangles in your (degenerate) strip in a VBO approach. I mean, if there is a nice big flat 6x6 area of grass voxels, you can draw the entire top in just 2 triangles rather than 64.
With the GS approach you can't do the trivial culling of faces occluded by adjacent voxels that is very straightforward with a VBO approach either.
I have not tried the GS approach, but I can say that the VBO approach with combining of repeating adjacent tiles works very well. I found messing with element indices to be much slower than just repeating the vertices. If you split your world into nice small cubes you can typically use just one byte per component per vertice and even pack the texture info and normals (a face on an axis-aligned cube has only 3 possible normals) etc into a forth byte to make 4 bytes per vertex which is nice and fast.
I have used separate VBOs for each of the 6 faces - you only ever need to draw at most 3 of them obviously. This fits nicely with the different texturing usually used on the top-parts of minecraft-style voxels. Because for each set the normal and such is then uniform.
With use of vertically-tiled pixmaps in an atlas with GL_REPEAT
on the horizontal axis and having 90-deg rotated versions of the pixmaps in the same atlas I found I can draw massive amounts of apparently different blocks using the same VBO in the same call. In the 6x6 grass area example, I'd have split that into 12 triangles as I only have repeat on one dimension in my atlas.
I've mostly been getting this to work on the very low end of integrated graphics chips and mobile, where GS is just something I can dream about one day playing with.
No comments:
Post a Comment