简体   繁体   中英

Vertex Buffer Abstraction in OpenGl

I have been trying to write some classes to abstract OpenGl. So far I have written a VertexArray class that uses template functions which are working fine so far. However I have encountered problems with my VertexBuffer class that I have not been capable of fixing. C++ and OpenGl are still fairly new to me so the solution might be pretty simple.

Whenever I try to replace the Vertex Buffer creation code with the constructor of the VertexBuffer class things go wrong and nothing is displayed on the screen even though the code of the constructor and the one directly written in the Mesh class are (I believe) the same.

Here is the code:

VertexBuffer.h:

#ifndef VERTEX_BUFFER_H
#define VERTEX_BUFFER_H

class VertexBuffer {
private:
public:
    unsigned int ID;
    VertexBuffer(const void* data, unsigned int size);
    VertexBuffer();
    ~VertexBuffer();
    void bind();
    void unbind();
};

#endif

VertexBuffer.cpp:

#include "VertexBuffer.h"

#define GLEW_STATIC
#include <GL/glew.h>
#include <iostream>

VertexBuffer::VertexBuffer(const void* data, unsigned int size) {
    glGenBuffers(1, &ID);
    glBindBuffer(GL_ARRAY_BUFFER, ID);
    glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);

    std::cout << "ID = " << ID << std::endl;
    std::cout << "data = " << data << std::endl;
    std::cout << "size = " << size << std::endl << std::endl;
}

VertexBuffer::VertexBuffer() {}

VertexBuffer::~VertexBuffer() {
    glDeleteBuffers(1, &ID);
}

void VertexBuffer::bind() {
    glBindBuffer(GL_ARRAY_BUFFER, ID);
}

void VertexBuffer::unbind() {
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

The Mesh constructor where I have been trying to implement it via the class:

Mesh::Mesh(std::vector<Vertex> vertices) {

    model = glm::mat4(1.0f);
    indicesSize = vertices.size();

    // generate vertex array object
    va = VertexArray();
    va.bind();

    //============================================================

    //This code works:
    /*
    glGenBuffers(1, &vb.ID);
    glBindBuffer(GL_ARRAY_BUFFER, vb.ID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
    */

    //------------------------------------------------------------

    //This code does not work:
    vb = VertexBuffer(&vertices[0], sizeof(Vertex) * vertices.size());

    //============================================================

    // points
    va.push<float>(3, 9, false);

    // colors
    va.push<float>(3, 9, false);

    // normals
    va.push<float>(3, 9, false);
};

I would be happy if anyone can help me. Thanks in advance!

You have to store vb in some kind of smart pointer or add move semantics to VertexBuffer .

vb = VertexBuffer(&vertices[0], sizeof(Vertex) * vertices.size());
     ^^^ [1]

in [1] temporary VertexBuffer is created, then by operator = , the member ID is copied in shallow way into vb and finally at the end of expression temporary VertexBuffer is destroyed with deleting generated ID (by destructor of temporary instance), which is still stored in vb , but it is not valid anymore.

Solution with move semantics could be like:

class VertexBuffer {
    std::unique_ptr<unsigned int> ID;
public:
    VertexBuffer& operator=(VertexBuffer&& other) {
        ID = std::move(other.ID);
        return *this;
    }

    ~VertexBuffer() {
        if (ID)
            glDeleteBuffers(1, ID.get() );
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM