【问题标题】:Porting from OpenGL to MetalKit - Projection Matrix (?) Problems从 OpenGL 移植到 MetalKit - 投影矩阵(?)问题
【发布时间】:2020-02-22 16:45:51
【问题描述】:

问题

我正致力于在 iOS 上从 OpenGL (OGL) 移植到 MetalKit (MTK)。我无法在应用程序的 MetalKit 版本中获得相同的显示。我修改了投影矩阵以解决两个框架之间标准化设备坐标的差异,但不知道要更改什么以获得相同的显示。有什么想法需要更改才能从 OpenGL 移植到 MetalKit?

到目前为止投影矩阵的变化...

我了解 OGL 与 MTK 中的标准化设备坐标 (NDC) 不同:

  • OGL NDC:-1 < z < 1
  • MTK 国家数据中心:0 < z < 1

我修改了投影矩阵以解决 NDC 差异,如 here 所示。不幸的是,对投影矩阵的这种修改不会导致与旧 OGL 代码相同的显示。

我什至不知道还能尝试什么。

背景

作为参考,这里有一些其他背景信息:

  • 视图矩阵很简单(恒等矩阵);即相机位于(0, 0, 0) 并朝向(0, 0, -1)
  • 在旧版 OpenGL 代码中,我使用 GLKMatrix4MakeFrustum 生成投影矩阵,使用屏幕边界为 leftrighttopbottomnear=1far=1000

我在调试时将场景剥离为裸露的骨骼,下面是 2 张图像,第一张来自旧版 OGL 代码,第二张来自 MTK,都只显示了带有调试纹理和黑色背景的“地面”平面。

任何关于在 MetalKit 中获得相同显示可能需要更改什么的想法将不胜感激。

截图

OpenGL(旧版)

金属套件

编辑 1

我尝试提取与投影矩阵的计算和使用相关的代码:

float aspectRatio = 1.777; // iPhone 8 device
float top = 1;
float bottom = -1;
float left = -aspectRatio;
float right = aspectRatio;
float RmL = right - left;
float TmB = top - bottom;
float nearZ = 1;
float farZ = 1000;

GLKMatrix4 projMatrix = {   2 * nearZ / RmL,     0,                      0,                               0,
                            0,                   2 * nearZ / TmB,        0,                               0,
                            0,                   0,                      -farZ / (farZ - nearZ),          -1,
                            0,                   0,                      -farZ * nearZ / (farZ - nearZ),  0 };

GLKMatrix4 viewMatrix = ...; // Identity matrix: camera at origin, looking at (0, 0, -1), yUp=(0, 1, 0);
GLKMatrix4 modelMatrix = ...; // Different for various models, but even when this is the identity matrix in old/new code the visual output is different
GLKMatrix4 mvpMatrix = GLKMatrix4Multiply(projMatrix, GLKMatrix4Multiply(viewMatrix, modelMatrix));

...

GLKMatrix4 x = mvpMatrix; // rename for brevity below
float mvpMatrixArray[16] = {x.m00, x.m01, x.m02, x.m03, x.m10, x.m11, x.m12, x.m13, x.m20, x.m21, x.m22, x.m23, x.m30, x.m31, x.m32, x.m33};

// making MVP matrix available to vertex shader
[renderCommandEncoder setVertexBytes:&mvpMatrixArray
                              length:16 * sizeof(float)
                             atIndex:1]; // vertex data is at "0"

[renderCommandEncoder setVertexBuffer:vertexBuffer
                               offset:0
                              atIndex:0];

...

[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip
                         vertexStart:0
                         vertexCount:4];

【问题讨论】:

    标签: ios opengl metal metalkit projection-matrix


    【解决方案1】:

    遗憾的是,这个问题最终是由于顶点着色器中的一个错误导致 Z 轴上的所有几何图形 +1,从而导致视觉差异。

    对于任何未来的 OpenGL-to-Metal 移植器:上面的投影矩阵变化,考虑到标准化设备坐标的差异,就足够了。

    【讨论】:

      【解决方案2】:

      如果没有看到代码,很难说出问题所在。最常见的问题之一可能是错误配置的视口:

      // Set the region of the drawable to draw into.
      [renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, 0.0, 1.0 }];
      

      视口的默认值为:

      originX = 0.0
      originY = 0.0
      width = w
      height = h
      znear = 0.0
      zfar = 1.0
      

      *金属:znear = minZ,zfar = maxZ。

      MinZ 和 MaxZ 表示场景将进入的深度范围 渲染并且不用于剪辑。大多数应用程序将设置 这些成员为 0.0 和 1.0 以使系统能够渲染到 深度缓冲区中的整个深度值范围。在某些情况下,您 可以通过使用其他深度范围来实现特殊效果。例如, 要在游戏中渲染平视显示器,您可以将两个值都设置为 0.0 强制系统在前景的场景中渲染对象,或 您可以将它们都设置为 1.0 以渲染应始终 在后台。

      应用程序通常将 MinZ 和 MaxZ 分别设置为 0.0 和 1.0 使系统渲染到整个深度范围。然而,你 可以使用其他值来实现某些效果。例如,你 可能将两个值都设置为 0.0 以强制所有对象进入前景, 或将两者都设置为 1.0 以将所有对象渲染到背景中。

      【讨论】:

      • 抱歉缺少代码 - 从大型遗留项目中提取相关代码很棘手,尤其是当我不确定什么是“错误”时。欣赏这个答案,但不幸的是,这对我没有用。
      • 你碰巧知道这里的znear和zfar对应的是什么吗?或者,也许我想问,这些值在什么坐标系中?文档对这些值一无所知,所以希望您有更多的知识。
      • 抱歉“万圣节假期”回复晚了。我刚刚更新了我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-11
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多