[WebGL] DrawElements and indices: Can vertices ever really be shared?

Started by
2 comments, last by 21st Century Moose 3 years, 4 months ago

Consider the typical draw call

webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, faces); 
webgl.drawElements(webgl.TRIANGLES, nfaces * 3, webgl.UNSIGNED_SHORT, 0);

Now, let's say for simplicity that I am rendering a cube. If the component of each Vertex are its position px, py, pz and its normal nx, ny, nz, then I have 8 unique vertices.

I can then keep a buffer with these 8 vertices, keep another “faces” buffer with indices to which vertex each face uses, and there you go, shared vertices through an indexed drawElements call. Fine.

When we introduce UV coordinates, though, I don't have 8 unique vertices anymore. I end up with each face requiring exactly three unique vertices.

The faces buffer, then, might as well be [(0,1,2), (3,4,5), (6,7,8) … and so on].

So, as vertices carry more information, they become impossible to share. Yet, I need an index buffer in order to be able to call drawElements. An index buffer whose content ends up being nothing but a sequence of 0 … nverts-1 integers.

Am I missing something?

Advertisement

That's how GLTF format looks like to speed up loading… it goes straight to GPU.

GPU prefers a clearly defined Triangle List. Also it is a general scheme that can handle all mesh types - a collection of separated triangles.

The downside of GLTF is that you lose information on which vertices are the same originally.

What you're missing is that a cube is an excessivly simplistic example that is not representative of real-world use cases.

If we step up to the next level of complexity - something like a Quake model - and examine the Shambler model, we'll see that the base model file is 284 triangles, which if not using indexing equates to 852 vertices; if we're using a 32-byte vertex format that's ~27k in size.

If we remove duplication from this model (and remembering that it's vertex format would include positions, normals and texture coordinates) we reduce it to 220 vertices and 852 indices, so assuming the same 32-byte vertex format and 16-bit index format. that's ~9k in size.

So for this case indexing reduces the overall size of the model to one-third of what it was.

It's also excessively simplistic to assume that the only purpose of indexing is to reuse vertices, because that's not the case at all. Another purpose of indexing is to allow for draw call concatenation, so that a model which previously required multiple draw calls to render might be capable of being handled in only one. Finally, indexing also allows for the hardware vertex cache to operate, so that a vertex which was recently transformed won't need to be re-transformed if it is referenced again.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement