glGenVertexArrays 上的 OpenGL C++ glfw 3 glew 错误 1282

Posted

技术标签:

【中文标题】glGenVertexArrays 上的 OpenGL C++ glfw 3 glew 错误 1282【英文标题】:OpenGL C++ glfw 3 glew Error 1282 on glGenVertexArrays 【发布时间】:2019-03-14 13:34:02 【问题描述】:

我正在尝试用 C++ 编写我的第一个游戏引擎(我已经在 java 中完成了它) 我创建了一个基本的网格类,它为 vao/Vertex 数组保存了一个整数 GLuint,为 Buffers/vbos 保存了一个数组(目前大小仅为 2), 当我尝试在网格类中调用我的构造函数时,我调用了函数 glGenVertexArrays(1, &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, &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;
  

是与驱动程序、链接器有关还是我的代码出错了?

【问题讨论】:

可能不相关,但是... sizeof(vertices) 在您的 Mesh 构造函数中可能不会像您认为的那样做。 非常感谢 Rabbid76,现在可以使用了! 【参考方案1】:

GLEW 库必须在 OpenGL 上下文由glfwMakeContextCurrent 变为当前状态后由glewInit 初始化。 见Initializing 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 constex 变为当前状态之前调用任何 OpenGL 指令是没有意义的。 从initializeGLFW 中删除GLenum error = glGetError();


在构造函数Mesh::Mesh(float vertices[])中,sizeof(vertices)不是数组的大小(这不是java)。它是指向数组的指针的大小,在 64 位系统中为 8。

使用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);

std::vector 中的元素个数可以通过std::vector::size 获取,指向内容的指针可以通过std::vector::data 获取。 在您的情况下,每个顶点坐标由 3 个分量(xyz)组成,因此坐标数为 vertices.size() / 3glBufferData 的第二个参数必须是缓冲区的大小(以字节为单位),即 vertices.size() * sizeof(float)

【讨论】:

您应该对照GLEW_OK (=0) 检查glewInit 的返回值。目前,当 glew 满意时,代码返回 false,这与您想要的完全相反。

以上是关于glGenVertexArrays 上的 OpenGL C++ glfw 3 glew 错误 1282的主要内容,如果未能解决你的问题,请参考以下文章

glGenVertexArrays 上的 OpenGL C++ glfw 3 glew 错误 1282

glGenVertexArrays 没有给出唯一的 vaos

了解顶点数组对象(glGenVertexArrays)

为啥使用 GTKGLArea 时在 PyOpenGL 中未定义 glGenVertexArrays

LWJGL OpenGL glGenVertexArrays() 错误:此函数不可用

glGenVertexArrays(1, &vao) 处的分段错误;