I have a little problem. I have a lot of geometry in an Array-Buffer. ( > 10.000 triangles)
Sometimes I want to hide some of the triangles temporarily. My thought was, that its a simple thing to just overwrite the triangle data in the buffer with all zeroes.
So I would be rendering a triangle where all 3 vertices are equal.
Now, how would the performance be? I know the worst-case is “it is as much work as rendering a normal triangle”. But I would like to know if I save much by doing this.
I was thinking that the vertex shader would probably still have to run for all vertices of the triangle but the fragment shader is likely to not run at all since no fragments will be created, correct?
Is there any other good way to temporarily hide some of my geometry, am I missing something obvious?
Thank you in advance.
I believe that it’s possible that the fragment shader will be run even for a zero-area triangle. In fact, I think it’s guaranteed to happen if GL_POLYGON_SMOOTH is enabled.
If you want to dynamically hide primitives, you could use glDrawElements() with a dynamically-generated index buffer. If the sections to be shown or hidden form contiguous blocks, you could use one of the glMultiDraw* functions. Either of those approaches will avoid having the vertex shader process redundant vertices.
You can use a geometry shader to actually discard primitives based upon whatever criteria you specify (e.g. via attributes or uniforms), but that has its own performance penalty.
The most efficient solution will depend upon the details and (probably) the implementation.
Is GL_POLYGON_SMOOTH enabled by default? Because I dont enable it right now and I am curious whether I should disable it explicitely.
I am also using an Element-Array-Buffer with indices right now. But if I had to remove values somewhere from the center of the buffer I would need to shift all the other indices to fill the gap. That doesnt sound like something I am eager to do. Or is there some better way for this?
My gut feeling is that making multiple draw calls on sub-ranges of the buffer is going to be cheaper than making two updates to the buffer (once for “removing” the triangles, once for restoring them), unless you’ve got an extreme case where there are a lot of triangles you want to “remove” and they’re well-distributed through the buffer. As GClements said, using the glMultiDraw calls can be more efficient, but make sure that you benchmark as it’s not guaranteed. Another possible approach is what I call “immediate mode indexing”, using glBegin (GL_TRIANGLES), a bunch of glArrayElement calls, then glEnd (you won’t be able to do this on a core profile, of course) - that can run pretty fast too. Again, the objective is to avoid having to update that buffer, which can be a slow operation, particularly if only updating a middle-region of the buffer and if the region you’re updating is currently in use for a prior draw call.
If the order doesn’t matter, then filling gaps with values from the end of the array is likely to be quicker than shifting everything after that point. This assumes that you’re using disjoint triangles (or quads), not strips or fans.
Alternatively, enabling primitive restart and overwriting the indices of hidden vertices with the restart index might work. Having multiple consecutive occurrences of the restart index is atypical, but doesn’t appear to be explicitly prohibited.
Okay, thank you very much.