Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift、OpenGL和glvertexattributepointer_Swift_Opengl_Nsopenglview - Fatal编程技术网

Swift、OpenGL和glvertexattributepointer

Swift、OpenGL和glvertexattributepointer,swift,opengl,nsopenglview,Swift,Opengl,Nsopenglview,我正在将Objective-C代码翻译成Swift,以便学习OpenGL的一些基础知识。我对它完全陌生。我有一个正在工作的项目,它编译并生成一个带有浮动矩形的工作NSOpenGLView,但是颜色不对。我已经将问题缩小到使用指向顶点和颜色数据的glvertexattributepointer函数 以下是存储顶点和颜色数据的方式: struct Vertex { var position: (x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat)

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

以下是存储顶点和颜色数据的方式:

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)) )
我试图翻译的
glvertexattributepointer
函数的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  ));
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)
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)
}
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))
Objective-C版本使用
offsetof
宏设置这些函数的指针参数。Swift不允许使用宏,所以我试图找出在它的位置上使用什么。我尝试过通过
nil
,如下所示:

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  ));
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)
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)
}
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))
但如果我这样做,颜色数据数组将填充位置数据-不考虑偏移,因此它将位置数据用于位置和颜色属性

我找到了建议将
与unsafepointer一起使用的方法,并进行了尝试,如下所示:

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  ));
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)
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)
}
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
GLfloat
s,如下所示:

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  ));
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)
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)
}
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))
让ptr=UnsafePointer([vertexData.v1.position.x])
GLVertexAttribute指针(GLuint(positionAttribute)、4、UInt32(GL_浮点)、UInt8(GL_假)、GLsizei(sizeof(顶点))、ptr)
GLVertexAttribute指针(GLuint(colorAttribute)、4、UInt32(GL_浮点)、UInt8(GL_假)、GLsizei(sizeof(顶点))、ptr.advancedBy(4))

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

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

在您的情况下,假设您的结构是紧密打包的,第一个调用应该接收
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
因此,我认为这也应该起作用:

let ptr = UnsafePointer<()> + sizeof(GLfloat) * 4
让ptr=UnsafePointer+sizeof(GLfloat)*4

我定义了如下顶点结构:

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
}
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)

}
func BUFFER_OFFSET(n: Int) -> UnsafePointer<Void> {
    let ptr: UnsafePointer<Void> = nil
    return ptr + n
}
然后我设置顶点

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(视图:drawInRect:)的功能如下:

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
}
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)

}
func BUFFER_OFFSET(n: Int) -> UnsafePointer<Void> {
    let ptr: UnsafePointer<Void> = nil
    return ptr + n
}
缓冲区偏移函数的定义如下:

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
}
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)

}
func BUFFER_OFFSET(n: Int) -> UnsafePointer<Void> {
    let ptr: UnsafePointer<Void> = nil
    return ptr + n
}
func缓冲区\u偏移量(n:Int)->UnsafePointer{
设ptr:UnsafePointer=nil
返回ptr+n
}
我能得到结果


非常感谢@Bartek

问题是参数的类型是
UnsafePointer
,因此不能只传入
Int
值。你必须传递一个指针。我已经在一个操场上测试了我的结构,它是按照你建议的方式布置的-我认为你是对的,颜色数据的偏移量应该是位置数据偏移量的16个字节(
4*sizeof(GLfloat)
),我尝试了一些排列,但它仍然崩溃。@RomanSausarnes您是否100%肯定指针的实际值为16?\@RomanSausarnes:不要这样做,您没有使用客户端内存存储顶点数据。如果您将指针传递到CPU端内存,GPU将不知道如何处理它。取一个空指针并将偏移量添加到该指针上。@RomanSausarnes:在C中,这将是一个大意:
(float*)0+
。我不熟悉Objective C。GL只需要一个整数偏移量,函数采用指针类型,但不要让它误导您。当数据是GPU端时,它是一个偏移量,不应该与存储在CPU端的任何数据相关。@RomanSausarnes关于
nil+16
?或者这一点目前还有效,但需要注意的一个重要问题是,Swift结构的布局没有正式定义,也没有保证在不同的编译器版本之间保持稳定。您可能会发现,当/如果Swift编译器发生更改,您必须对此进行调整。如果您需要绝对确定数据布局/打包,请在C中定义一个结构类型,并从Swift使用它。@rickster首先,非常感谢您的建议。我现在正在学习GLKit和Swift。:)