How to convert large arrays of quad primitives to triangle primitives?

后端 未结 2 1527
没有蜡笔的小新
没有蜡笔的小新 2021-01-19 01:41

I have an existing system, which provides 3D meshes. The provided data are an array of vertex coordinates with 3 components (x, y, z) and an index list. The issue is that th

2条回答
  •  时光取名叫无心
    2021-01-19 02:10

    If that has to be done only once, then that would be the solution. But the mesh data are not static.

    The mesh data may be dynamic, but the topology of that list is the same. Every 4 vertices is a quad, so every 4 vertices represents the triangles (0, 1, 2) and (0, 2, 3).

    So you can build an arbitrarily large static index buffer containing an ever increasing series of these numbers (0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, etc). You can even use baseVertex rendering to offset them to render different serieses of quads using the same index buffer.

    My suggestion would be to make the index buffer use GLushort as the index type. This way, your index data only takes up 12 bytes per quad. Using shorts gives you a limit of 16384 quads in a single drawing command, but you can reuse the same index buffer to draw multiple serieses of quads with baseVertex rendering:

    constexpr GLushort batchSize = 16384;
    constexpr unsigned int vertsPerQuad = 6;
    void drawQuads(GLuint quadCount)
    {
      //Assume VAO is set up.
      int baseVertex = 0;
      while(quadCount > batchSize)
      {
        glDrawElementsBaseVertex(GL_TRIANGLES​, batchSize * vertsPerQuad, GL_UNSIGNED_SHORT, 0, baseVertex​ * 4);
        baseVertex += batchSize;
        quadCount -= batchSize;
      }
      glDrawElementsBaseVertex(GL_TRIANGLES​, quadCount * vertsPerQuad, GL_UNSIGNED_SHORT, 0, baseVertex​ * 4);
    }
    

    If you want slightly less index data, you can use primitive restart indices. This allows you to designate an index to mean "restart the primitive". This allows you to use a GL_TRIANGLE_STRIP primitive and break the primitive up into pieces while still only having a single draw call. So instead of 6 indices per quad, you have 5, with the 5th being the restart index. So now your GLushort indices only take up 10 bytes per quad. However, the batchSize now must be 16383, since the index 0xFFFF is reserved for restarting. And vertsPerQuad must be 5.

    Of course, baseVertex rendering works just fine with primitive restarting, so the above code works too.

提交回复
热议问题