0
votes

actually Im a bit confused about using glBufferSubData and glMapBuffer. In my program I'm loading a mesh of Triangles so i created a Struct of Vertex and initialized my VertexBuffer with the data of whole mesh. I implemented ray-casting and ray-triangle intersection. What im trying to do is, if my cursor intersects with the mesh, the intersected triangle changes his color as long its get intersected. Its working at the moment but when I try to load a bigger mesh with 50.000+ Vertices it doesnt work anymore. I am updating my whole VBO with glBufferData because I dont understand how I can update only Color of Triangles with glBufferSubData. Can someone explain me how I can update only the specific part (e.g. Color) of my VBO ?

struct Vertex
{
    glm::vec3  Pos;
    glm::vec3  Normal;
    glm::vec3  Color;
};

VertexBuffer(void* vertices, size_t size)
{
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_DYNAMIC_DRAW);

    glBindVertexArray(0);
}

void Render()
{
    glBindVertexArray(vertexBuffer->VAO);
    glUseProgram(Fill->program);

    glUniformMatrix4fv(glGetUniformLocation(Fill->program, "model"), 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(glGetUniformLocation(Fill->program, "view"), 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(glGetUniformLocation(Fill->program, "projection"), 1, GL_FALSE, glm::value_ptr(proj));

    for (int j = 0; j < numVertices; j += 3){

        if (intersectPlane(this->Vertices[j], this->Vertices[j + 1], this->Vertices[j + 2], ray, orig)){

            glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->buffer);
            this->Vertices[j].Color = glm::vec3(1.0, 0.0, 0.0);
            this->Vertices[j + 1].Color = glm::vec3(1.0, 0.0, 0.0);
            this->Vertices[j + 2].Color = glm::vec3(1.0, 0.0, 0.0);
            glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vertex), Vertices, GL_DYNAMIC_DRAW);
        }
        else{
            glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->buffer);
            this->Vertices[j].Color = glm::vec3(0.695f, 0.695f, 0.695f);
            this->Vertices[j + 1].Color = glm::vec3(0.695f, 0.695f, 0.695f);
            this->Vertices[j + 2].Color = glm::vec3(0.695f, 0.695f, 0.695f);
            glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vertex), Vertices, GL_DYNAMIC_DRAW);
        }
    }

    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->buffer);

    GLuint posLoc = glGetAttribLocation(Fill->program, "Position");
    GLuint norm = glGetAttribLocation(Fill->program, "Normal");
    GLuint colo = glGetAttribLocation(Fill->program, "Color");

    glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Pos));
    glVertexAttribPointer(norm, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Normal));
    glVertexAttribPointer(colo, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Color));

    glEnableVertexAttribArray(posLoc);
    glEnableVertexAttribArray(norm);
    glEnableVertexAttribArray(colo);

        glDrawArrays(GL_TRIANGLES, 0, numVertices);
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glUseProgram(0);

}
1
If when your mesh is too big the app crashes or doesn't work, it's probably due to not enough GPU memory. You should draw in "chunks" of data, and swap buffers only when all of them are done.Ripi2
Hmm Do you think its maybe because I am checking 20.000 triangles for intersection and loading the whole buffer everytime new ? Because otherwise it wouldnt even render the mesh without intersection it the data is too big. Am i wrong?Luqman Akash
Define what is "doesn't work". If your GPU doesn't have enough memory it will not receive more data and likely will not draw anything. 20000 triangles is not much memory.Ripi2
Basically it renders the model extreme slow, I cant even move my mouseLuqman Akash
Because you're calling glBufferdata thousands of times. And every time it updates the whole buffer. Try doing this after you've done with filling 'Vertices' , i.e. outside the for-loop.Ripi2

1 Answers

1
votes

glBufferSubData updates part (or the whole) of the buffer without the need to recreate it.

In your case you can do some calculus to know the position in bytes inside the buffer (so called "offset") of the edge currently selected, and update the buffer just for that pair of vertices.

glMapBuffer gives you a (virtual) pointer to the buffer. You can read or write to that address directly using your C/C++ functions. Be aware to "unmap" when done.

Now, your buffer layout is Pos,Normal,Color and repeat. So: PxPyPzNxNyNzCrCgCbPxPyPzNxNyNzCrCgCbPxPyPzNxNyNzCrCgCb... "interleaved data". You must be carefull with the positions (bytes) you update.