BruceSherwood/glowscript

Support Total Canvas Vertex Count >65535+

Closed this issue · 4 comments

I'm writing this running into the vertex limit in VPython7.
The help comment on http://www.glowscript.org/docs/VPythonDocs/compound.html say to compound objects to get around the 65536 uint16 limit for WebGL:

Limitation on the number of objects to compound: In the WebGL 3D graphics library that is used by VPython, a compound cannot have more than 65536 (2**16) vertexes (pos, normal, color), due to WebGL using 16-bit integers to reference the vertexes. For example, a box object has 8*3 = 24 vertex objects, because each corner requires three vertex objects, all with the same positions but with three different normals. That means that a list of boxes to compound must not contain more than int(65536/24) = 2730 boxes. A cylinder, in order to have smooth sides, requires 206 vertexes, so a list of cylinders to compound must not contain more than int(65536/206) = 318 cylinders. If you need to compound more than 2730 boxes, a way to deal with the limitation is to make several compounds, each with less than 2730 boxes (and it may be convenient to store these compounds in a list). You can compound a list of compound objects, but the total number of vertexes cannot exceed the limit.

Since the limit is simply due to the index, it is possible to support multiple lists in the first place and keep the offset index within a 16-bit unsigned int. See: https://stackoverflow.com/a/5189502/4916612

See https://www.youtube.com/watch?v=AXZiNHkMpZs&feature=youtu.be#t=2m33s

Additionally, the OES_element_index_uint has been promoted to core in WebGL 2.0:
https://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/

For my particular application, in VPython I generate the vertexes and then generate a list of quads. I would be perfectly happy doing a compound object out of half the quads and then drawing each half, but that doesn't work as the

if (this.canvas.vertex_id >= 65536) throw new Error('Currently the number of vertices is limited to 65536.')
error keeps getting thrown.

Any way around this issue that is appropriate for glowscript/vpython?

Thanks for the links, which I'll study. However, I have regularly used the compounding scheme successfully, whereas it sounds like it doesn't work for you, which is puzzling, unless each of your compounds goes over the limit. Making a compound places the mesh in GPU memory and frees up all the vertex elements that went into the quads. Can you provide a simple test case that fails? What platform do you use? I do look forward to using WebGL 2.0, which relaxes various previous limitations. I don't know how to read/interpret the OES link: what is this, exactly?

Note that if a compound were implemented in terms of drawArrays instead of drawElements the compound object would take about 8 times as long to render. Imagine a rectangular grid of vertexes, in which case each vertex would touch 8 triangles. In order to use drawArrays, there would have to be 8 vertexes at every location, which would mean that 8 times as many vertex-handling GPU elements would have to execute. As for the first link you gave, note that the writer says "For the moment being, what you can do is to divide your big object in several segments of 65K elements each and re-index every segment so all the segments have indexes from 0 to 65K. I have tested it and WebGL allows it." That sounds to me to be essentially the same thing as dividing a large object into several compound objects. There remains the question of why that doesn't work in your tests.

I think a primary issue is that for my use case (plotting a surface in spherical coordinates across a range of parameters), it made sense to just update a single vertex buffer as the parameters changed. For this reason, I kept the vertex handles around (in vpython) to manipulate, even after combining Quads using these vertices into a compound object. There are additional vertices in the scene for plotting other objects as well (that have not been compounded yet), so my spherical surface actually has a limit much less than 65535 vertices as I was attempting before.

Seems like I will have to remove and recreate it each time a parameter changes. The OES_element_index is essentially the 32-bit unsigned int that WebGL 1.0 was lacking (and causing me all sorts of trouble with a 65535 vertex limit). In WebGL 2.0, the 32-bit unsigned int index is standard.

I look forward to the time, presumably not distant, when WebGL is generally available.