Home > Blockchain >  glBufferSubData calling multiple times overrides the first data
glBufferSubData calling multiple times overrides the first data

Time:08-20

I am using glBufferSubData to change positions of vertices. Everything works fine, when I call the code below once. If I run this whole code two times to add two pointclouds the vertex positions is updated only for the last geometry.

Please look at only following methods of the class, because the rest of the code is just a constructor to initialize the clouds:

void opengl_init() 
void opengl_draw()

I think something is wrong with winding to the vao buffer.

Question: How can I correctly update vertex positions glBufferSubData so that both pointclouds would move?

glBufferSubData

class pointcloud {
    public:
        int id = 0;
        std::vector<vertex> vertices;
        std::vector<unsigned int> indices;//pairs
        unsigned int vao, vbo, ibo;

        //individual polylines
        pointcloud(const std::vector<float>& coord, const std::vector<float>& colors)//, std::vector<Texture> textures
        {
            vertices.reserve(coord.size());
            indices.reserve((coord.size() - 1) * 2);

            for (int i = 0; i < coord.size(); i  = 3) {
                vertex vertex;
                vertex.position = glm::vec3(coord[i   0], coord[i   1], coord[i   2]);
                vertex.color = glm::vec3(colors[i   0], colors[i   1], colors[i   2]);
                vertices.emplace_back(vertex);
            }
            for (int i = 0; i < (coord.size() / 3) - 1; i  ) {
                indices.emplace_back(i   0);
                indices.emplace_back(i   1);
            }

            // now that we have all the required data, set the vertex buffers and its attribute pointers.
            //setup_polyline();
        }

        //merged polylines
        pointcloud(const std::vector<std::vector<float>>& coord, const std::vector<std::vector<float>>& colors)//, std::vector<Texture> textures
        {
            //reserve memory
            int v_count = 0;
            int i_count = 0;
            for (int i = 0; i < coord.size(); i  ) {
                v_count  = coord[i].size();
                i_count  = coord[i].size() - 1;
            }

            vertices.reserve(v_count);
            indices.reserve(i_count);

            //fill vertics and indices lists

            for (int i = 0; i < coord.size(); i  ) {
                for (int j = 0; j < coord[i].size(); j  = 3) {
                    vertex vertex;
                    vertex.position = glm::vec3(coord[i][j   0], coord[i][j   1], coord[i][j   2]);
                    vertex.color = glm::vec3(colors[i][j   0], colors[i][j   1], colors[i][j   2]);
                    vertices.emplace_back(vertex);
                }
            }

            v_count = 0;
            for (int i = 0; i < coord.size(); i  ) {
                for (int j = 0; j < (coord[i].size() / 3) - 1; j  ) {
                    //std::cout << v_count   j   0 << " " << v_count   j   1 << std::endl;
                    indices.emplace_back(v_count   j   0);
                    indices.emplace_back(v_count   j   1);
                }
                v_count  = (coord[i].size() / 3);
            }

            //std::cout << vertices.size() << std::endl;

            // now that we have all the required data, set the vertex buffers and its attribute pointers.
            //setup_polyline();
        }

        //// initializes all the buffer objects/arrays

        void opengl_init(bool draw_dynamic = true, int _id = 0)
        {
            id = _id   1;

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // init vertex-array and vertex-array-buffer
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //vertex array
            glGenVertexArrays(1, &vao);
            glBindVertexArray(vao);

            //bind vertex-array-buffer to the vertex-array
            glGenBuffers(1, &vbo);
            glBindBuffer(GL_ARRAY_BUFFER, vbo);

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //declare array with data or empty array depending how data will be displayed
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            auto type = !draw_dynamic ? GL_STATIC_DRAW : GL_STREAM_DRAW;
            glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertex), &vertices[0], type); // target | size | data (poinnting to first element e.g. glm::value_ptr(vertices[0])) | usage

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // set attributes that corresponds to layout id in the vertex shader
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // vertex Positions
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)0);
            // vertex normals
            glEnableVertexAttribArray(1);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)offsetof(vertex, color));

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //bind buffers vao | vbo | ibo
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //glBindVertexArray(0);
        }

        // render the mesh
        void opengl_draw(opengl_shaders::shader& shader, bool draw_dynamic = true)
        {
            //update
            //https://learnopengl.com/Advanced-OpenGL/Advanced-Data
            if (draw_dynamic) {
                for (auto& v : vertices)
                    v.position.y  = 0.001;
                glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(vertex), &vertices[0]);
            }

            //draw
            glBindVertexArray(vao);
            glDrawArrays(GL_POINTS, 0, vertices.size());
            //glBindVertexArray(0);
        }

        void opengl_clear(opengl_shaders::shader& shader) {
            glDeleteVertexArrays(1, &vao);
            glDeleteBuffers(1, &vbo);
            shader.delete_shader();
        }
    };

CodePudding user response:

glBufferSubData updates a subset of the data store of a buffer object that is currently bound to the specified target. You must bind the buffer before you can modify its data:

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(vertex), &vertices[0]);

The GL_ARRAY_BUFFER binding is a global state. This binding is maintained until it is changed. As for your code it works for 1 pointcloud, but it doesn't work if you have more than 1 pointcloud and vertex buffer.

  • Related