Reputation: 995
This might be again some stupid question and perhaps it's something really obvious what I am missing, but I having trouble to get glMultiDrawArrays working in OpenGL4.
I found plenty of explanations like this:
for (int i = 0; i < numarrays; i++)
glDrawArrays (GL_TRIANGLE_FAN, arrayfirsts[i], arraycounts[i]);
is similar to that:
glMultiDrawArrays (GL_TRIANGLE_FAN, arrayfirsts, arraycounts, numarrays);
And I am perfectly fine with that explanation. However, what I couldn't find out so far is- how has buffering to be done when I want to use glMultiDrawArrays?
Currently I have my code like this:
UINT vertssize = FloatsPerVertex * 4;
UINT texsize = TexCoords2D * 4;
VertsBuf[0] = RFX2*Z*(X - FX2);
VertsBuf[1] = RFY2*Z*(Y - FY2);
VertsBuf[2] = Z;
VertsBuf[3] = (U)*TexInfo[0].UMult;
VertsBuf[4] = (V)*TexInfo[0].VMult;
VertsBuf[5] = RFX2*Z*(X + XL - FX2);
VertsBuf[6] = RFY2*Z*(Y - FY2);
VertsBuf[7] = Z;
VertsBuf[8] = (U + UL)*TexInfo[0].UMult;
VertsBuf[9] = (V)*TexInfo[0].VMult;
VertsBuf[10] = RFX2*Z*(X + XL - FX2);
VertsBuf[11] = RFY2*Z*(Y + YL - FY2);
VertsBuf[12] = Z;
VertsBuf[13] = (U + UL)*TexInfo[0].UMult;
VertsBuf[14] = (V + VL)*TexInfo[0].VMult;
VertsBuf[15] = RFX2*Z*(X - FX2);
VertsBuf[16] = RFY2*Z*(Y + YL - FY2);
VertsBuf[17] = Z;
VertsBuf[18] = (U)*TexInfo[0].UMult;
VertsBuf[19] = (V + VL)*TexInfo[0].VMult;
DrawVerts(DrawVertsBuf, vertssize, texsize, Color);
with DrawVerts looking like that:
void DrawVerts(FLOAT* verts, UINT vertsize, UINT texsize, vec4f DrawColor)
{
UINT TotalSize = vertsize + texsize;
UINT stride = (sizeof(float) * FloatsPerVertex) + (sizeof(float) * TexCoords2D);
UINT vertoffset = (sizeof(float) * FloatsPerVertex);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * TotalSize, verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, stride, (void*)vertoffset);
glUniform4f(DrawTileDrawColor, DrawColor.X, DrawColor.Y, DrawColor.Z, DrawColor.W);
// Draw
glDrawArrays(GL_TRIANGLE_FAN, 0, vertsize / FloatsPerVertex);
// Clean up
glDisableVertexAttribArray(VERTEX_COORD_ATTRIB);
glDisableVertexAttribArray(TEXTURE_COORD_ATTRIB);
}
How do I have to change that in order to call successfully glMultiDrawArrays? Of course I do have to add a counter then, that's obvious. I also tried some, but only ended up in crashing or no drawing so far. Tutorials and examples I found either spare the buffering part or they are for OpenGL1.x which I understand moving over to OpenGL4. Currently its called up to 1000 times and I want to give it a try to optimize my code with it.
Upvotes: 1
Views: 2936
Reputation: 18389
Here is an example drawing two quads:
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/glut.h>
typedef struct {
int elements_count;
float *array;
} fan_s;
GLuint vbo_id;
#define VBO_SIZE 4096
static void setup_vbo(void) {
glGenBuffers(1, &vbo_id);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBufferData(GL_ARRAY_BUFFER, VBO_SIZE, NULL, GL_DYNAMIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
static void draw_fans(const fan_s *fans, int num_fans) {
#define MAX_FANS 1024
GLint fans_starts[MAX_FANS];
GLsizei fans_sizes[MAX_FANS];
float *mapping = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
int i;
int num_elements_total = 0;
for(i = 0; i != num_fans; ++i) {
memcpy(mapping, fans[i].array, fans[i].elements_count * 3 * sizeof(float));
mapping += fans[i].elements_count * 3;
fans_starts[i] = num_elements_total;
fans_sizes[i] = fans[i].elements_count;
num_elements_total += fans[i].elements_count;
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glMultiDrawArrays(GL_TRIANGLE_FAN, fans_starts, fans_sizes, num_fans);
}
static void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
float fan0_data[] = {
0.0, 0.0, 0.0,
0.0, 100.0, 0.0,
100.0, 100.0, 0.0,
100.0, 0.0, 0.0
};
float fan1_data[] = {
200.0, 0.0, 0.0,
200.0, 100.0, 0.0,
300.0, 100.0, 0.0,
300.0, 0.0, 0.0
};
fan_s fans[] = {
4, fan0_data,
4, fan1_data
};
draw_fans(fans, 2);
glutSwapBuffers();
}
static void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
}
static void keyboard(unsigned char key, int x, int y) {
if(key == 27) {
exit(0);
}
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 150);
glutCreateWindow("");
glClearColor(0.0, 0.0, 0.0, 1.0);
glColor4f(1.0, 1.0, 1.0, 1.0);
glewInit();
setup_vbo();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
For simplicity sake, I haven't checked any errors, including overflow (see VBO_SIZE
and MAX_FANS
).
Upvotes: 2