3

I'm rendering a grid-structure with lots of data-points (>1M). The structure of my data is in the picture.

Structure of data-points

So the content of my index buffer looks like this 0, 100, 1, 101, 2, 102, 3, 103, ...

I'm a bit annoyed by the huge size of my index-buffer which I need to define my triangle strip. Is there a possibility to tell OpenGL to generate these indices automatically in the showed way? Or maybe some trick with glVertexAttribPointer I haven't though of?

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
freakinpenguin
  • 831
  • 14
  • 24
  • shouldn't it start at 0 (or loop back to 101) – ratchet freak Nov 05 '14 at 10:51
  • 1
    not that I'm aware of. you could use `glDrawArrays` without any bound attributes and read your vertex data from a sampler or image (`texelFetch`/`imageLoad`), indexed with `gl_VertexID`. It might be slower due to pulling data and cache misses, but can't be certain. – jozxyqk Nov 05 '14 at 11:01
  • @ratchetfreak: You are right. It should start with 0! – freakinpenguin Nov 05 '14 at 11:30

2 Answers2

3

There is indeed a function for something like this: glDrawElementsBaseVertex

so you can draw them all with:

for(int i=0; i < height-1; i++){
    glDrawElementsBaseVertex(GL_TRIANGLE_STRIP, 200, GL_UNSIGNED_INT, 0, i*100);
}

the index buffer is then just: 0, 100, 1, 101, 2, 102, 3, 103,... 98, 198, 99, 199

With some tweaking you can even use glMultiDrawElementsBaseVertex:

GLsizei *count = new GLsizei[height-1];
GLvoid **indices = new GLvoid[height-1];
GLint *basevertex​ = new GLint[height-1];
for(int i = 0; i< height-1; i++){
    count[i]=200;
    indices[i]=0;
    basevertex​[i]=i*100;
}
glMultiDrawElementsBaseVertex(GL_TRIANGLE_STRIP, count, indices, height-1, basevertex​);
ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • Isn't the question about generating the indices as opposed to rendering what's in the element array buffer? – legends2k Nov 05 '14 at 12:22
  • @legends2k it's (between the lines) about reducing the size of the element array buffer which this solution allows. There's a bit of a X-Y problem when you include the last paragraph of the OP. – ratchet freak Nov 05 '14 at 12:24
  • Aah, I see it now. Generate just the indices for one row and reuse it for all the rest of the rows. Anyway, I'm the one who +1'd this answer, since I liked the solution even otherwise before commenting. – legends2k Nov 05 '14 at 12:34
  • 1
    @ratchetfreak: Hmm, that's an interesting approach. But I still have some concerns about the increase of the GL-calls. 1000-gl-calls more per drawing is a lot of work for the cpu... – freakinpenguin Nov 05 '14 at 15:06
  • @ThomasSpranger that's why I added the `glMultiDrawElementsBaseVertex` variant, and nothing is stopping you from increasing up the indexbuffer so 2 or more lines are drawn at once – ratchet freak Nov 05 '14 at 15:11
  • @ratchetfreak: Ok, now I got it. Cool idea, much better than the current, but I still have some concerns (sorry ;)): With glMultiDrawElementsBaseVertex I'll have to copy the complete arrays on each draw-call. So there would be 3 arrays with 1000 elements to copy on every frame. Or am I wrong? – freakinpenguin Nov 05 '14 at 16:06
  • @ThomasSpranger you can pre-generate them and hold them statically, if you look carefully you'll see that they don't need to change at all between frames – ratchet freak Nov 05 '14 at 16:09
  • 1
    @ratchetfreak: Sure, but I'll have to send them to the graphicscard on every frame. I don't think I can use a buffer for these...? – freakinpenguin Nov 05 '14 at 16:09
  • @ThomasSpranger still better than calling `glDrawElementsBaseVertex` 1000 times, honestly try to get a happy medium between index buffer size and the size of the arrays. – ratchet freak Nov 05 '14 at 16:13
  • @ratchetfreak: Ok, I think that's definitely better than the previous solution. Thanks a lot for your help! – freakinpenguin Nov 05 '14 at 16:17
  • 2
    @ThomasSpranger: there is also [`glMultiDrawElementsIndirect()`](https://www.opengl.org/wiki/GLAPI/glMultiDrawElementsIndirect) from [`GL_ARB_multi_draw_indirect`](https://www.opengl.org/registry/specs/ARB/multi_draw_indirect.txt) which allows you to put those arrays into a buffer object and to further reduce CPU overhead with this approach. – derhass Nov 05 '14 at 19:34
1

The best solution I was able to find is to use glMultiDrawElementsIndirect. The buffer size is lots of smaller than the original one and you can pass all draw-commands with one gl-call. Thanks to derhass for the hint!

freakinpenguin
  • 831
  • 14
  • 24