Modern OpenGL: VAO binding causes access violation

428 Views Asked by At

I'm trying to learn some basic OpenGL 3D programming. I'm following this guide and some youtube videos. In particular I've reached the chapter which talks about model loading (using Assimp). I've more or less managed to make something work using the guide's code, then I tried to write a more structured program following a series of videos on youtube, in particular this one but when I finished and run the program, it stops, without showing anything if not a black screen. When running the program using the visual studio debugger, I get the following error:

Exception thrown at 0x00007FF9DABA7610 (nvoglv64.dll) in "program name.exe" 0xC0000005: Access violation reading location 0x0000000000000000

The code that generates the exception is

glBindVertexArray(this->VAO);
glDrawElements(GL_TRIANGLES, (this->indices).size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

the first line. I've tried searching for some similar errors on the internet, hoping for answers, and I found that these errors are often caused by a bad configured VAO, in particular this site suggests to carefully check the portion of code where the VAO is configured, which I did, and it seems fine. Moreover, when I try to use the same code to render a model from an array of vertices, it works fine. The method where the VAO is configured is the following one:

void Mesh::setup() {

    // create buffers and array objects
    glGenVertexArrays(1, &(this->VAO));
    glGenBuffers(1, &(this->VBO));
    glGenBuffers(1, &(this->EBO));

    // configure buffers
    glBindVertexArray(this->VAO);
    {

        // VBO
        glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
        glBufferData(GL_ARRAY_BUFFER, (this->vertices).size() * sizeof(Vertex), &(this->vertices)[0], GL_STATIC_DRAW);

        // data configuration
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Vertex::position));
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Vertex::normal));
        glEnableVertexAttribArray(2);
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Vertex::textureCoordinates));

        // EBO
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, (this->indices).size() * sizeof(unsigned int), &(this->indices)[0], GL_STATIC_DRAW);

    }
    glBindVertexArray(0);

}

where Vertex is a custom structure of the form

typedef struct Vertex {

    glm::vec3 position;
    glm::vec3 normal;
    glm::vec2 textureCoordinates;

    // convert an array of vertices into a vector of struct Vertex vertices
    static std::vector<struct Vertex> genList(float* vertices, int nrVertices);

} Vertex;

My program is pretty much the same as the one showed on the youtube video (the classes are pretty much identical, the file tree structure might differ a bit). As I can't write all the program, I will explain its structure:

There is a model class which loads a model from a file or from a class defined in the project:

  • Model(glm::vec3 position, glm::vec3 size) initializes the class variables
  • void loadModel(std::string path) loads a model from a file: it uses assimp to convert a model file into a aiScene* object from which the specific data is retrieved via: void processNode(aiNode* node, const aiScene* scene) (a recursive function which iterates through each Assimp's node), Mesh processMesh(aiMesh* mesh, const aiScene* scene) (a function called by processNode which converts the information inside aiMesh into a custom Mesh object that I will describe later), and std::vector<Texture> loadTexture(aiMaterial* material, aiTextureType type) (a function called by processMesh which retrieves all the textures of a material associated to a mesh; it returns a custom Texture object, which I will describe later)
  • void render(Shader* sahder) (Shader is a custom class that manages shaders) draws the model on the screen. Each mesh of the model is stored in a class variable and has a render method called by Model::render.
  • void init() it is a method that is meant to be overridden by a child class. In particular, for example, I've defined a class Cube : public Model which has a Cube constructor (that calls the Model super-constructor) and has an init method where the vertex data of the cube -initialized using an array then converted to a Vertex structure -, indices and textures are used to initialize a Mesh object, then stored into a meshes list inside Model class. Using this approach the cube model is perfectly rendered without any exception

There is a Mesh class which converts an Assimp's aiMesh* object into a custom object:

  • Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture> textures = {}) calls the void Mesh::setup() method
  • void setup() it is the method I've included before: it configures the VAO, EBO and VBO (which, I repeat, work perfectly with the cube class)
  • void render(Shader* shader) sets the correct value for texture units (distinguishing between diffuse and specular textures) and binds the textures. Then draw each vertex using glDrawElements, these are the lines that generate the exception.

There is a Texture class which loads textures and stores textures' parameters:

  • Texture(std::string path, std::string directory, aiTextureType type) initializes class variables
  • void generate() generates an OpenGL texture object
  • void load(bool flipv) loads the texture from an image (using stb library) and configures texture object parameters (e.g. wrap S or T and so on)
  • void bind() binds the texture to GL_TEXTURE_2D

In the main function I declared a Model object giving a path (which loaded succcesfully according to the debug std::cout statements I've inserted):

Model model(glm::vec3(0.0f), glm::vec3(1.0f))
model.loadModel("path");

Then in the mainloop, after enabling the shader:

model.render(&objectShader);

As I said before, I've checked my code and it seems to have no errors. I've searched online but couldn't find anything. I can't even think of a way to test the program and see where does this error come from. Have you go any suggestion on how to avoid this issue?

Thanks in advance for your effort and time in answering me! I don't really know if what I've explained about the program and what I've included about the code is enough. If you have any requests on the code or on how the program works that might help you find the issue, please ask me and I will edit this question.

0

There are 0 best solutions below