10
\$\begingroup\$

OK, I understand that gl_quads are deprecated, and thus we're not 'supposed' to use them anymore. I also understand that a modern PC when running a game using gl_quads is actually drawing two triangles.

Now, I've heard because of that a game should be written using triangles instead. But I'm wondering if, due to the specifics of how OpenGL makes that quad into two triangles, it is ever advantageous to use quads still?

Specifically, I'm currently rendering many unconnected quads from rather large buffer objects. One of the areas I have to be careful is how large the vector of floats I'm using to make/update these buffer objects get (I have quite a few extra float values per vertex, and a lot of vertices in a buffer - the largest buffers are about 500KB).

So it strikes me that if I change my buffer objects to draw triangles this vertex data is going to be 50% larger (six vertices to draw a square rather than 4), and take 50% longer for the CPU to generate.

If gl_quads still work, am I getting a benefit here, or is the 50% extra memory and CPU time still being used on OpenGL's automatic conversion to two triangles?

\$\endgroup\$
  • 4
    \$\begingroup\$ I'm sure OpenGL supports some kind of indexed vertex buffer, meaning you store only the same 4 vertices for a quad, and instead of repeating whole vertices to make the two triangles, you only repeat the indices: [0,1,2], [2,3,0] \$\endgroup\$ – user13213 Mar 5 '13 at 0:12
  • \$\begingroup\$ Great answer here \$\endgroup\$ – bobobobo Mar 5 '13 at 1:01
  • \$\begingroup\$ I believe that the GL spec still stipulates some cases where drawing as a quad matters, e.g. with glPolygonMode (..., GL_LINE). \$\endgroup\$ – Maximus Minimus Mar 5 '13 at 1:09
5
\$\begingroup\$

Test your actual game. If quads are faster, use those. If not, don't.

One can reason that they're slower in some cases because some hardware doesn't support quads, so the driver has to do a lot of work to "fix" quad draw calls. Some hardware does support quads, doing the split to triangles in some fixed-function input assembly step, so it works with no significant overhead. There's also questions regarding how quads are submitted indexed vs non-indexed, as you raised, and which makes better use of limited bus transfer bandwidth and CPU generation time. Folk wisdom says to avoid quads, which is good advice if you're starting from nothing, maybe not so much if your code already works. folk wisdom says that a lot of things murder performance despite real, well-performing games doing those things.

In short, test. Don't assume, and don't ask the Internet for performance advice. We may be right sometimes but more often we'll either feed you out of date data, data based on some specific circumstance you're not in, or outright garbage we ourselves acquired second-hand from the Internet or colleagues (who themselves may not have first-hand experience).

\$\endgroup\$
3
\$\begingroup\$

What are the alternatives? Well, one alternative is to use Geometry Shaders, passing a GL_LINES_ADJACENCY primitive (4 vertices) and having the GS convert this primitive into a triangle strip. However, that's going to be slower to render, because one should assume geometry shaders are always slower to render.

A better method is to use indexed rendering. Here, you have two alternatives: GL_TRIANGLES and GL_TRIANGLE_STRIP with primitive restarting. The latter will result in a slightly shorter index buffer (one index for every quad). You can reuse the same index buffer for any quad rendering, so you won't need to update or modify the index buffer.

I would also suggest using unsigned shorts as the index type. If you need to render more than 16384 quads at once, then make multiple rendering calls, using glDrawElementsBaseVertex to offset the indices.

\$\endgroup\$
  • \$\begingroup\$ Some recent benchmarking I've done shows glMultiDrawArrays to now be a fast path on both NV and AMD (didn't bother with Intel) so there's another option - glMultiDrawArrays with fan or strip. \$\endgroup\$ – Maximus Minimus Mar 5 '13 at 9:57
  • \$\begingroup\$ @mh01: This requires a client-side array of drawing commands. You'd need glMultiDrawArraysIndirect to do it GPU-side. Which you can do, but it limits the hardware. \$\endgroup\$ – Nicol Bolas Mar 5 '13 at 10:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.