Search code examples
openglpoint-clouds

glDrawArrays does not render entire point cloud


I'm trying to render huge point clouds (~150M) but OpenGL only renders part (~52M) of it. When rendering smaller datasets (<40M) everything works fine. I'm using single VBO. When using multiple VBOs, points get rendered but rendering is awfully slow, which is expected. My element has a size of 44bytes and GPU has 3GB of memory available. This should be enough for nearly ~70M points but I can render as much as 100M points with multiple VBOs. Is there any OpenGL specific limitation per VBO I'm not aware of?.

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, cloud.size() * sizeof(Point), cloud.data(), GL_STATIC_DRAW);
// lot of other code
glDrawArrays(GL_POINTS, 0, cloud.size());

Solution

  • It looks like some part of your system uses 32-bit unsigned integers to store the size of the buffers, thus passing 148M*44bytes overflows and gets converted to about 54.9M or 50.4M depending on whether your megabytes are binary or decimal. I'd start with checking your OpenGL binding library to see that the prototypes it declares correctly use 64-bit types. If it does then the bug must be in the OpenGL drivers.

    To transfer more than 4GB data to the buffer you may try using one of the other available functions: glBufferSubData and glBufferStorage, or memory-map the buffer with glMapBufferRange, which might workaround the limitation of 4GB.

    Another thing to consider is to use one VAO but split the data between multiple buffers. Presumably your Point consists of different attributes, like position, color, etc... You can put each of them in a separate buffer and still use one VAO and one draw call. You can also optimize the types of the attributes you use (e.g. don't use floats where shorts or bytes would do) and the layout of the structure (check that there's no unnecessary padding between the fields).