在我尝试学习CG和OpenGL之后,我找到了the book "Interactive Computer Graphics",我觉得这对初学者来说是个不错的选择。现在,我正在尝试按照书中的理论创建3D中所谓的Sierpinski垫片。该项目位于Xcode 4.5中,可以很好地构建并运行,但是当它到达glEnable(GL_DEPTH_TEST)
行时,它会崩溃并且Xcode会显示错误Exc_bad_access
。
以下是我的代码:
//
// main.cpp
// SierpinskiGasket
//
// Created by Federico Martinez on 24.01.13.
// Copyright (c) 2013 ParallelDev. All rights reserved.
//
#include "Angel.h"
const int NumTimesToSubdivide = 3;
const int NumTriangles = 27; // 3^5 triangles generated
const int NumVertices = 3 * NumTriangles;
vec3 points[NumVertices];
vec3 base_colors[4] = {
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0),
vec3(0.0, 0.0, 0.0)
};
vec3 colors[NumVertices];
int Index = 0;
int colorIndex;
//----------------------------------------------------------------------------
void triangle( const vec3& a, const vec3& b, const vec3& c ){
colors[Index] = base_colors[colorIndex];
points[Index++] = a;
colors[Index] = base_colors[colorIndex];
points[Index++] = b;
colors[Index] = base_colors[colorIndex];
points[Index++] = c;
}
//----------------------------------------------------------------------------
void tetra(vec3 a, vec3 b, vec3 c, vec3 d){
colorIndex = 0;
triangle(a, b, c);
colorIndex = 1;
triangle(a, c, d);
colorIndex = 2;
triangle(a, d, b);
colorIndex = 3;
triangle(b, d, c);
}
//----------------------------------------------------------------------------
void divide_tetra(const vec3& a, const vec3& b, const vec3& c, const vec3& d, int count){
if ( count > 0 ) {
vec3 mid[6];
mid[0] = (a+b) / 2.0;
mid[1] = (a+c) / 2.0;
mid[2] = (a+d) / 2.0;
mid[3] = (b+c) / 2.0;
mid[4] = (c+d) / 2.0;
mid[5] = (b+d) / 2.0;
divide_tetra(a, mid[0], mid[1], mid[2], count-1);
divide_tetra(mid[0], b, mid[3], mid[5], count-1);
divide_tetra(mid[1], mid[3], c, mid[4], count-1);
divide_tetra(mid[2], mid[5], mid[5], d, count-1);
}else {
tetra(a, b, c, d); // draw tetrahedron at end of recursion
}
}
//----------------------------------------------------------------------------
void
init( void )
{
vec3 vertices[4] = {
vec3(-1.0, -1.0, -1.0),
vec3(1.0, -1.0, -1.0),
vec3(0.0, 1.0, -1.0),
vec3(0.0, 0.0, 1.0)
};
// Subdivide the original triangle
divide_tetra(vertices[0], vertices[1], vertices[2], vertices[3], NumVertices);
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(points)+sizeof(colors), NULL, GL_STATIC_DRAW );
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vertex.glsl", "fragment.glsl" );
glUseProgram( program );
// Initialize the vertex position attribute from the vertex shader
GLuint loc = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( loc );
glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0) );
GLuint loc2 = glGetAttribLocation(program, "vColor");
glEnableVertexAttribArray(loc2);
glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(points)));
glClearColor( 1.0, 1.0, 1.0, 1.0 ); /* white background */
}
void display(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glFlush();
}
int main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_3_2_CORE_PROFILE | GLUT_DEPTH);
glEnable(GL_DEPTH_TEST);
glutInitWindowSize(640, 480);
glutCreateWindow("Sierpinski Gasket Recursive");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
大部分代码来自本书。文件Angel.h
和InitShader.cpp
提供了大多数着色器和矢量实用程序,它们由本书的作者提供。
这Exc_bad_access
是什么意思?代码中是否有任何可能导致此问题的错误?
更新GDB Stacktrace
(gdb) t a a bt
Thread 5 (process 60424):
#0 0x00007fff8ecce6d6 in __workq_kernreturn ()
#1 0x00007fff8e5fdeec in _pthread_workq_return ()
#2 0x00007fff8e5fdcb3 in _pthread_wqthread ()
#3 0x00007fff8e5e8171 in start_wqthread ()
Thread 4 (process 60424):
#0 0x00007fff8ecce6d6 in __workq_kernreturn ()
#1 0x00007fff8e5fdeec in _pthread_workq_return ()
#2 0x00007fff8e5fdcb3 in _pthread_wqthread ()
#3 0x00007fff8e5e8171 in start_wqthread ()
Thread 3 (process 60424):
#0 0x00007fff8ecce6d6 in __workq_kernreturn ()
#1 0x00007fff8e5fdeec in _pthread_workq_return ()
#2 0x00007fff8e5fdcb3 in _pthread_wqthread ()
#3 0x00007fff8e5e8171 in start_wqthread ()
Thread 2 (process 60424):
#0 0x00007fff8ecced16 in kevent ()
#1 0x00007fff8d6b0dea in _dispatch_mgr_invoke ()
#2 0x00007fff8d6b09ee in _dispatch_mgr_thread ()
Thread 1 (process 60424):
#0 0x00007fff8ecf03d7 in glEnable ()
#1 0x000000010000212a in main (argc=1, argv=0x7fff5fbff800) at /Users/BRabbit27/Documents/COURSERA/ComputerGraphicsBook/SierpinskiGasket3D/SierpinskiGasket3D/main.cpp:129
更新LLDB Stacktrace
(lldb) bt all
* thread #1: tid = 0x2e03, 0x00007fff8ecf03d7 libGL.dylib`glEnable + 15, stop reason = EXC_BAD_ACCESS (code=1, address=0x248)
frame #0: 0x00007fff8ecf03d7 libGL.dylib`glEnable + 15
frame #1: 0x000000010000212a SierpinskiGasket3D`main + 58 at main.cpp:129
frame #2: 0x00007fff8fd5e7e1 libdyld.dylib`start + 1
thread #2: tid = 0x3103, 0x00007fff8ecced16 libsystem_kernel.dylib`kevent + 10
frame #0: 0x00007fff8ecced16 libsystem_kernel.dylib`kevent + 10
frame #1: 0x00007fff8d6b0dea libdispatch.dylib`_dispatch_mgr_invoke + 883
frame #2: 0x00007fff8d6b09ee libdispatch.dylib`_dispatch_mgr_thread + 54
thread #3: tid = 0x3203, 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
frame #0: 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
frame #1: 0x00007fff8e5fdeec libsystem_c.dylib`_pthread_workq_return + 25
frame #2: 0x00007fff8e5fdcb3 libsystem_c.dylib`_pthread_wqthread + 412
frame #3: 0x00007fff8e5e8171 libsystem_c.dylib`start_wqthread + 13
thread #4: tid = 0x3303, 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
frame #0: 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
frame #1: 0x00007fff8e5fdeec libsystem_c.dylib`_pthread_workq_return + 25
frame #2: 0x00007fff8e5fdcb3 libsystem_c.dylib`_pthread_wqthread + 412
frame #3: 0x00007fff8e5e8171 libsystem_c.dylib`start_wqthread + 13
thread #5: tid = 0x3403, 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
frame #0: 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
frame #1: 0x00007fff8e5fdeec libsystem_c.dylib`_pthread_workq_return + 25
frame #2: 0x00007fff8e5fdcb3 libsystem_c.dylib`_pthread_wqthread + 412
frame #3: 0x00007fff8e5e8171 libsystem_c.dylib`start_wqthread + 13
答案 0 :(得分:5)
简短回答:在glutCreateWindow
之后移动任何OpenGL调用。
基本原理:OpenGL使用一种名为 context 的数据结构,它存储了所有内部状态:纹理,着色器,状态设置等。每个OpenGL函数在启动之前都会访问当前上下文操作。创建上下文是您正在使用的窗口系统的函数,或者在GLUT的情况下,glutCreateWindow
函数。 OP中发生的事情是OpenGL实现实际上是解除引用NULL指针并导致异常。
这对于OpenGL实现来说是不好的形式 - 如果没有当前的上下文,大多数实现通常会立即返回任何OpenGL函数。