Search code examples
c++openglglfwglew

OpenGL C++ glfw 3 glew Error 1282 on glGenVertexArrays


I'm trying to write my first game engine in C++ (I've arleady done it in java tho) I created a basic mesh class, which holds an integer of GLuint for the vao/Vertex Arrays, and an array (for the moment of just a size of 2) for the Buffers/vbos, When i try to call my constructor in the mesh class, and i call the function glGenVertexArrays(1, &vaoId); The program crashes, on visual studio a box shows up saying

access violated during the path execution on 0x00000000

Mesh.cpp:

#include "Mesh.h"

Mesh::Mesh(GLuint vaoid, int verticeslength) : vaoId(vaoid), 
verticesLength(verticeslength) {}

Mesh::Mesh(float vertices[]) {
    this->verticesLength = sizeof(vertices) / sizeof(float); // set the length of the vertices
    glGenVertexArrays(1, &vaoId); // create VAO
    glBindVertexArray(vaoId); // bind VAO
    glGenBuffers(1, &vboIds[0]); // allocate memory to VBO
    glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]); // bind vbo
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) / sizeof(float), 
    vertices, GL_STATIC_DRAW); // store data in vbo
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // store vbo in vao
  }

  Mesh::~Mesh() {
      glDisableVertexAttribArray(0); // disable the position vbo
      glDeleteBuffers(2, vboIds); // delete the vbos
      glDeleteVertexArrays(1, &vaoId); // delete the vbos
      delete &vaoId;
      delete &vboIds;
   }

   GLuint Mesh::getVaoId() { return vaoId; }

   int Mesh::getVerticesLength() { return verticesLength; }

   void Mesh::render() {
        glBindVertexArray(vaoId);
        glEnableVertexAttribArray(0);
        glDrawArrays(GL_TRIANGLES, 0, verticesLength);
        glDisableVertexAttribArray(0);
        glBindVertexArray(0);
    }

Mesh.h:

#ifndef Mesh_H
#define Mesh_H

#include <GL/glew.h>

 class Mesh {
 private:
     int verticesLength;
     GLuint vboIds[2]; // 0 = position, 1 = textureCoords
     GLuint vaoId;
 public:
     Mesh(GLuint vaoId, int verticesLength);
     Mesh(float vertices[]);
     ~Mesh();
     int getVerticesLength();
     GLuint getVaoId();
     void render();
 };

 #endif Mesh

Main.cpp:

 #include <iostream>
 #include "Mesh.h"
 #include <GLFW/glfw3.h>
 #include "GlfwUtils.h"
 #include "InputManager.h"

 #define WIDTH 800
 #define HEIGHT 600

 bool initializeGLFW();

 int main() {
     if (!initializeGLFW()) return EXIT_FAILURE;
     GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Scope Engine", 
     NULL, NULL);
     glfwMakeContextCurrent(window);
     if (!window) {
        std::cout << "Window creation failed" << std::endl;
        return EXIT_FAILURE; 
     }
     glfwSetKeyCallback(window, InputManager::key_callback);

     float vertices[] = {
     -0.5f, 0.5f, 0,
     -0.5f, -0.5f, 0,
      0.5f, -0.5f, 0,
      0.5f, -0.5f, 0,
      0.5f, 0.5f, 0,
      -0.5f, 0.5f, 0
      }; 

      Mesh* mesh = new Mesh(vertices); // gotta initalize the mesh!


     while (!glfwWindowShouldClose(window)) {
          mesh->render();
          std::cout << "Game Loop!" << std::endl;
          GlfwUtils::UpdateDisplay(window);
     }

     delete mesh;
     glfwDestroyWindow(window);
     return EXIT_SUCCESS;
 }

 bool initializeGLFW() {
     glewExperimental = GL_TRUE;
     if (!glewInit()) {
         std::cout << "Couldn't initalize OpenGL" << std::endl;
         return false;
     }
     GLenum error = glGetError();
     if (error != GL_NO_ERROR) { std::cout << "OpenGL error: " << error << std::endl; }
     if (!glfwInit()) {
         std::cout << "Couldn't initalize GLFW" << std::endl;
         return false;
     }
     glfwSetErrorCallback(GlfwUtils::error_callBack);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
     return true;
  }

is it something that has to do with the driver, with the linker or did i made an error in my code?


Solution

  • The GLEW library has to be initialized, by glewInit, after the OpenGL context has become current by glfwMakeContextCurrent.
    See Initializing GLEW.

    First make the OpenGL context current and then init GLEW:

    glfwMakeContextCurrent(window);
    if (!window) {
        std::cout << "Window creation failed" << std::endl;
        return EXIT_FAILURE; 
    }
    
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) {
        std::cout << "Couldn't initalize OpenGL" << std::endl;
        return false;
    }
    

    It doesn't make sens to call any OpenGL instruction before the OpenGL constex is made current.
    Remove GLenum error = glGetError(); from initializeGLFW.


    In the constructor Mesh::Mesh(float vertices[]), sizeof(vertices) is not the size of the array (this is not java). It is the size of an pointer to an array, which is 8 at a 64-bit system.

    Use std::vector:

    #include <vector>
    
    std::vector<float> vertices{
        -0.5f, 0.5f, 0,
        -0.5f, -0.5f, 0,
         0.5f, -0.5f, 0,
         0.5f, -0.5f, 0,
         0.5f, 0.5f, 0,
        -0.5f, 0.5f, 0
    }; 
    Mesh *mesh = new Mesh(vertices);
    
    class Mesh {
    private:
        int noOfVertices;
        // [...]
    
    public:
        Mesh::Mesh(const std::vector<float> &vertices);
        // [...]
    };
    
    Mesh::Mesh(const std::vector<float> &vertices) {
    
        // [...]
    
        noOfVertices = (int)vertices.size() / 3;
        glBufferData(GL_ARRAY_BUFFER, 
            vertices.size()*sizeof(float), vertices.data(), GL_STATIC_DRAW);
    }
    

    The number of elements in a std::vector van be get by std::vector::size a pointer to the content of can be get by std::vector::data.
    In your case, each vertex coordinate consists of 3 components (x, y and z), so the number of coordinates is vertices.size() / 3.
    The 2nd parameter to glBufferData has to be the size of the buffer in bytes, which is vertices.size() * sizeof(float).