openGL: glGenVertexArrays 访问位置0x00000000时发生访问冲突

3

我想自学OpenGL,所以买了一本关于OpenGL的书,第一章有示例代码,我尝试运行它,但出现了错误。在第17行(glGenVertexArrays(NumVAOs, VAOs);)和第18行(glBindVertexArray(VAOs[Triangles]);)时,VS 2013 Ultimate报错,准确地说是“Unhandled exception at 0x77350309 in openGL_3.exe: 0xC0000005: Access violation executing location 0x00000000.”。因此,我认为这可能与内存有关,但我不知道具体原因。有人能帮我吗?

#include <iostream>
using namespace std;

#include <vgl.h>
#include <LoadShaders.h>


enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;

void init(void)
{
    glGenVertexArrays(NumVAOs, VAOs);
    glBindVertexArray(VAOs[Triangles]);
    GLfloat vertices[NumVertices][2] = {
        { -0.90, -0.90 }, // Triangle 1
        { 0.85, -0.90 },
        { -0.90, 0.85 },
        { 0.90, -0.85 }, // Triangle 2
        { 0.90, 0.90 },
        { -0.85, 0.90 }
    };
    glGenBuffers(NumBuffers, Buffers);
    glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),
    vertices, GL_STATIC_DRAW);
    ShaderInfo shaders[] = {
        { GL_VERTEX_SHADER, "triangles.vert" },
        { GL_FRAGMENT_SHADER, "triangles.frag" },
        { GL_NONE, NULL }
    };
    GLuint program = LoadShaders(shaders);
    glUseProgram(program);
    glVertexAttribPointer(vPosition, 2, GL_FLOAT,
    GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(vPosition);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBindVertexArray(VAOs[Triangles]);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    glFlush();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutInitWindowSize(512, 512);
    glutInitContextVersion(4, 3);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutCreateWindow(argv[0]);
    if (glewInit()) {
        cerr << "Unable to initialize GLEW ... exiting" << endl;
        exit(EXIT_FAILURE);
    }
    init();
    glutDisplayFunc(display);
    glutMainLoop();
}
3个回答

5

0

你确定在调用glewInit()之前请求版本4.3吗?每个版本>= 3.0都需要WGL_ARB_create_context(Windows)/GLX_ARB_create_context(Linux)扩展。

通常,要创建"现代"的OpenGL上下文(3.0+),需要执行以下操作:

  1. 创建临时上下文并将其设置为当前上下文。
  2. 初始化扩展(手动或使用像GLEWGLFW这样的加载器)。
  3. 请求所需版本(如果创建版本3.2或更高版本,并且存在WGL_ARB_create_context_profile/GLX_ARB_create_context_profile)。
  4. 1.中删除临时上下文并绑定新上下文。

您可能想查看:

我不知道在GLUT中请求上下文版本和GLEW初始化之间的联系是什么(我经常使用GLEW,但是上下文的创建是我手动完成的,使用特定于平台的API),但显然,当您调用glGenVertexArrays时,新的OpenGL API指针未初始化。这就是您错误的原因-您尝试通过指针调用函数,而该指针为NULL


freeglut(以及整个“glutInitContextVersion”API)只是freeglut特定扩展中的一部分,不在其他GLUT版本中存在。就像GLFW、SDL或类似库一样,它将以平台抽象的方式处理上下文创建。实际上,这种方法没有任何根本性问题,除了在核心配置文件中尝试使用glewInit()而没有设置glewExperimental=GL_TRUE - derhass

0

我基本上同意Sga的答案,建议在调用glewInit()之前设置glewExperimental=GL_TRUE。如果不设置此选项,GLEW将无法在核心配置文件中初始化。

然而,glewInit()没有失败的事实意味着OP根本没有得到核心配置文件(或者GLEW已经被修复,但这更多是理论上的可能性)。

我已经查看了freeglut对问题“Where is the documentation for glutInitContextVersion?”中(freeglut特定的)glutInitContextVersion API的实现,那时的结论可能对这种情况有所帮助。引用自己的话:

从查看代码(当前稳定版本2.8.1),可以看到freeglut实现了以下逻辑:如果实现无法满足版本约束条件,但支持ARB_create_context扩展,则会生成一些错误并且不会创建上下文。然而,如果请求一个版本,但实现甚至不支持相关扩展,则会创建一个传统的GL上下文,有效地忽略版本请求。
因此,根据报告的行为,我推断OP只得到了一个传统的上下文,可能是Microsoft默认的OpenGL 1.1实现。
这也解释了为什么即使在glewInit()成功后,glGenVertexArrays()仍然是一个空指针:该扩展不支持此上下文。
您应该在glutCreateWindow()调用之后立即检查glGetString(GL_VERSION)和glGetString(GL_RENDERER)实际返回的内容。根据输出,您可能需要检查/更新您的图形驱动程序,或者您可能会发现您的GPU根本无法支持现代GL。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接