Use VBO for vertex+indices, not tex coords?

Started by
23 comments, last by Kaptein 13 years, 1 month ago
Okay. So what do you gentlemen suggest I do? My ultimate goal is to render a 100x100x100 area. Should I list each vertex on each cube 3 times, and texture coordinates for each vertex, and then use indices for both? Do you think that makes the most sense performance wise, taking into account my completely self-taught beginner knowledge with OpenGL and graphics programming?

Using that, here's a breakdown on the amount of memory I'd be using:

Cubes: 100x100x100 = 1,000,000
Vertices per cube = 24
Position coordinates per vertex = 3
Texture coordinates per vertex = 2
Bytes per position coordinate = 2
Bytes per texture coordinate = 2

Total memory used = 1,000,000 * 24 * (3*2 + 2*2) = 240,000,000 bytes = 228.88 megabytes

Is that too much? I guess I wouldn't really need to worry about rendering anything else. What happens if you try to push 228.88 mb to a gpu, and it's only a 128gb card, or they don't have a gpu?

Any other thoughts or advice?
Advertisement
I think the best thing you can do is just throw out there what you can and see what happens. If its too slow, come back and tweak, try new algorithms, invent new paging systems. You're a beginner, you won't be able to see all the angles and pitfalls from the beginning, and you're not going to design a perfect system from scratch. Your learning and experience will come from pushing up against boundaries, getting an intuition for what can and cannot be done, and coming up with solutions for problems that you run into.

Also, your estimate seems high by a factor of 2x. If your values max out at 100, than you only need one byte per "value", not 2.

What happens if you try to push 228.88 mb to a gpu, and it's only a 128gb card, or they don't have a gpu?[/quote]

If you have more data for the gpu than it can hold, the driver pages memory in and out from system memory as needed.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
Can you use a single byte for position coordinates and texture coordinates without using shaders? Hodgman said earlier that you need to use shaders to do that (for tex coords at least). Is there any thing from just using a GLbyte type, and using GL_BYTE in the draw/load call?

That would definitely make a difference.
Probably you want GL_UNSIGNED_BYTE.

Hodgman's advice was to pack x AND y into a single byte, which requires some bit math to encode/decode two values from a single byte.

Your original statement was 3*2 bytes per vertex, so you were assuming you need 2 bytes for X, 2 for Y, and 2 for Z, while I said that x,y, and z only need one byte each, or three bytes total per vertex, instead of six.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
ninja'd
Okay. Then assuming I use one byte for texture coordinates and position coordinates, here's the adjusted math.

[color=#1C2837][size=2]Total memory used = 1,000,000 * 24 * (3*1 + 2*1) = 120,000,000 bytes = 114.44 megabytes
[color=#1C2837][size=2]

[color="#1C2837"]If anyone has any simple suggestions for performance improvements from here, that would be great. Like I said, I'm doing this as a project to learn, so I'm always looking for a "next step". I'm pretty happy with myself for understanding the differences and implementations of immediate mode, vertex arrays, display lists, and vertex buffer objects in just a few weeks.
[color="#1C2837"]

[color="#1C2837"]Thanks for all the help :)
Something to keep in mind is that you're calculating some kind of "upper limit" on your VBO size here.

Also, if the scene is minecraftesque, then not all cells inside the 100x100x100 region need to be drawn --- only the cube-faces that touch air need to be drawn (the rest can be thrown away, excluded from the VBO).

For example, if the 100x100x100 area was entirely filled in, then you'd only need to render the outside faces of the outer-most cubes (which is 100x100x6 faces, instead of 100x100x100x6 faces).
Likewise, if the 100x100x100 area was completely empty, then there's nothing to draw ;)

The worst-case scenario that I can think of would be an alternating checker-board pattern of filled/empty cells, as every cube-face would be touching air. This pattern would result in 100x100x100x6/2 faces (giving an upper limit size of ~57MB).

Also, if the scene is minecraftesque, then not all cells inside the 100x100x100 region need to be drawn --- only the cube-faces that touch air need to be drawn (the rest can be thrown away, excluded from the VBO).


Right now, I'm passing every *possible* vertex to the GPU, and leaving it there indefinitely (never touching the VBO), and simply changing my indices based on cubes being added/removed. Would you do this differently?

Right now, I'm passing every *possible* vertex to the GPU, and leaving it there indefinitely (never touching the VBO), and simply changing my indices based on cubes being added/removed. Would you do this differently?
Yeah, actually that's a good idea if the geometry can change -- having to upload another 60-200MB VBO to the card is probably something you want to avoid.

Another way to keep the size of your VBO down then, would be to make it cover a smaller area.

For example, lets say you need to draw a (2d for sake of the example) 100x100 area of blocks.
If you create a VBO that includes a 10x10 area of blocks, then you could draw this small VBO 100 times in order to cover the full 100x100 area (each time you draw it, you set a different model matrix to offset it to a different position).
Each time you draw the "small" VBO, you can use a different index buffer that contains the right indices for that particular "sub area".

This way you've got a small VBO, but also have many IBOs (one for each 10x10 area).
Also, if your VBO has less than 65k verts in it, then you can use 16-bit indices, instead of 32-bit indices, which halves the size of your IBOs ;)

If you create a VBO that includes a 10x10 area of blocks, then you could draw this small VBO 100 times in order to cover the full 100x100 area (each time you draw it, you set a different model matrix to offset it to a different position).


That makes sense memory-wise, but then you'd be making 100 draw calls per frame. Isn't that generally slower, although more efficient, memory-wise? I think the actual Minecraft does this with 16x16x16 blocks of cubes.

Also, right now I'm simply passing my index array in every frame, so I'm not using an IBO, I'm using an index array, right? How much time per frame should be taken up by rendering compared to the amount of time that should be taken up with other things, such as collision detection, physics, input/output, moving character, etc?

This topic is closed to new replies.

Advertisement