3

我正在将这个 repo中的 Objective-C 代码翻译成 Swift,以便学习 OpenGL 的一些基础知识。我对它完全陌生。我有一个工作项目,它编译并生成一个带有浮动矩形的工作 NSOpenGLView,但颜色是错误的。我已将问题缩小到我使用glVertexAttribPointer指向顶点和颜色数据的函数。

这是我存储顶点和颜色数据的方式:

struct Vertex {
    var position: (x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)
    var color: (r: GLfloat, g: GLfloat, b: GLfloat, a: GLfloat)
}

struct Vertices {
    var v1: Vertex
    var v2: Vertex
    var v3: Vertex
    var v4: Vertex
}

var vertexData = Vertices(
    v1: Vertex( position:   (x: -0.5, y: -0.5, z:  0.0, w:  1.0),
                color:      (r:  1.0, g:  0.0, b:  0.0, a:  1.0)),
    v2: Vertex( position:   (x: -0.5, y:  0.5, z:  0.0, w:  1.0),
                color:      (r:  0.0, g:  1.0, b:  0.0, a:  1.0)),
    v3: Vertex( position:   (x:  0.5, y:  0.5, z:  0.0, w:  1.0),
                color:      (r:  0.0, g:  0.0, b:  1.0, a:  1.0)),
    v4: Vertex( position:   (x:  0.5, y: -0.5, z:  0.0, w:  1.0),
                color:      (r:  1.0, g:  1.0, b:  1.0, a:  1.0)) )

glVertexAttribPointer我尝试翻译的函数的 Objective-C 版本如下所示:

glVertexAttribPointer((GLuint)positionAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, position));
glVertexAttribPointer((GLuint)colourAttribute  , 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, colour  ));

Objective-C 版本使用offsetof宏来设置这些函数的指针参数。Swift 不允许使用宏,所以我试图弄清楚用什么来代替它。我试过通过nil,像这样:

glVertexAttribPointer(GLuint(positionAttribute), 4, UInt32(GL_FLOAT), UInt8(GL_FALSE), GLsizei(sizeof(Vertex)), nil)

glVertexAttribPointer(GLuint(colorAttribute), 4, UInt32(GL_FLOAT), UInt8(GL_FALSE), GLsizei(sizeof(Vertex)), nil)

但如果我这样做,颜色数据数组将填充位置数据 - 不考虑偏移,因此它将位置数据用于位置和颜色属性。

我发现this stackoverflow answer建议使用withUnsafePointer并尝试过,如下所示:

withUnsafePointer(&vertexData.v1.position) { ptr in
    glVertexAttribPointer(GLuint(positionAttribute), 4, UInt32(GL_FLOAT), UInt8(GL_FALSE), GLsizei(sizeof(Vertex)), ptr)
}

withUnsafePointer(&vertexData.v1.color) { ptr in
    glVertexAttribPointer(GLuint(colorAttribute), 4, UInt32(GL_FLOAT), UInt8(GL_FALSE), GLsizei(sizeof(Vertex)), ptr)
}

但这会使整个显示器崩溃,需要强制关机并重新启动。

我不确定下一步该尝试什么。我正在处理的完整代码可在此处获得。

编辑:

我还尝试将指针指向第一个数据点并将其推进 4GLfloat秒,如下所示:

let ptr = UnsafePointer<GLfloat>([vertexData.v1.position.x])
glVertexAttribPointer(GLuint(positionAttribute), 4, UInt32(GL_FLOAT), UInt8(GL_FALSE), GLsizei(sizeof(Vertex)), ptr)

glVertexAttribPointer(GLuint(colorAttribute), 4, UInt32(GL_FLOAT), UInt8(GL_FALSE), GLsizei(sizeof(Vertex)), ptr.advancedBy(4))

显示器不会崩溃,但屏幕上根本没有绘制任何内容。

4

2 回答 2

4

要复制offsetof功能,您只需要知道每个字段位于结构中的哪个字节偏移量。

在您的情况下,假设您的结构紧凑,第一个调用应该接收0,第二个调用应该4 * GLfloat是第一个组件的大小。我不确定如何直接从结构中提取这些数据,尤其是因为您使用的是元组。

为了说明,您的结构:

struct Vertex {
    var position: (x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)
    var color: (r: GLfloat, g: GLfloat, b: GLfloat, a: GLfloat)
}

可能是这样布置的:

GLfloat // <-- structure start // <-- position
GLfloat
GLfloat
GLfloat
GLfloat // <-- color
GLfloat
GLfloat
GLfloat

因此,position位于 offset0color4 * 处的谎言GLfloat


要创建一个值为 16 的指针,这个答案看起来很相关:

let ptr = UnsafePointer<()> + 16

所以我想这也应该起作用:

let ptr = UnsafePointer<()> + sizeof(GLfloat) * 4
于 2015-12-19T21:17:45.847 回答
2

我定义了如下顶点结构:

struct Vertex {
var x : GLfloat = 0.0
var y : GLfloat = 0.0
var z : GLfloat = 0.0

var r : GLfloat = 0.0
var g : GLfloat = 0.0
var b : GLfloat = 0.0
var a : GLfloat = 1.0


init(_ x : GLfloat, _ y : GLfloat, _ z : GLfloat, _ r : GLfloat = 0.0, _ g : GLfloat = 0.0, _ b : GLfloat = 0.0, _ a : GLfloat = 1.0) {
    self.x = x
    self.y = y
    self.z = z

    self.r = r
    self.g = g
    self.b = b
    self.a = a
}

然后我设置顶点

let vertices : [Vertex] = [
    Vertex( 1.0, -1.0, 0, 1.0, 0.0, 0.0, 1.0),
    Vertex( 1.0,  1.0, 0, 0.0, 1.0, 0.0, 1.0),
    Vertex(-1.0,  1.0, 0, 0.0, 0.0, 1.0, 1.0),
    Vertex(-1.0, -1.0, 0, 1.0, 1.0, 0.0, 1.0)
]

let indices : [GLubyte] = [
    0, 1, 2,
    2, 3, 0
]

我使用 GLKViewController,所以 glkView(view:drawInRect:) 函数如下:

override func glkView(view: GLKView, drawInRect rect: CGRect) {
    glClearColor(1.0, 0.0, 0.0, 1.0);
    glClear(GLbitfield(GL_COLOR_BUFFER_BIT))

    shader.prepareToDraw()

    glEnableVertexAttribArray(VertexAttributes.Position.rawValue)
    glVertexAttribPointer(
        VertexAttributes.Position.rawValue,
        3,
        GLenum(GL_FLOAT),
        GLboolean(GL_FALSE),
        GLsizei(sizeof(Vertex)), BUFFER_OFFSET(0))


    glEnableVertexAttribArray(VertexAttributes.Color.rawValue)
    glVertexAttribPointer(
        VertexAttributes.Color.rawValue,
        4,
        GLenum(GL_FLOAT),
        GLboolean(GL_FALSE),
        GLsizei(sizeof(Vertex)), BUFFER_OFFSET(3 * sizeof(GLfloat))) // x, y, z | r, g, b, a :: offset is 3*sizeof(GLfloat)

    glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer)
    glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer)
    glDrawElements(GLenum(GL_TRIANGLES), GLsizei(indices.count), GLenum(GL_UNSIGNED_BYTE), nil)

    glDisableVertexAttribArray(VertexAttributes.Position.rawValue)

}

BUFFER_OFFSET 函数定义如下:

func BUFFER_OFFSET(n: Int) -> UnsafePointer<Void> {
    let ptr: UnsafePointer<Void> = nil
    return ptr + n
}

我可以得到结果

在此处输入图像描述

非常感谢@Bartek!

于 2016-02-26T14:47:02.923 回答