GLKit 与 Metal 透视矩阵的区别

GLKit vs. Metal perspective matrix difference

我正在读金属 tutorial on raywenderlich.com, where it introduces a pure Swift float4x4 helper class。 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
  }

为什么要改q[2][2]q[3][2]。这是不是 Metal 和 GLKit 的坐标系不兼容?

这是本教程的特定选择吗?如果不是,那么 GLKit 和 Metal mathematics 之间还有其他不兼容的地方吗?


更新: 我在 WWDC 2016 上找到了关于 Metal 的 clip space 坐标系的很好的插图 Session: 采用 Metal I.

引用自this forum question

OpenGL uses different clip-space coordinates than Metal (in GL, z goes from -1 to 1, while in Metal z goes from 0 to 1), so using GLKMatrix4MakePerspective doesn't give you a matrix that properly transforms from eye space to clip space. Instead, it transforms half of the viewing volume behind the eye, causing sometimes-subtle clipping and culling issues. You can fix up the matrix you get back from GLK by setting the matrix elements that are relevant to depth by adding the following code to makePerspectiveViewAngle:

let zs = farZ / (nearZ - farZ)

q[2][2] = zs

q[3][2] = zs * nearZ