Swift:glDrawElements崩溃,EXC_BAD_ACCESS代码= 1

时间:2015-12-14 10:42:27

标签: ios swift opengl-es

我正在通过此guide在iOS上学习 OpenGL ,我想在 swift 上实现所有内容。所以,有一些代码我正在崩溃:

记忆结构:

private struct Vertex {
    var Position: (GLfloat, GLfloat, GLfloat)
    var Color: (GLfloat, GLfloat, GLfloat, GLfloat)
}

private static var Vertices = [
    Vertex(Position: (1, -1, 0) , Color: (1, 0, 0, 1)),
    Vertex(Position: (1, 1, 0)  , Color: (0, 1, 0, 1)),
    Vertex(Position: (-1, 1, 0) , Color: (0, 0, 1, 1)),
    Vertex(Position: (-1, -1, 0), Color: (0, 0, 0, 1))
]

private static var Indices: [GLubyte] = [
    0, 1, 2,
    2, 3, 0
]

创建顶点缓冲区:

var vertexBuffer = GLuint()
glGenBuffers(1, &vertexBuffer)
glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer)
glBufferData(GLenum(GL_ARRAY_BUFFER), Vertices.size, Vertices, GLenum(GL_STATIC_DRAW))

var indexBuffer = GLuint()
glGenBuffers(1, &indexBuffer)
glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer)
glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), Indices.size, Indices, GLenum(GL_STATIC_DRAW))

设置内存偏移:

var positionPtr = 0
glVertexAttribPointer(GLuint(positionSlot), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(strideofValue(Vertex)), &positionPtr)
var colorPtr = strideof(GLfloat) * 3
glVertexAttribPointer(GLuint(colorSlot), 4, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(strideofValue(Vertex)), &colorPtr)

崩溃(试图绘制):

var startPtr = 0
// EXC_BAD_ACCESS code=1 here!
glDrawElements(GLenum(GL_TRIANGLES), GLsizei(Indices.count / 3), GLenum(GL_UNSIGNED_BYTE), &startPtr)

编译所有着色器时没有任何错误,glClear()绘制得很好,所以我想我的问题与VBO有关。

在这里我如何计算数组的大小:

extension Array
{
    var size: Int {
        get { return self.count * strideof(Element) }
    }
}

UPD:我正在使用OpenGLES 2.0。

1 个答案:

答案 0 :(得分:2)

4个月前,我已经向你学习了数量。我试图将它从objective-c转换为swift,直到在图片下方绘制矩形。

现在我运行它并转换为Swift 2.1。它仍然可以工作,并在下面显示相同的图像。

enter image description here

这里是我的代码(方法setupVBO,渲染和结构)

// Track of all our per-vertex information (currently just color and position)
struct Vertex {
    var Position: (CFloat, CFloat, CFloat)
    var Color: (CFloat, CFloat, CFloat, CFloat)
}

// Array with all the info for each vertex
var Vertices = [
    Vertex(Position: (1, -1, 0) , Color: (1, 0, 0, 1)),
    Vertex(Position: (1, 1, 0)  , Color: (0, 1, 0, 1)),
    Vertex(Position: (-1, 1, 0) , Color: (0, 0, 1, 1)),
    Vertex(Position: (-1, -1, 0), Color: (0, 0, 0, 1))
 ]

 // Array that gives a list of triangles to create, by specifying the 3 vertices that make up each triangle
var Indices: [GLubyte] = [
   0, 1, 2,
   2, 3, 0
]

//helper extensions to pass arguments to GL land
extension Array {
    func size () -> Int {
       return self.count * sizeofValue(self[0])
    }
}

//The best way to send data to OpenGL is through something called Vertex Buffer Objects.
func setupVBOs() {  // VBO : Vertex Buffer Objects.

    //There are two types of vertex buffer objects – one to keep track of the per-vertex data (like we have in the Vertices array), and one to keep track of the indices that make up triangles (like we have in the Indices array).
    glGenBuffers(1, &vertexBuffer)
    glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer)
    glBufferData(GLenum(GL_ARRAY_BUFFER), Vertices.count * sizeofValue(Vertices[0]), Vertices, GLenum(GL_STATIC_DRAW)) //  send the data over to OpenGL-land.

    glGenBuffers(1, &indexBuffer)
    glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer)
    glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), Indices.count * sizeofValue(Indices[0]), Indices, GLenum(GL_STATIC_DRAW))
}

func render() {
    glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0)
    glClear(GLbitfield(GL_COLOR_BUFFER_BIT))

    //glViewport(0, 0, GLint(frame.size.width), GLint(frame.size.height))
    glViewport(0, GLint(frame.size.height/2)/2, GLint(frame.size.width), GLint(frame.size.height/2))

    //  feed the correct values to the two input variables for the vertex shader – the Position and SourceColor attributes.
    glVertexAttribPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), nil)
    glVertexAttribPointer(colorSlot, 4, GLenum(GL_FLOAT), GLboolean(UInt8(GL_FALSE)), GLsizei(sizeof(Vertex)), UnsafePointer<Int>(bitPattern: sizeof(Float) * 3))

    // This actually ends up calling your vertex shader for every vertex you pass in, and then the fragment shader on each pixel to display on the screen.
    glDrawElements(GLenum(GL_TRIANGLES), GLsizei(Indices.count), GLenum(GL_UNSIGNED_BYTE), nil)

    _context.presentRenderbuffer(Int(GL_RENDERBUFFER))
}