GLKit与金属透视矩阵的区别

hyp*_*not 4 opengl 3d glkit swift metal

我正在raywenderlich.com上阅读Metal 教程,其中引入了一个纯Swift Swift4x4 帮助器类。99%的内容只是GLKit函数的包装,只有一个确实令我困惑的函数:

  static func makePerspectiveViewAngle(_ fovyRadians: Float, aspectRatio: Float, nearZ: Float, farZ: Float) -> float4x4 {
    var q = unsafeBitCast(GLKMatrix4MakePerspective(fovyRadians, aspectRatio, nearZ, farZ), to: float4x4.self)
    let zs = farZ / (nearZ - farZ)
    q[2][2] = zs
    q[3][2] = zs * nearZ
    return q
  }
Run Code Online (Sandbox Code Playgroud)

为什么需要改变q[2][2]和改变q[3][2]。这是Metal和GLKit的坐标系之间的某种不兼容吗?

这是本教程的特殊选择吗?如果不是,GLKit和金属数学之间是否还有其他不兼容之处?


更新:我从WWDC 2016会议上发现了有关Metal的剪辑空间坐标系的很好的插图:采用Metal I.

剪辑空间

Rip*_*pi2 5

引用此论坛问题

OpenGL使用的剪辑空间坐标与Metal不同(在GL中,z从-1到1,而在Metal z从0到1),因此使用GLKMatrix4MakePerspective不能为您提供从眼部空间正确转换为剪辑的矩阵空间。取而代之的是,它将眼睛后面一半的观看量改变了,从而导致有时微妙的剪裁和剔除问题。您可以通过将以下代码添加到makePerspectiveViewAngle中来设置与深度相关的矩阵元素,从而修复从GLK返回的矩阵:

令zs = farZ /(nearZ-farZ)

q [2] [2] = zs

q [3] [2] = zs * nearZ