Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 10

Thread: VBOs and elements issue

  1. #1
    Junior Member Newbie
    Join Date
    Sep 2013
    Location
    Berlin
    Posts
    20

    VBOs and elements issue

    Hey all,

    I'm trying to optimize my program to a relatively modern openGL standard. In that interest, I'm trying to write a class for 3D objects with a model and texture loading function (with SOIL) as well as a display function for the VBOs generated in the loader functions. However, nothing ever shows up on the screen. I think I might be mixing something up with the element array.

    My object loader code is:
    Code :
    bool MainWindow::VBO::loadOBJFile(const char* file)
    {
        std::vector<GLfloat> temp_coords, v_idx, n_idx, uv_idx, final_vertices, final_normals, final_uvs;
        std::vector<glm::vec3> temp_vertices, temp_normals, middle_vertices, middle_normals;
        std::vector<glm::vec2> temp_uv, middle_uvs;
        char buffer[512];
        FILE *Data = NULL;
        int bufferError,
            readError = 3;
        errno_t test;
        test = fopen_s(&Data, file, "r");
        if(Data == NULL)
        {
            qDebug() << "OBJ file" << file << "not found!";
            return false;
        }
        else
        {
            qDebug() << "OBJ file" << file << "loading now into" << this;
        }
        do
        {
            bufferError = fscanf(Data, "%s", buffer);
     
            if(bufferError == EOF)
            {
                break;
            }
     
            if(strcmp(buffer, "v") == 0)
            {
                glm::vec3 vertex;
                readError   = fscanf(Data, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
                temp_coords.push_back(vertex.x);
                temp_coords.push_back(vertex.y);
                temp_coords.push_back(vertex.z);
                temp_vertices.push_back(vertex);
            }
            else if(strcmp(buffer, "vt") == 0)
            {
                glm::vec2 uv;
                readError   = fscanf(Data, "%f %f\n", &uv.x, &uv.y);
                temp_uv.push_back(uv);
            }
            else if(strcmp(buffer, "vn") == 0)
            {
                glm::vec3 normal;
                readError   = fscanf(Data, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
                temp_normals.push_back(normal);
            }
            else if(strcmp(buffer, "f") == 0)
            {
                unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
                int matches = fscanf(Data, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0],
                                                                              &vertexIndex[1], &uvIndex[1], &normalIndex[1],
                                                                              &vertexIndex[2], &uvIndex[2], &normalIndex[2] );
                if (matches != 9){
                    qDebug() << "File can't be read by our simple parser! Try exporting with other options";
                    qDebug() << "matches is" << matches;
                    return false;
                }
                v_idx.push_back(vertexIndex[0]);
                v_idx.push_back(vertexIndex[1]);
                v_idx.push_back(vertexIndex[2]);
                uv_idx.push_back(uvIndex[0]);
                uv_idx.push_back(uvIndex[1]);
                uv_idx.push_back(uvIndex[2]);
                n_idx.push_back(normalIndex[0]);
                n_idx.push_back(normalIndex[1]);
                n_idx.push_back(normalIndex[2]);
            }
            else if(strcmp(buffer, "o") == 0)
            {
                readError = fscanf(Data, "%s", modelName);
                qDebug() << "name of the model is" << modelName;
            }
            else
            {
    //            qDebug() << "testString is" << buffer << "and won't be recognized";
            }
        }while(1);
        fclose(Data);
     
        for( unsigned int i=0; i<v_idx.size(); i++ ){
            unsigned int vertexIndex = v_idx[i];
            glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];
            middle_vertices.push_back(vertex);
        }
        for( unsigned int i=0; i<uv_idx.size(); i++ ){
            unsigned int uvIndex = uv_idx[i];
            glm::vec2 uv = temp_uv[ uvIndex-1 ];
            middle_uvs.push_back(uv);
        }
        for( unsigned int i=0; i<n_idx.size(); i++ ){
            unsigned int normalIndex = n_idx[i];
            glm::vec3 normal = temp_normals[ normalIndex-1 ];
            middle_normals.push_back(normal);
        }
     
        for(unsigned int i= 0; i<middle_vertices.size();i++)
        {
            final_vertices.push_back(middle_vertices.at(i).x);
            final_vertices.push_back(middle_vertices.at(i).y);
            final_vertices.push_back(middle_vertices.at(i).z);
        }
        for(unsigned int i= 0; i<middle_normals.size();i++)
        {
            final_normals.push_back(middle_normals.at(i).x);
            final_normals.push_back(middle_normals.at(i).y);
            final_normals.push_back(middle_normals.at(i).z);
        }
     
        for(unsigned int i= 0; i<middle_uvs.size();i++)
        {
            final_uvs.push_back(middle_uvs.at(i).x);
            final_uvs.push_back(middle_uvs.at(i).y);
        }
     
        glGenBuffers(1, &vertices);
        glBindBuffer(GL_ARRAY_BUFFER, vertices);
        glBufferData(GL_ARRAY_BUFFER, final_vertices.size(), final_vertices.data(), GL_STATIC_DRAW);
     
        glGenBuffers(1, &normals);
        glBindBuffer(GL_ARRAY_BUFFER, normals);
        glBufferData(GL_ARRAY_BUFFER, final_normals.size(), final_normals.data(), GL_STATIC_DRAW);
     
        glGenBuffers(1, &uvs);
        glBindBuffer(GL_ARRAY_BUFFER, uvs);
        glBufferData(GL_ARRAY_BUFFER, final_uvs.size(), final_uvs.data(), GL_STATIC_DRAW);
     
        for( unsigned int i=0; i<v_idx.size(); i++ ){
            v_idx[i]--;
        }
     
        glGenBuffers(1, &elements);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elements);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, v_idx.size(), v_idx.data(), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     
        return true;
    }
    Texture loader is:
    Code :
    bool MainWindow::VBO::loadTexture(const char* texfile)
    {
     
        glGenTextures(1, &tex);
        glBindTexture(GL_TEXTURE_2D, tex);
     
        // inspired by http://open.gl/textures
        int width, height;
        unsigned char* image =
                SOIL_load_image(texfile, &width, &height, 0, SOIL_LOAD_RGB);
        if(image == 0)
        {
            qDebug() << "Texture file" << texfile << "not found!";
            return false;
        }
        else
        {
            qDebug() << "image =" << image << "from file" << texfile;
            qDebug() << "width and height =" << width << height;
        }
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
        SOIL_free_image_data(image);
     
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     
        return true;
    }
    The display function:
    Code :
        glm::mat4 anim = glm::yawPitchRoll(-handPitch, -handRoll, -handYaw);
        glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(handX, handY, handZ));
        glm::mat4 view = glm::lookAt(glm::vec3(xPosTranslate, 0.0, 5.0), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));
        glm::mat4 projection = glm::perspective(45.0f, /*1.0*/0.5f*this->width()/this->height(), 0.1f, 100.0f);
        glm::mat4 mvp = projection * view * model * anim;
        glUseProgram(program);
        glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(mvp));
     
        glUseProgram(program);
     
        glEnableVertexAttribArray(attribute_coord3d);
    void MainWindow::drawOBJ(VBO object)
    {
        glEnableVertexAttribArray(attribute_coord3d);
        glBindBuffer(GL_ARRAY_BUFFER, object.vertices);
        glVertexAttribPointer(
                    attribute_coord3d, // attribute
                    3, // number of elements per vertex, here (x,y,z)
                    GL_FLOAT, // the type of each element
                    GL_FALSE, // take our values as-is
                    0, // no extra data between each position
                    0 // offset of first element
                    );
     
        glEnableVertexAttribArray(attribute_v_normal);
        glBindBuffer(GL_ARRAY_BUFFER, object.normals);
        glVertexAttribPointer(
                    attribute_v_normal, // attribute
                    3, // number of elements per vertex, here (x,y,z)
                    GL_FLOAT, // the type of each element
                    GL_FALSE, // take our values as-is
                    0, // no extra data between each position
                    0 // offset of first element
                    );
     
        glEnableVertexAttribArray(attribute_v_uv);
        glBindBuffer(GL_ARRAY_BUFFER, object.uvs);
        glVertexAttribPointer(
                    attribute_v_uv, // attribute
                    2, // number of elements per vertex, here (U,V)
                    GL_FLOAT, // the type of each element
                    GL_FALSE, // take our values as-is
                    0, // no extra data between each position
                    0 // offset of first element
                    );
     
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object.elements);
    }
    int size;
        glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
        glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
     
        glDisableVertexAttribArray(attribute_coord3d);
        glDisableVertexAttribArray(attribute_v_color);
        glDisableVertexAttribArray(attribute_v_uv);
        glDisableVertexAttribArray(attribute_v_normal);
        glUseProgram(0);
    I don't see where my error is, however I'm pretty certain, as I wrote, that something is not quite right about the handling of the elements. I haev a whole bunch of glGetError() calls in between (deleted those here for readability), they return no errors. If any of you pros around here might give the code a quick look, it'd be appreciated.

  2. #2
    Intern Contributor
    Join Date
    Jul 2014
    Location
    Italy, Lissone
    Posts
    55
    replace this code lines:
    Code :
        glGenBuffers(1, &vertices);
        glBindBuffer(GL_ARRAY_BUFFER, vertices);
        glBufferData(GL_ARRAY_BUFFER, final_vertices.size(), final_vertices.data(), GL_STATIC_DRAW);
     
        glGenBuffers(1, &normals);
        glBindBuffer(GL_ARRAY_BUFFER, normals);
        glBufferData(GL_ARRAY_BUFFER, final_normals.size(), final_normals.data(), GL_STATIC_DRAW);
     
        glGenBuffers(1, &uvs);
        glBindBuffer(GL_ARRAY_BUFFER, uvs);
        glBufferData(GL_ARRAY_BUFFER, final_uvs.size(), final_uvs.data(), GL_STATIC_DRAW);
     
    ..blah blah
     
        glGenBuffers(1, &elements);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elements);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, v_idx.size(), v_idx.data(), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    with this other code lines:
    Code :
        glGenBuffers(1, &vertices);
        glBindBuffer(GL_ARRAY_BUFFER, vertices);
        glBufferData(GL_ARRAY_BUFFER, final_vertices.size() * sizeof(GLfloat), &final_vertices[0], GL_STATIC_DRAW);
     
        glGenBuffers(1, &normals);
        glBindBuffer(GL_ARRAY_BUFFER, normals);
        glBufferData(GL_ARRAY_BUFFER, final_normals.size() * sizeof(GLfloat), &final_normals[0], GL_STATIC_DRAW);
     
        glGenBuffers(1, &uvs);
        glBindBuffer(GL_ARRAY_BUFFER, uvs);
        glBufferData(GL_ARRAY_BUFFER, final_uvs.size() * sizeof(GLfloat), &final_uvs[0], GL_STATIC_DRAW);
     
    ..blah blah
     
        glGenBuffers(1, &elements);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elements);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, v_idx.size() *sizeof(GLuint), &v_idx[0], GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    then in this piece of code:
    Code :
        glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);

    do like that to avoid other passages
    Code :
        glDrawElements(GL_TRIANGLES, v_idx.size(), GL_UNSIGNED_SHORT, 0);

    it should work, let me know what the result is, ;

  3. #3
    Junior Member Newbie
    Join Date
    Sep 2013
    Location
    Berlin
    Posts
    20
    Hey thanks I'll try it!
    From my understanding though. shouldn't it be "final_vertices.size() / sizeof(GLfloat)" instead of "final_vertices.size() * sizeof(GLfloat)"? Alas, if your proposal doesn't work I'll try mine.

    edit: Well, neither your nor my way worked, I get the same results. :/
    Last edited by LReiter; 08-25-2014 at 02:13 AM.

  4. #4
    Junior Member Regular Contributor
    Join Date
    Dec 2010
    Location
    Oakville, ON, CA
    Posts
    107
    Where is the VAO? A non-zero VAO must be bound to do all the configurations of vertex attributes.
    ?

  5. #5
    Junior Member Newbie
    Join Date
    Sep 2013
    Location
    Berlin
    Posts
    20
    Do I really need a VAO? I never used them before, and many of the tutorials I've seen online don't mention them.

    edit: I don't think I do, do I? I've gotten my code to the point now where the models show on screen, just the faces don't seem to be quite right.

    On the left is the model in Blender (I used a snake texture because it has more irregularities than human skin) and on the right is the output in the program.
    As for the red box, it's the same problem - there seems to be a corner missing.

    edit2:
    For sake of completion, here is my current code for getting the vertices and elements (I'm omitting the code for normals and UVs here to keep it short, but it's basically the same) and drawing them:
    Code :
    //variables
    std::vector<GLfloat> final_vertices;
    std::vector<GLuint> v_idx;
    std::vector<glm::vec3> temp_vertices, middle_vertices;
     
    //reading directly from OBJ
    if(strcmp(buffer, "v") == 0)
            {
                glm::vec3 vertex;
                readError   = fscanf(Data, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
                temp_vertices.push_back(vertex);
            }
     
    //getting the order from the faces
    else if(strcmp(buffer, "f") == 0)
            {
                unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
                int matches = fscanf(Data, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0],
                                                                              &vertexIndex[1], &uvIndex[1], &normalIndex[1],
                                                                              &vertexIndex[2], &uvIndex[2], &normalIndex[2] );
                v_idx.push_back(vertexIndex[0]);
                v_idx.push_back(vertexIndex[1]);
                v_idx.push_back(vertexIndex[2]);
            }
     
    // putting the vertices in the right order into middle_vertices
    for( unsigned int i=0; i<v_idx.size(); i++ ){
            unsigned int vertexIndex = v_idx[i];
            glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];
            middle_vertices.push_back(vertex);
        }
     
    //getting the vertices from vector::glm::vec3 to vector::GLfloat
    for(unsigned int i= 0; i<middle_vertices.size();i++)
        {
            final_vertices.push_back(middle_vertices.at(i).x);
            final_vertices.push_back(middle_vertices.at(i).y);
            final_vertices.push_back(middle_vertices.at(i).z);
        }
     
    //buffering them
    glGenBuffers(1, &vertices);
    glBindBuffer(GL_ARRAY_BUFFER, vertices);
    glBufferData(GL_ARRAY_BUFFER, final_vertices.size() * sizeof(GLfloat), final_vertices.data(), GL_STATIC_DRAW);
     
    //reducing the indices by 1
    for( unsigned int i=0; i<v_idx.size(); i++ ){
        v_idx[i]--;
    }
     
    //buffering the elements
    glGenBuffers(1, &elements);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elements);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, v_idx.size() * sizeof(GLuint), v_idx.data()/*&v_idx[0]*/, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     
    //in drawing loop
    glEnableVertexAttribArray(attribute_coord3d);
        glBindBuffer(GL_ARRAY_BUFFER, object.vertices);
        glVertexAttribPointer(
                    attribute_coord3d, // attribute
                    3, // number of elements per vertex, here (x,y,z)
                    GL_FLOAT, // the type of each element
                    GL_FALSE, // take our values as-is
                    0, // no extra data between each position
                    0 // offset of first element
                    );
     
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object.elements);
        glDrawElements(GL_TRIANGLES, object.sizeOf_v_idx, GL_UNSIGNED_INT, 0);
    Last edited by LReiter; 08-25-2014 at 05:59 AM.

  6. #6
    Junior Member Regular Contributor
    Join Date
    Dec 2010
    Location
    Oakville, ON, CA
    Posts
    107
    You do need a valid non-zero VAO to be bound as the specs of core OpenGL says. In a compatibility mode - not sure. But better to do so.
    I believe your problem actually comes from reading the obj file. Inspect it in text editor. Obj may have different number of normals, texcoords and vertices. Normally, you have to load all three into separate arrays, then using the faces' indices unpack and group all three attributes into a single interleaved array (VBO) tesselating polygons into triangles, then gen and bind VAO, map the VBO using glVertexAttribPointer & glEnableVertexAttribArray, and then draw arrays using GL_TRIANGLES. When you feel a superman enough, think about packing the triangles into something more optimal and use indexed drawing.
    Good luck!

  7. #7
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,217
    In a compatibility context you can pretend VAOs never existed.

    It's worth noting that glEnableVertexAttribArray, glBindBuffer, glVertexAttribPointer and friends existed in OpenGL before VAOs did (in versions 1.5 and 2.0, to be precise). You can also check the GL_VERSION that an extension is written against, and that it requires: if either predates VAOs then you can safely use it in compatibility or downlevel contexts without VAOs too.

    For example: GL_ARB_direct_state_access is specified as requiring GL 2.0, so you can code to GL 2.0 but use that extension if available and without VAOs for it's buffer object and vertex specification calls.

  8. #8
    Junior Member Newbie
    Join Date
    Sep 2013
    Location
    Berlin
    Posts
    20
    I'm having a problem understanding why the error might be in the obj file. I just exported it from Blender, when I re-import it it looks just fine.
    The file does have a different number of data sets for vertices, tex coords and normals, however that's why I'm sorting them in my function. After I do that, the std::vectors storing the data are the same length (though the uv vector is only 2/3 of the other's length).
    From what I understand, I don't explicitly have to put all the vertex, uv and normal data into one big VBO, I can just as well keep them in different ones and send them to the vertex shader by themselves.
    However, I tried doing so, but the code crashes more specifically, the for loop crashes and I got no idea why.
    Code :
        glGenBuffers(1, &single_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, single_vbo);
        for(unsigned int i=0; i<final_vertices.size()-2; i++)
        {
            bigBuffer.push_back(final_vertices.at(i));
            bigBuffer.push_back(final_vertices.at(i+1));
            bigBuffer.push_back(final_vertices.at(i+2));
            bigBuffer.push_back(final_uvs.at(i));
            bigBuffer.push_back(final_uvs.at(i+1));
            bigBuffer.push_back(final_normals.at(i));
            bigBuffer.push_back(final_normals.at(i+1));
            bigBuffer.push_back(final_normals.at(i+2));
        }
        glBufferData(GL_ARRAY_BUFFER, bigBuffer.size() * sizeof(GLfloat), bigBuffer.data(), GL_STATIC_DRAW);
     
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
        glVertexAttribPointer(shaderAttributes[0], 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), 0);
        glVertexAttribPointer(shaderAttributes[1], 2, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)12);
        glVertexAttribPointer(shaderAttributes[2], 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)20);
     
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glEnableVertexAttribArray(0);
        glBindVertexArray(0);

    edit: I put a
    Code :
    glDrawArrays(GL_TRIANGLES, 0, object.sizeOf_v_idx);
    call into my display function instead of the
    Code :
    glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
    call. Now it works (aside from some culling issues).
    Last edited by LReiter; 08-26-2014 at 03:53 AM.

  9. #9
    Intern Contributor
    Join Date
    Jul 2014
    Location
    Italy, Lissone
    Posts
    55
    o first thing when you do you for loop here there is at least one big mistake:
    Code :
        for(unsigned int i=0; i<final_vertices.size()-2; i++) // here is you first big one mistake
        {
            bigBuffer.push_back(final_vertices.at(i));  // first cycle: i = 0 so vertices.at(0) //second cycle: i = 1 so vertices.at(1)
            bigBuffer.push_back(final_vertices.at(i+1)); // first cycle: i = 0 so vertices.at(0+1) //second cycle: i = 1 so vertices.at(1 + 1)
            bigBuffer.push_back(final_vertices.at(i+2)); // first cycle: i = 0 so vertices.at(0+2); //second cycle: i = 1 so vertices.at(1 + 2)
            bigBuffer.push_back(final_uvs.at(i)); // like above
            bigBuffer.push_back(final_uvs.at(i+1)); // like above
            bigBuffer.push_back(final_normals.at(i)); // like above
            bigBuffer.push_back(final_normals.at(i+1)); // like above
            bigBuffer.push_back(final_normals.at(i+2)); // like above
        }

    how you ca see by the comment i put in your code you are picking the same vertices again and again, i leave you the easy fun part: find how to solve it (really, is not that complicated)

    also i think that your program crashes at for loop because probably your final_uvs, final_normals and final_vertex have not the same size so, since you are looping until "i" < final_vertices.size() -2 (why final_vertices.size() -2?) after some loops "i" becomes bigger than the size of one or more of your vectors and more precisely of your final_uvs and/or final_normals, sorry but you have to find another way. good job

    EDIT: a solution could be
    Code :
    for(blah blah; buffer_size < vertices_size + uvs_size + normals_size; blah_blah)
    {
    ...
    blah bla
    ...
    }
    Last edited by Ruggero Visitnin; 08-26-2014 at 09:36 AM.

  10. #10
    Junior Member Regular Contributor
    Join Date
    Dec 2010
    Location
    Oakville, ON, CA
    Posts
    107
    In obj files numeration starts at 1, not 0.
    And here:
    glVertexAttribPointer(shaderAttributes[0], 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), 0);
    glVertexAttribPointer(shaderAttributes[1], 2, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (GLvoid*)12);
    glVertexAttribPointer(shaderAttributes[2], 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)20);
    You specify different stride for each attrib pointer, that is wrong. Aside from that, the VBO must be bound BEFORE the glVertexAttribPointer called, because the mapping is performed for the buffer currently bound.
    Simply saying, your code is just full of bugs. How can we help you?
    By giving an advice to put more attention to what you are writing? Or read the docs for the functions you are using?
    Last edited by Yandersen; 08-26-2014 at 12:07 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •