2
\$\begingroup\$

In relation to my previous question: Rendering without VAO's & VBO's?

I came to realize that i have completely to port the example in modern OpenGL with VAO's and VBO's .

So their rendering function was this :

void renderTriangleModels()
{
  // Draw simulation model

  const ParticleData &pd = model.getParticles();
  float surfaceColor[4] = { 0.2f, 0.5f, 1.0f, 1 };

  if (shader)
  {
    shader->begin();
    glUniform3fv(shader->getUniform("surface_color"), 1, surfaceColor);
    glUniform1f(shader->getUniform("shininess"), 5.0f);
    glUniform1f(shader->getUniform("specular_factor"), 0.2f);

    GLfloat matrix[16];
    glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
    glUniformMatrix4fv(shader->getUniform("modelview_matrix"), 1, GL_FALSE, matrix);
    GLfloat pmatrix[16];
    glGetFloatv(GL_PROJECTION_MATRIX, pmatrix);
    glUniformMatrix4fv(shader->getUniform("projection_matrix"), 1, GL_FALSE, pmatrix);
  }

  for (unsigned int i = 0; i < model.getTriangleModels().size(); i++)
  {
    // mesh 
    TriangleModel *triModel = model.getTriangleModels()[i];
    const IndexedFaceMesh &mesh = triModel->getParticleMesh();
    Visualization::drawTexturedMesh(pd, mesh, triModel->getIndexOffset(), surfaceColor);
  }
  if (shader)
    shader->end();
}

And calls Visualization::drawTexturedMesh which is the following :

template<class PositionData>
void Visualization::drawMesh(const PositionData &pd, const IndexedFaceMesh &mesh, const unsigned int offset, const float * const color)
{
    // draw mesh 
    const unsigned int *faces = mesh.getFaces().data();
    const unsigned int nFaces = mesh.numFaces();
    const Vector3r *vertexNormals = mesh.getVertexNormals().data();

    if (MiniGL::checkOpenGLVersion(3, 3))
    {
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_REAL, GL_FALSE, 0, &pd.getPosition(offset)[0]);
        glEnableVertexAttribArray(2);
        glVertexAttribPointer(2, 3, GL_REAL, GL_FALSE, 0, &vertexNormals[0][0]);
    }
    else
    {
        float speccolor[4] = { 1.0, 1.0, 1.0, 1.0 };
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, speccolor);
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 100.0f);
        glColor3fv(color);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glVertexPointer(3, GL_REAL, 0, &pd.getPosition(0)[0]);
        glNormalPointer(GL_REAL, 0, &vertexNormals[0][0]);
    }

    glDrawElements(GL_TRIANGLES, (GLsizei)3 * mesh.numFaces(), GL_UNSIGNED_INT, mesh.getFaces().data());

    if (MiniGL::checkOpenGLVersion(3, 3))
    {
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(2);
    }
    else
    {
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
    }
}

Assuming that I run the Demo with OpenGL 3.3 the if else isn't really required but I posted it anyway. So "translating" those functions to use VAO's and VBO's I have created the following.

void initVAO()
{
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glGenBuffers(3, vbo);
    glGenBuffers(1, &ibo);

    ParticleData &pd = model.getParticles();

    TriangleModel *triModel = model.getTriangleModels()[0];
    const IndexedFaceMesh &mesh = triModel->getParticleMesh();
    const unsigned int offset = triModel->getIndexOffset();

    const unsigned int *faces = mesh.getFaces().data();
    const unsigned int nFaces = mesh.numFaces();
    const Vector3r *vertexNormals = mesh.getVertexNormals().data();
    const Vector2r *uvs = mesh.getUVs().data();

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, pd.size(), &pd.getPosition(offset)[0],       GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_REAL, GL_FALSE, 0, BUFFER_OFFSET(0));
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, mesh.getUVs().size(), &uvs[0][0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_REAL, GL_FALSE, 0, BUFFER_OFFSET(0));
    glBindBuffer(GL_ARRAY_BUFFER, 0);


    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);              
    glBufferData(GL_ARRAY_BUFFER,mesh.getVertexNormals().size(),
    &vertexNormals[0][0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 3, GL_REAL, GL_FALSE, 0, BUFFER_OFFSET(0));
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizei)3 * mesh.numFaces(), mesh.getFaces().data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glBindVertexArray(0);
}

And I modified draw to this:

template<class PositionData> void drawTexturedMesh(const PositionData &pd, const IndexedFaceMesh &mesh, const unsigned int offset, const float * const color, GLuint text)
{
    // draw mesh 
    const unsigned int *faces = mesh.getFaces().data();
    const unsigned int nFaces = mesh.numFaces();
    const Vector3r *vertexNormals = mesh.getVertexNormals().data();
    const Vector2r *uvs = mesh.getUVs().data();

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

    //glDrawElements(GL_TRIANGLES, nFaces, GL_UNSIGNED_INT, BUFFER_OFFSET(0));

    glDrawElements(GL_TRIANGLES, (GLsizei)3 * mesh.numFaces(), GL_UNSIGNED_INT, mesh.getFaces().data());
}

-If the uncommented glDrawElements is used I get nothing, according to RenderDoc all Position values passed to shader are 0.

-If the commented one is used I get a shape which is not even nearly close to what the example draws.

Does anyone has any clue or tip on why this is happening? Or can you notice something different or wrong? Would appreciate it.

Thanks.

Edit: Le Comte du Merde-fou 's answer is indeed correct! I was giving the wrong size to the buffers. Still a wrong mesh is being generated.

I modified my code to this:

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3r) * pd.size(), &pd.getPosition(offset)[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_REAL, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, mesh.getUVs().size() * sizeof(Vector2r), &uvs[0][0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_REAL, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindBuffer(GL_ARRAY_BUFFER, 0);


glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ARRAY_BUFFER, mesh.getVertexNormals().size() * sizeof(Vector3r), &vertexNormals[0][0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_REAL, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizei)3 * mesh.numFaces(), mesh.getFaces().data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

And my draw function to this:

// draw mesh 
const unsigned int *faces = mesh.getFaces().data();
const unsigned int nFaces = mesh.numFaces();
const Vector3r *vertexNormals = mesh.getVertexNormals().data();
const Vector2r *uvs = mesh.getUVs().data();

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

glDrawArrays(GL_TRIANGLES, 0, nFaces);

It really has started getting under my skin... Is this a good porting according to the old code I posted???

I can provide more code if asked , but i cannot post it all since it's pretty big by now.

Thanks again.

Update So after banging my head long time, I decided to calm down. And I did what I hate to do . I opened up RenderDoc and started checking the vertices passed to GPU manually one-by-one in order to find why the mesh is screwed up. So in certain points i found values like vec3(0.97, 68548, 1) . Then I banged my head some more. And then I calmed down again and starting checking why those values show up. What I found out affects this line of code (on their side).

glVertexAttribPointer(0, 3, GL_REAL, GL_FALSE, 0, &pd.getPosition(offset[0]);

As you can see they use GL_REAL which is typedef as GL_FLOAT . Silly me they also have it typedefed as GL_DOUBLE... So my Positions vertex was defined as GL_DOUBLE while it was passed to the GPU as GL_FLOAT. Changing it to GL_DOUBLE almost gave me the expected result...

I still have an issue because some more triangles show up in the side of the mesh. I will update tomorrow to show the new mesh.

Thanks to Le Comte du Merde-fou 's again for the help in indicating that the size parameter was obviously wrong in GL_BUFFER_DATA.

\$\endgroup\$
2
\$\begingroup\$
glBufferData(GL_ARRAY_BUFFER, pd.size(), &pd.getPosition(offset)[0],       GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, mesh.getUVs().size(), &uvs[0][0], GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER,mesh.getVertexNormals().size(),
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizei)3 * mesh.numFaces(), mesh.getFaces().data(), GL_STATIC_DRAW);

Assuming that .size() here returns std::vector::size, the first three of these are wrong. The second parameter of a glBufferData call is the size of the data in bytes, not the number of vertices or indices.

Even if .size() returns the correct value, the fourth is also wrong for the same reason.

\$\endgroup\$
  • \$\begingroup\$ This, by the way, is why it's important to show all of your code: we have no way of knowing if your .size() call returns the correct value or not - If it wasn't for the fourth call (which suggests that the first three are also wrong), as well as the fact that this is a common-enough mistake, nobody would have been able to correct this error. \$\endgroup\$ – Maximus Minimus Oct 18 '16 at 19:35
  • \$\begingroup\$ Thanks for taking the time to answer. I am a little busy right now so i haven't had the time to check it but i will soon . \$\endgroup\$ – Davelis4 Oct 19 '16 at 8:52
  • \$\begingroup\$ I did an update if you want to check it out. \$\endgroup\$ – Davelis4 Oct 20 '16 at 18:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.