Opengl线程1:EXC_BAD_ACCESS(代码= 1,地址= 0x0)

时间:2017-12-09 22:34:35

标签: c++ opengl glfw

我使用GLFW版本2制作OpenGL视频游戏。我收到一个我不明白的错误

以下代码为:

//
//  GameWindow.cpp
//  RocketGame
//
//  Created by Vaibhav Malhotra on 12/5/17.
//  Copyright © 2017 Vaibhav Malhotra. All rights reserved.
//

#include "GameWindow.hpp"

typedef struct
{
    GLfloat positionCoordinates[3];
    GLfloat textureCoordinates[2];
} vertexData;

#define Square_Size 100

vertexData vertices[] = {
    {{0.0f,0.0f,0.0f}, {0.0f,0.0f}},
    {{Square_Size,0.0f,0.0f},{1.0f,0.0f}},
    {{Square_Size,Square_Size,0.0f},{1.0f,1.0f}},
    {{0.0f,Square_Size,0.0f},{0.0f,1.0f}}
};

void GameWindow::setRunning(bool newRunning)
{
    _running = newRunning;
}

bool GameWindow::getRunning()
{
    return _running;
}

GLuint GameWindow::loadAndBufferImage(const char *filename)
{
    GLFWimage imageData;
    glfwReadImage(filename, &imageData, NULL);
    GLuint textureBufferID;
    glGenTextures(1, &textureBufferID);
    glBindTexture(GL_TEXTURE_2D, textureBufferID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageData.Width, imageData.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData.Data);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glfwFreeImage(&imageData);

    return textureBufferID;    
}

GameWindow::GameWindow(bool running):_running(running),_height(800),_width(800*16/9),_vertexBufferID(0)
{        
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glViewport(0.0f, 0.0f, _width, _height);

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0, _width, 0, _height);
    glMatrixMode(GL_MODELVIEW);

    glGenBuffers(1, &_vertexBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, sizeof(vertexData), (GLvoid *) offsetof(vertexData, positionCoordinates));

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, sizeof(vertexData), (GLvoid *) offsetof(vertexData, textureCoordinates));

    _textureBufferID = loadAndBufferImage("rocket.tga");    
}

void GameWindow::render()
{
    glClear(GL_COLOR_BUFFER_BIT);

    //glColor3f(1.0f, 0.0f, 0.0f);
    glDrawArrays(GL_QUADS, 0, 4);

    glfwSwapBuffers();        
}

void GameWindow::update()
{

}

在render函数下,代码glDrawArrays(GL_QUADS, 0, 4);返回运行时错误:

  

线程1:EXC_BAD_ACCESS(代码= 1,地址= 0x0)。

对于输出我只是得到一个黑屏。

为什么会出现这个错误?

2 个答案:

答案 0 :(得分:0)

  

在render函数下代码glDrawArrays(GL_QUADS,0,4);返回运行时错误线程1:EXC_BAD_ACCESS(代码= 1,地址= 0x0)。

glDrawArrays上的内存访问冲突通常暗示了VBO或类似存储对象的某些问题。

据我所知,您的代码存在三个问题:

  • 当您需要在glEnableClientState之前的每一帧调用时,您只需拨打gl*Pointer及其相应的glDrawArrays次来电。如果您只想打电话给他们一次,请查看Vertex Array Objects (VAOs),虽然这些仅在OpenGL 3开始后可用。请记住,当您移动glEnableClientState来电时,您必须确保您的缓冲区再次与glBindBuffer绑定。
  • 每个客户端状态都有相应的gl*Pointer电话。您对glVertexPointer正确使用GL_VERTEX_ARRAY,但对于GL_TEXTURE_COORD_ARRAY,您需要glTexCoordPointer
  • 您的glEnableClientState来电缺少相应的glDisableClientState来电,需要在glDrawArrays来电后按与拨打电话相反的顺序拨打电话。

正如旁注所示,不推荐使用GLU库。您gluOrtho2D来电似乎是唯一依赖它的实例,可以轻松替换为:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, _width, 0, _height, -1.0f, 1.0f);

答案 1 :(得分:0)

您在glDrawArrays中遇到异常,因为它试图读取地址0处的内存,这是您的代码实际指定的内容。

GL的纹理坐标数组指针是initializez到NULL而没有VBO。由于您使用旧版GL,因此将其解释为客户端内存地址。现在您启用GL_TEXCOORD_ARRAY但从未实际设置glTexCoordPointer,因此它会保留NULL

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vertexData), (GLvoid *) offsetof(vertexData, textureCoordinates));

快速解决方案当然是不要通过指向纹理坐标来覆盖顶点数组指针状态,而是通过glTexCoordPointer指定texcoord数组指针。

真正的解决方案是放弃传统的GL,这个GL已经被淘汰了,现在已经过去十年了,转而使用"现代"使用GL 3.2核心简介或更高版本的OpenGL。