How to change element array buffer or have multiple?

78 Views Asked by At

I'm trying to create and element array buffer to draw two different shapes with a different number of vertices. I haven't been able to find any resources on this as they mostly show how to draw a single triangle or square separately.

Let's say i want to draw both at the same time, the square would have 6 indices while the triangle(just an example) would have 3 indices. But I'm not sure how to go about this. I've tried having two element array buffers or just reassigning it.

float vertice[] =
{
    -0.5f, -0.5f, 0.0f,     0.5f, 0.3f, 0.0f,
     0.5f,  0.5f, 0.0f,     0.5f, 0.3f, 0.0f,
     0.5f, -0.5f, 0.0f,     0.5f, 0.3f, 0.0f,
    -0.5f,  0.5f, 0.0f,     0.5f, 0.3f, 0.0f
}; 

float vertices2[] =
{
    -0.5f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f,
     0.0f,  0.0f, 0.0f,     0.0f, 1.0f, 0.0f,
     0.5f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f
};

int indice[] =
{
    0, 1, 2,
    0, 1, 3
};

int indice2[] =
{
    0, 1, 3
};
VertexArray vao;
vao.Bind();

VertexBuffer vbo(vertice, sizeof(vertice), GL_STATIC_DRAW);
vbo.Bind();

IndexBuffer ibo(indice, sizeof(indice), GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

vao.Unbind();
vbo.Unbind();

VertexArray vao2;
vao2.Bind();

VertexBuffer vbo2(vertices2, sizeof(vertices2), GL_STATIC_DRAW);
vbo2.Bind();

IndexBuffer ibo2(indice2, sizeof(indice2), GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

vao2.Unbind();
vbo2.Unbind();
vao.Bind();
ibo.Bind(); 
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
ibo.Unbind();
vao.Unbind();

vao2.Bind();
ibo2.Bind();
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
ibo2.Unbind();
vao2.Unbind();

If anyone has any resources or something where i can work out how to do this properly, that be very much appreciated.

1

There are 1 best solutions below

0
Botje On

The obvious solution is to merge all your arrays together. Summarized:

float vertice[] = {
  // the 4 vertices from vertice
  // the 3 vertices from vertice2
};

int indice[] = {
  // the 6 indices from indice
  0, 1, 2,
  0, 1, 3
  // the 3 indices from indice2, all + 4 to account for the earlier ones.
  4, 5, 6
}

But often it is impractical to do this at compile time. So let's do it at runtime!

struct Merger {
  std::vector<float> vertices;
  std::vector<int> indices;

  void addFromArrays(const float * vs, size_t numvs, const int * is, size_t numis) {
    size_t offsetvs = vertices.size();
    vertices.resize(offsetvs + numvs);
    std::copy(vs, vs + numvs, std::begin(vertices) + offsetvs);

    size_t offsetis = indices.size();
    indices.resize(offsetis + numis);
    std::transform(is, is + numis, std::begin(indices) + offsetis,
       [=](int i) { return i + offsetvs; });
  }
}

Using it is simple:

Merger m;
m.addFromArrays(vertice, 24, indice, 6);
m.addFromArrays(vertice2, 18, indice2, 3);
// now use m.vertices.data() and m.indices.data() as inputs to glBufferData

Of course all these explicit item counts get in the way, but we can add a templated method to Merger to calculate it for you:

  template <size_t Vs, size_t Is>
  void addFromArrays(const float (&vs)[Vs], const int (&is)[Is]) {
    addFromArrays(vs, Vs, is, Is);
  }