OpenGL C glfw 3 выдает ошибку 1282 в glGenVertexArrays

#c #opengl #glfw #glew

#c #opengl #glfw #glew

Вопрос:

Я пытаюсь написать свой первый игровой движок на C (хотя я уже сделал это на Java), я создал базовый класс mesh, который содержит целое число GLuint для массивов vao / Vertex и массив (на данный момент размером всего 2) для буферов / vbo, когда я пытаюсь вызвать свой конструктор в классе mesh, и я вызываю функцию glGenVertexArrays(1, amp; vaoId). ; Программа выходит из строя, в Visual Studio появляется окно с надписью

доступ нарушен во время выполнения пути на 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, amp;vaoId); // create VAO
    glBindVertexArray(vaoId); // bind VAO
    glGenBuffers(1, amp;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, amp;vaoId); // delete the vbos
      delete amp;vaoId;
      delete amp;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;
  }
  

это как-то связано с драйвером, компоновщиком или я допустил ошибку в своем коде?

Комментарии:

1. Возможно, это не связано, но… sizeof(vertices) в вашем Mesh конструкторе, вероятно, не выполняется то, что вы думаете.

2. Большое спасибо Rabbid76, теперь это работает!

Ответ №1:

Библиотека GLEW должна быть инициализирована glewInit после того, как контекст OpenGL станет текущим glfwMakeContextCurrent . С помощью.
Смотрите Инициализацию GLEW.

Сначала сделайте контекст OpenGL текущим, а затем инициализируйте 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;
}
  

Не имеет смысла вызывать какую-либо инструкцию OpenGL до того, как константа OpenGL станет текущей.
Удалить GLenum error = glGetError(); из initializeGLFW .


В конструкторе не указан размер массива Mesh::Mesh(float vertices[]) , sizeof(vertices) (это не java). Это размер указателя на массив, который равен 8 в 64-разрядной системе.

Использовать 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> amp;vertices);
    // [...]
};

Mesh::Mesh(const std::vector<float> amp;vertices) {

    // [...]

    noOfVertices = (int)vertices.size() / 3;
    glBufferData(GL_ARRAY_BUFFER, 
        vertices.size()*sizeof(float), vertices.data(), GL_STATIC_DRAW);
}
  

Количество элементов в std::vector фургоне, которое можно получить с помощью std::vector::size указателя на содержимое, может быть получено с помощью std::vector::data .
В вашем случае координата каждой вершины состоит из 3 компонентов (x, y и z), поэтому количество координат равно vertices.size() / 3 .
Вторым параметром для glBufferData должен быть размер буфера в байтах, который является vertices.size() * sizeof(float) .

Комментарии:

1. Вы должны проверить возвращаемое значение glewInit на GLEW_OK соответствие (=0). В настоящее время код возвращает false, когда glew удовлетворен, что прямо противоположно тому, что вы хотите.