I am trying to improve the performance of my drawing. What I actually do is to draw a mesh in 2D with the height as the color. I have the mesh_xy matrix for the x-y coordinate and mesh_z for the height matrix and construct a index matrix for the plotting elements. First I tried to use the client side array and it works fine. Then I made the minimal change by putting the mesh_xy to the server side as a VBO. Nothing is rendered. Anyone can help me?
The relating code is pasted below. draw_bmfm5() is the function using client side array which works perfect. draw_bmfm6() is the VBO (only the mesh_xy is in the server side). One thing I need to mention is: my graphics card supports the VBO which I have tested using other program.
void draw_bmfm5(float scale)
{
glPushMatrix();
glScalef(scale,scale,1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_1D);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);//which is not default
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);//use texture coordinate
glEnableClientState(GL_INDEX_ARRAY);
glVertexPointer(2,GL_FLOAT,0,mesh_xy);//all 1d array, make it 2D and less data is transferred
glTexCoordPointer(1,GL_FLOAT,0,mesh_z);
for(i=0;i<n-1;i++)
{
glDrawElements(GL_TRIANGLE_STRIP,2*HEIGHT,GL_UNSIGNED_INT,index_xy[i]);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_INDEX_ARRAY);
glDisable(GL_TEXTURE_1D);
glPopMatrix();
}
//the only difference between 5 and 6 is:
//we are going to store the mesh_xy into the server side
GLuint vbo_vertex,vbo_tex,vbo_indx;
PFNGLGENBUFFERSARBPROC pglGenBuffersARB = 0; // VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC pglBindBufferARB = 0; // VBO Bind Procedure
PFNGLBUFFERDATAARBPROC pglBufferDataARB = 0; // VBO Data Loading Procedure
#define glGenBuffersARB pglGenBuffersARB
#define glBindBufferARB pglBindBufferARB
#define glBufferDataARB pglBufferDataARB
void create_vbo()
{
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
glGenBuffersARB(1,&vbo_vertex);
glBindBufferARB(GL_ARRAY_BUFFER,vbo_vertex);
glBufferDataARB(GL_ARRAY_BUFFER,3000*141*2*sizeof(float),mesh_xy,GL_STATIC_DRAW);
glGenBuffersARB(1,&vbo_tex);
glGenBuffersARB(1,&vbo_indx);
glBindBufferARB(GL_ARRAY_BUFFER,vbo_tex);
glBufferDataARB(GL_ARRAY_BUFFER,3000*141*sizeof(开发者_如何学Pythonfloat),mesh_z,GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,vbo_indx);
glBufferDataARB(GL_ARRAY_BUFFER,HEIGHT*WIDTH*2*sizeof(int),index_xy,GL_DYNAMIC_DRAW);
}
void draw_bmfm6(float scale)
{
glPushMatrix();
glScalef(scale,scale,1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_1D);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);//which is not default
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);//use texture coordinate
glEnableClientState(GL_INDEX_ARRAY);
//glVertexPointer(2,GL_FLOAT,0,mesh_xy);//all 1d array, make it 2D and less data is transferred
glBindBufferARB(GL_ARRAY_BUFFER,vbo_vertex);
glVertexPointer(2,GL_FLOAT,0,0);
glTexCoordPointer(1,GL_FLOAT,0,mesh_z);
for(i=0;i<n-1;i++)
{
glDrawElements(GL_TRIANGLE_STRIP,2*HEIGHT,GL_UNSIGNED_INT,index_xy[i]);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_INDEX_ARRAY);
glDisable(GL_TEXTURE_1D);
glPopMatrix();
}
GL_INDEX_ARRAY does not mean what you think it means. It's meant to control a color selector from a color palette, which is used in GL when you render to palettized framebuffers. The simple fact that you call glDrawElements means that you're using vertex indices. There's no client-side array to Enable.
So... When you look at your VBO, you can see how that gets your calls confused:
glBindBufferARB(GL_ARRAY_BUFFER,vbo_tex);
glBufferDataARB(GL_ARRAY_BUFFER,3000*141*sizeof(float),mesh_z,GL_DYNAMIC_DRAW);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,vbo_indx);
glBufferDataARB(GL_ARRAY_BUFFER,HEIGHT*WIDTH*2*sizeof(int),index_xy,GL_DYNAMIC_DRAW);
The last call actually uses the buffer bound to ARRAY_BUFFER, i.e. vbo_tex. So, you're uploading your indices to vbo_tex and not putting anything into vbo_indx
Next, on your binding of the VBOs, you're not selecting the proper vbo for each Pointer call.
Indices and vertices are fundamentally different. You can put one or the other (preferably both) into vbos, but your index_xy structure is an array of arrays, so I'll write code that only puts the vertices in vbos (as I don't know the underlying data structure for the indices)
Putting this all together gives:
void create_vbo()
{
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
glGenBuffersARB(1,&vbo_vertex);
glBindBufferARB(GL_ARRAY_BUFFER,vbo_vertex);
glBufferDataARB(GL_ARRAY_BUFFER,3000*141*2*sizeof(float),mesh_xy,GL_STATIC_DRAW);
glGenBuffersARB(1,&vbo_tex);
glBindBufferARB(GL_ARRAY_BUFFER,vbo_tex);
glBufferDataARB(GL_ARRAY_BUFFER,3000*141*sizeof(float),mesh_z,GL_DYNAMIC_DRAW);
}
void draw_bmfm6(float scale)
{
glPushMatrix();
glScalef(scale,scale,1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_1D);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);//which is not default
glEnableClientState(GL_VERTEX_ARRAY); // Why was this Disable ?
glEnableClientState(GL_TEXTURE_COORD_ARRAY);//use texture coordinate
//glEnableClientState(GL_INDEX_ARRAY); // removed
glBindBufferARB(GL_ARRAY_BUFFER,vbo_vertex);
glVertexPointer(2,GL_FLOAT,0,0);
glBindBufferARB(GL_ARRAY_BUFFER,vbo_tex); // Binding the texcoord buffer
glTexCoordPointer(1,GL_FLOAT,0,0); // 0 as offset
for(i=0;i<n-1;i++)
{
glDrawElements(GL_TRIANGLE_STRIP,2*HEIGHT,GL_UNSIGNED_INT,index_xy[i]);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// glDisableClientState(GL_INDEX_ARRAY); // not needed
glDisable(GL_TEXTURE_1D);
glPopMatrix();
}
Note: I have not tested this code, but I have fixed a number of issues. There might be other ones.
Last, pushing the index array data into VBOs would require binding and putting the data into ELEMENT_ARRAY_BUFFER, and pass offsets into the buffer from the glDrawElements call.
精彩评论