another question -- I want to draw a voxelized model, ie an object made of thousands of tiny cubes. Is it necessary to pass the cube vertex information (translated by the cube position) to the renderer thousands of times? Isn't there any way of using shaders so that I only need pass the cube information once, then pass arrays of positions and colors for all the cubes?
From reading about OpenGLES 2.0 I can't see a way to do it. Is it not possible? (though it seems like OpengGLES 3.0 will offer that ability).
And even to draw a single cube, do I really have to pass 36 vertices instead of 8? Because each vertex seemingly is associated with only one normal, you've got to pass the same vertex in three times, once for each face it is part of. That's so inefficient! How do programs like Minecraft, with thousands upon thousands of cubes, do it? Is there some way they get around having to pass all that vertex information?
I'm not 100% sure about OpenGL ES, but long story short, when it comes to voxel engines, you most likely will be using VBOs or display lists, where you load the cubes all at once into GPU memory and let it do the rendering.
With vertex arrays and, by extension, VBOs, you pass the vertices all at once, then pass an index array that refers to the vertices you need, or if you use display lists, you can package all your commands for faster rendering.
As for Minecraft... it's programmed in Java using the LWJGL (LightWeight Java Game Library), which is a layer on top of JOGL, the Java OpenGL binding.
Minecraft handles the "thousands upon thousands of cubes" by loading only a few "chunks" (16x16x256 groups of blocks) at a time. If I remember correctly, each chunk is compiled into a display list and rendered. Display lists in particular must be compiled each time they are modified, but since the maximum range you can reach in that game is about 5 blocks, it only needs to worry about the chunks nearest the player.
All in all, voxel engines tend not to have that many vertices in total, if you take into account optimizations for non-visible voxels.
EDIT: After thinking about it for a bit, I felt I needed to point out that Minecraft is not particularly efficient, as far as voxel engines go. There are many optimizations one could make, but as with anything, the amount of time and effort required needs to be weighed against the benefits.
EDIT2: I mistakenly brought up immediate mode, something that was not included in OpenGL ES; removed to avoid confusion.
Last edited by Aestivae; 12-06-2012 at 06:53 PM.
I'm using VBO's already, but it is still a lot of (basically) unnecessary information to be loading. I was just wondering if there was a better way. And even though you can use indices, you can't really take much advantage of any savings there, because like I said, each vertex must be repeated three times because of the three differently-facing normals needed.
I don't understand about your Minecraft comment? Even though you can only change things maybe 5 blocks away,you still have to render that entire scene, everything you can see?
Basically I am just not seeing that great performance even when loading everything in as a display list -- I was just thinking there must be some optimizations that could be made due to the repeated geometry of the cubes.
As long as you are drawing polygons, you will always be sending the same number of vertices to the GPU anyway. The only thing a VBO or display list does is shift that responsibility to the GPU so the CPU doesn't have to work on it (also avoiding the bus transfer bottleneck).You can't get much faster in terms of raw OpenGL, so you should consider algorithms that will reduce the amount of polygons considered (removing hidden surfaces, etc.).
When you draw a thousand blocks, no matter whether the CPU or GPU does it, you draw a thousand blocks. Even if those blocks are not visible, the GPU still does the calculations, but then does tests and decides not to draw them, wasting computing time.
What I meant with my "5 blocks" comment was just that the display lists don't have to be recompiled very often, so the bus traffic and CPU usage is low.
EDIT: I find I keep thinking of things just right after posting...
One of the things Minecraft does to speed things up is by running an algorithm that marks only faces that are exposed to air for rendering. This is why (if you're familiar with the game) when you build a wall of glass blocks several blocks thick, you only see the outermost layer of blocks, despite the transparency of glass blocks.
Last edited by Aestivae; 12-07-2012 at 07:01 AM.
Someone published a nice tutorial on how to make a voxel engine: