Most basic working vbo example

后端 未结 4 1633
清酒与你
清酒与你 2020-12-24 08:12

I want to know the simplest method for using vbo\'s in OpenGL... I have tried running a few examples that work but are clouded with all other information thats making it rea

4条回答
  •  时光说笑
    2020-12-24 08:40

    What you are doing looks right, except sizeof(vertices) gives you the size of the address, not the size of the array. So, when you call glBufferData, you are allocating 8 bytes and when you call glBufferSubData, you fill those 8 bytes with the first four bytes of the vertices array and then the first four bytes of the normals array. Then, when you go to call glDrawArrays, the first indice causes an array index out of bounds exception (Hence the EXC_BAD_ACCESS).

    // Data
    GLuint geometry_array = 0;
    GLuint indice_array = 0;
    
    GLfloat *geometry;
    GLuint *indices;
    

    You can do this initialization differently, but I interleave all my data into a 32 bytes per vertice array. Any way you choose to set up your array works, as long as you use glVertexPointer, glNormalPointer, and glTexCoordPointer correctly.

    // Initialize
    
    geometry = new GLfloat[8*num_geometry];
    indices = new GLuint[num_indices];
    
    /* Fill geometry: 0, 1, 2 = vertex_xyz 
     *                3, 4, 5 = normal_xyz
     *                6, 7 = tex_coord_uv
     */
    
    glGenBuffers(1, &geometry_array);
    glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*8*num_geometry, NULL, GL_DYNAMIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat)*8*num_geometry, geometry);
    
    glGenBuffers(1, &indice_array);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*num_indices, NULL, GL_STATIC_DRAW);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*num_indices, indices);
    

    The render function is five steps. First, bind the buffers so OpenGL knows where to find your geometry and indice data. Second, Enable the various client states for each type of data. If you leave one out, that type of data will not be rendered, and if leave all of them out, your entire object will not be rendered. Third, you have to tell OpenGL where each type of data is contained in your array. In this case the 32 byte geometry data starts with 12 bytes of vertex data, so the starting offset should be zero or NULL. Since each vertex-normal-texcoord combo is 32 bytes, that is the step size. "sizeof(GLfloat)8" says 32 bytes from offset NULL, there will be another vertice xyz group. In the case of the normals, each normal xyz group is 12 bytes after the offset for the vertice xyz group, hence "(float)(sizeof(GLfloat)*3)" as the starting offset. Again, the step size is 32 bytes. Fourth, you have to tell it to draw all of the triangles associated with the indice array. Finally, you should disable the client states, in case you want to use a different method of rendering.

    //Render
    // Step 1
    glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);
    
    // Step 2
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    
    // Step 3
    glTexCoordPointer(3, GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*5));
    glNormalPointer(GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*3));
    glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*8, NULL);
    
    // Step 4
    glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, NULL);
    
    // Step 5
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    

提交回复
热议问题