Skip to main content
GameDev.net gamedev.net
🔒 Locked

degenerate triangles

Started by AlanSmithee May 22, 2015 at 2:39 PM 3 replies 5.9k views
Original Post
AlanSmithee
AlanSmithee
Hi.

I am making a webgl 2d renderer to render quads (sprites).

To make the renderer more effective i minimize draw calls by having all vertex data in the same buffer.

Each vertex has a pos, tintcolor and texcoord, making one vertex (3 * 4 * 2) * 4(float) = 36 bytes.

Max number of sprites per draw call is 10.000.

At the moment i am rendering quads using indices, with drawElemtents and gl_triangle_strips.

Ie: quad one is made up of index 0-1-2 + 1-2-3, quad two of index 4-5-6 + 5-6-7 etc. This seems to be working fine. There is, however no shared vertices. (except those that are shared in a quad)

Looking at other solutions to this kind of batching, a lot of people do not use indices, but instead use drawArrays with gl_triangels and a degenerate triangle to separate quads.

I am looking for some input regarding the differences between the two, and if there are any disadvantages to using indices.

Thanks in advance!
C0lumbo
C0lumbo

Use indices. Obviously the proper answer is to profile, but the performance difference is probably marginal enough that it's hard to measure, so just use indices because it makes sense.

By using indices you are sending less data through (an index is smaller than a vertex), but more importantly by using an indexed draw you are allowing the GPU to use an optimisation called a post-transform cache. Basically, the quad (012, 213) involves 6 vertices, but the GPU can realise that it can reuse the previous vertex shader output for the second instance of vertices 1 and 2, skipping some work. GPUs don't use a post-transform cache for non-indexed rendering because it'd be too much work to check which vertices are duplicates of earlier ones.

There's a trickier question of whether or not you should use indices as a triangle strip with degenerates (0, 1, 2, 3, 3, 4, 4, 5, 6, 7, 7, etc) or a triangle list (0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7). It probably makes little difference but I'd choose the latter because there is at least some archaic console hardware that performed particularly badly with degenerates.

Note that rendering a big load of quads is quite common, sometimes it's handy just to make one giant array of indices exactly for that purpose and share it across your 2D system, your particle system, etc.

dpadam450
dpadam450

It shouldn't matter which one you choose, though webGL may be a lot slower so indices might be faster.

but instead use drawArrays with gl_triangels and a degenerate triangle to separate quads.

You would simply just have duplicated vertices where each triangle has 3 unique vertices. The degenerate thing would be if you were drawing indexed vertices using triangle strips/fans where you send -1 I believe as a degenerate index which tells the GPU to draw a brand new polygon that isn't attached to the edges of the previous triangle.

NBA2K, Madden, Maneater, Killing Floor, Sims 
AlanSmithee
AlanSmithee

Thanks for your input!

There's a trickier question of whether or not you should use indices as a triangle strip with degenerates (0, 1, 2, 3, 3, 4, 4, 5, 6, 7, 7, etc) or a triangle list (0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7). It probably makes little difference but I'd choose the latter because there is at least some archaic console hardware that performed particularly badly with degenerates.

It was a typo by me, I meant to say that I am using indices with gl_triangles, not gl_triangle_strips.

Note that rendering a big load of quads is quite common, sometimes it's handy just to make one giant array of indices exactly for that purpose and share it across your 2D system, your particle system, etc.

Yes, I am doing something like this currently, still need to flesh out the architecture.

At the moment, entities (be it particles or something else) is not aware of the rendering system in any way. If they are renderable, they will be rendered.

Sharing the actually index daxa cross components (physics, rendering etc) will make me think about what part of the system should be responsible for the data.

I am still in early stages of development, so I will keep this in consideration moving forward.

Again, thanks for taking you time to answer guys!

AlanSmithee
AlanSmithee
Sorry for bumping this, but I just wanted to add that there is an important difference between using indices and not, which is that there is a limit of 65000 indexes per draw call. (using WebGL)

This means that, using indices, I can draw at most 10833 (65000/6) quads (sprites) per draw call.

This covers my target of 10000 sprites, and it is relatively easy to split up a large draw call, but it is an important distinction to be aware of.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.