sjaustirni
sjaustirni

Reputation: 3237

VBO draws nothing

I'm trying to render my stored data using VBOs. However, nothing is actually rendered, although no error is thrown by glGetError();

void Model::initDrawing()
{
    glewInit(); 

    glGenBuffers(1, &_bufferID);
    glBindBuffer(GL_ARRAY_BUFFER, _bufferID);

    const GLsizeiptr vertex_size = sizeof(_modelMesh->vertices);
    const GLsizeiptr normal_size = sizeof(_modelMesh->vertices);
    glBufferData(GL_ARRAY_BUFFER, vertex_size+normal_size, 0, GL_STATIC_DRAW);


    GLvoid * vbo_buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
        memcpy(vbo_buffer, &_modelMesh->vertices[0], vertex_size);
        vbo_buffer += vertex_size;      
        memcpy(vbo_buffer, &_modelMesh->normals[0], normal_size);       
    glUnmapBuffer(GL_ARRAY_BUFFER);

    glVertexPointer(4, GL_FLOAT, 0, (GLvoid*)((char*)NULL));
    glNormalPointer(GL_FLOAT, 0, (GLvoid*)((char*)NULL+vertex_size));       
}

void Model::draw()
{
    glBindBuffer(GL_ARRAY_BUFFER, _bufferID);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glDrawElements(GL_TRIANGLE_STRIP, _modelMesh->vertices.size(), GL_UNSIGNED_INT, (GLvoid*)((char*)NULL));

    GLenum err;
    while ((err = glGetError()) != GL_NO_ERROR)
    {
        cerr << "OpenGL error: " << err << endl;
    }
}

where Mesh *_modelMesh consists of (among the others):

std::vector<Vertex4f> vertices;
std::vector<Normal3f> normals;

which are simply just vectors of numbers of GLfloat type:

typedef struct _vertex4f {
    Vertex3f vertex;
    GLfloat weight;
} Vertex4f;
typedef struct _vertex3f {
    GLfloat x, y, z;
} Vertex3f;

Is defining vectors and normals enough for drawing?

I'm also using light when rendering.

Upvotes: 0

Views: 276

Answers (2)

datenwolf
datenwolf

Reputation: 162164

Settings made by calls to gl…Pointer are not persistent within the buffer. Either you contain them within a Vertex Array Object, or you set them right before the gl…Draw calls. Furthermore, yor call to glDrawElements looks like you're intending to fetch indices from a Vertex Element Array buffer. I don't see you generating one.

These changes are required:

void Model::initDrawing()
{
    glewInit(); 

    glGenBuffers(1, &_bufferID);
    glBindBuffer(GL_ARRAY_BUFFER, _bufferID);

    const GLsizeiptr vertex_size = sizeof(_modelMesh->vertices);
    const GLsizeiptr normal_size = sizeof(_modelMesh->vertices);
    glBufferData(GL_ARRAY_BUFFER, vertex_size+normal_size, 0, GL_STATIC_DRAW);


    GLvoid * vbo_buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
        memcpy(vbo_buffer, &_modelMesh->vertices[0], vertex_size);
        vbo_buffer += vertex_size;      
        memcpy(vbo_buffer, &_modelMesh->normals[0], normal_size);       
    glUnmapBuffer(GL_ARRAY_BUFFER);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &element_bufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_bufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertex_size+normal_size, 0, GL_STATIC_DRAW);
    GLvoid * element_buffer = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
       /* fill element buffer */
    glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}

void Model::draw()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, _bufferID);
    glVertexPointer(4, GL_FLOAT, 0, (GLvoid*)((char*)NULL));
    glNormalPointer(GL_FLOAT, 0, (GLvoid*)((char*)NULL+vertex_size));       

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_bufferID);
    glDrawElements(GL_TRIANGLE_STRIP, _modelMesh->vertices.size(), GL_UNSIGNED_INT, (GLvoid*)((char*)NULL));

    GLenum err;
    while ((err = glGetError()) != GL_NO_ERROR)
    {
        cerr << "OpenGL error: " << err << endl;
    }
}

Upvotes: 2

Andon M. Coleman
Andon M. Coleman

Reputation: 43319

For one thing, your positions and normals are not sized correctly.

Their sizes should be something like _modelMesh->vertices.size () * sizeof (GLfloat) * 4 and _modelMesh->normals.size () * sizeof (GLfloat) * 3 respectively. They are not the same size.

You also do not want to use sizeof (_modelMesh->vertices), because vertices is a templated container. That will not give you the size of its contained elements, just the size of the instantiated std::vector <Vertex4f> object (which is probably a couple of pointers).

Finally, I do not see anywhere in this code where you bind anything to GL_ELEMENT_ARRAY_BUFFER.

Likewise, glBindBuffer(GL_ARRAY_BUFFER, _bufferID); is not necessary in Model::draw (...), because the only time the thing bound to GL_ARRAY_BUFFER matters is when you call gl...Pointer (...). From that point on, it does not matter what, if anything is bound to GL_ARRAY_BUFFER; its only purpose is to tell the Pointer command which buffer's memory the pointer is relative to.

Upvotes: 3

Related Questions