VBO limitations

Started by
9 comments, last by 21st Century Moose 12 years, 11 months ago
Hi all,

I new to 3D programming so I was wondering if you could help me here a little.
I wanted to create a terrain with a few million vertices using vertex buffer objects so I started reading about it, ending up with some questions.
My idea was dividing the terrain into small blocks, put each block in a VBO and then render each one using quad strips.
The problems are:
  1. Is MaxVertexIndex the size limit of a VBO (e.g. VBO[MaxVertexIndex]) or is it the greater index of a vertex that a VBO can hold (e.g. VBO = MaxVertexIndex)?
  2. Divide the terrain into blocks forces me to duplicate the vertices which belong to more than a block? (it's just to be sure because I'm almost certain of this)

I appreciate any feedback you can give me about my questions or my idea.
Thanks in advance,

Rui Barros.
Advertisement
In what function is this MaxVertexIndex?
If you use glDrawRangeElements the range specifies the valid values of the indices, not the number of indices.
Specify which language and/or wrapper you are using, if you're not using OpenGL directly.

To avoid duplication you could create one very large vertex buffer that contains all few million vertices, and then use separate index buffers to draw different parts. You might even get away with a single index buffer and separate start indices if you draw with glDrawElementsBaseVertex.
[color="#1C2837"]
MaxVertexIndex is a cap limit of the graphic cards (mine is 2[sup]16 [/sup]= 65536). I've read some posts about it but I'm not completely enlightened.
[color="#1C2837"]The only reason to divide the terrain is this limitation and not a personal option, in fact I wish I could just do it in a single VBO.

Note: I'm using OpenGL with glut and c/c++.
Using quad strips is generally a bad idea as they're not supported natively in hardware; the driver will need to decompose them to triangles before it can do anything with them. Depending on your use case (and target hardware) this may or may not add additional overhead, which may or may not be significant. (Just because something is supported by the API doesn't mean that it's supported in the hardware...)

In order to avoid vertex duplication you need to use indexes. Indexes are also important in that they will allow your hardware's vertex caches to actually work, which can gain a lot of performance in the vertex transformation stage. This is going to be critical for the vertex count you're aiming for.

At this stage it boils down to two choices: indexed triangles or indexed triangle strips. The differences are that indexed triangles have less setup overhead and can be used to represent any arbitrary geometry, whereas strips have constraints (less so with primitive restart, admittedly).

Because this is new to you I'm going to recommend that you back off a little and try something simpler. Your plans are somewhat ambitious right now, which introduces more scope for things to go wrong. Try building some simpler "rotating cube" applications to get comfortable with the API calls and concepts first, then dive into the real stuff.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

I'm aware that VBO is an advanced topic and I would take it slowly if I could but this is an university project.mellow.gif And just to clarify, when I say I'm new to 3D programming I mean I've been doing it for 2 months so I'm already quite comfortable with the basis of OpenGL.
I don't have to do anything too complex, but still I must use VBO so I was trying to find a simplistic use of it. I already tried it with small things (using an array of vertices and an array of indices). The problem is when it comes to things that might exceed the buffer cap. My main difficulty is finding out how buffers are limited when it comes to size.

In this case strips are enough because it's a simple square terrain but thanks for the triangle strip tip.

[color="#1C2837"]
MaxVertexIndex is a cap limit of the graphic cards (mine is 2[sup]16 [/sup]= 65536). I've read some posts about it but I'm not completely enlightened.
[color="#1C2837"]The only reason to divide the terrain is this limitation and not a personal option, in fact I wish I could just do it in a single VBO.

Note: I'm using OpenGL with glut and c/c++.


The documentation for glDrawElements states the following:

Implementations denote recommended maximum amounts of vertex and index data, which may be queried by calling glGet with argument GL_MAX_ELEMENTS_VERTICES and GL_MAX_ELEMENTS_INDICES. If end - start + 1 is greater than the value of GL_MAX_ELEMENTS_VERTICES, or if count is greater than the value of GL_MAX_ELEMENTS_INDICES, then the call may operate at reduced performance.[/quote]

So depending on which one of those constants returns 65536 it specifies either the recommended max 'count' or the size of the vertex range. I don't think there's any actual limit, though your buffer creation could fail if you try to make it too big, so check error values. Where do you get that MaxVertexIndex from?
It probably means the maximum integer value of an index.
Thanks Erik, I think that is exactly what I need.
[color="#1C2837"]As far as I realized MaxVertexIndex is a graphic cards' limitation and I checked mine using DirectX Caps Viewer that comes with D3D9 SDK.
[color="#1C2837"]
[color="#1C2837"]
[color="#1C2837"]
[color="#1C2837"]Note: In case anyone wants to check, the MaxVertexIndex value is under Direct3D9 Devices -> [yours graphic card name] -> D3D Devices Types -> HAL -> Caps
[color="#1C2837"]
[color="#1C2837"]PS: Maybe this is just a D3D limitation but as I found this in OGL posts I felt the need to ask
In general any such limitation should come from the hardware rather than from the API. The API is only a layer between your program and the hardware, the hardware itself calls the shots, and if hardware isn't able to do X then no amount of software can change that fact.

The limits given for glDrawElements are actually for glDrawRangeElements. There is a difference, but I'm suspicious. glDrawElements is an old old old function, dating back to OpenGL 1.1, and predating hardware T&L cards. With that in mind I'd be inclined towards caution and towards saying that they should also apply to glDrawElements - again on the basis that if the hardware can't do it, then there's no special magic in software that can change that.

In D3D these are absolute limits; if you exceed them your program will fail in lots of potentially exciting ways. In OpenGL they're just recommended limits; OpenGL itself doesn't define what happens if you exceed them. In most cases what actually happens is that your vertex pipeline will fall back to software emulation, which more or less wipes out the advantages of both VBOs and hardware T&L. In other words you probably don't want to exceed them.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.


The problem is when it comes to things that might exceed the buffer cap. My main difficulty is finding out how buffers are limited when it comes to size.


http://www.opengl.org/wiki/VBO_-_more

As for GL_MAX_ELEMENTS_INDICES and GL_MAX_ELEMENTS_VERTICES, these are for glDrawRangeElements (and theoretically glDrawElements). In other words, you may have to make multiple calls to glDrawElements to render your model.
GL_MAX_ELEMENTS_INDICES and GL_MAX_ELEMENTS_VERTICES has nothing to do with VBO size. Read the spec file if you want. http://www.opengl.org/documentation/specs

As for 65536, this would be 2^16. This is about indices. Older graphic cards prefered GLushort for indices rather than GLuint. I don't know about these days. I think AMD doesn't have a problem with 32 bit while nVidia still prefers 16 bit.

It is recommended to always use GL_TRIANGLES.
Not triangle_strips.
Not triangle_fans.
Not quads.
Not polygons.

PS: and yes, you can allocate a huge VBO (like 4 MB) and store your entire terrain in it. A huge IBO. Render it with many calls to glDrawRangeElement.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
I think I can manage it from here, thanks everyone.

PS: V-man, 4MB is not quite enough to hold all the terrain's data, there are 4million vertices with 3 components each which makes 12million floats (over 45MB) just for the coordinates. mellow.gif

Thanks all for the intel once again

This topic is closed to new replies.

Advertisement