Opengl 线程 1:EXC_BAD_ACCESS(代码=1,地址=0x0)
Opengl Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
我正在使用 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()
{
}
在渲染函数下,代码 glDrawArrays(GL_QUADS, 0, 4);
返回运行时错误:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0).
对于输出,我只是得到一个黑屏。
为什么会出现这个错误?
Under the render function the code glDrawArrays(GL_QUADS, 0, 4); is returning a runtime error Thread 1: EXC_BAD_ACCESS (code=1, address=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);
您在 glDrawArrays
中遇到异常,因为它试图读取地址 0 处的内存,这是您的代码实际指定的地址。
GL 的纹理坐标数组指针初始化为 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 3.2 核心配置文件切换到 "modern" OpenGL 或以上。
我正在使用 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()
{
}
在渲染函数下,代码 glDrawArrays(GL_QUADS, 0, 4);
返回运行时错误:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0).
对于输出,我只是得到一个黑屏。
为什么会出现这个错误?
Under the render function the code glDrawArrays(GL_QUADS, 0, 4); is returning a runtime error Thread 1: EXC_BAD_ACCESS (code=1, address=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);
您在 glDrawArrays
中遇到异常,因为它试图读取地址 0 处的内存,这是您的代码实际指定的地址。
GL 的纹理坐标数组指针初始化为 NULL
并且没有 VBO。由于您使用旧版 GL,因此这将被解释为客户端内存地址。现在你启用 GL_TEXCOORD_ARRAY
但从未真正设置 glTexCoordPointer
,所以它保持 NULL
:
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vertexData), (GLvoid *) offsetof(vertexData, textureCoordinates));
快速解决方案当然是不要通过指向纹理坐标来覆盖顶点数组指针状态,而是通过 glTexCoordPointer
.
真正的 解决方案是放弃十年来已弃用的旧版 GL,并使用 GL 3.2 核心配置文件切换到 "modern" OpenGL 或以上。