从OpenGL移植到MetalKit-投影矩阵(?)问题

问题描述 投票:0回答:2

问题

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

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

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

  • OGL NDC:-1 < z < 1
  • MTK NDC:0 < z < 1

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

我还在努力尝试其他尝试。

背景

供参考,这里是一些其他背景信息:

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

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

关于在MetalKit中获得相同显示所需的任何其他更改的想法,将不胜感激。

屏幕截图

OpenGL(旧版)

OpenGL Scene

金属套件

MetalKit Scene

编辑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
2个回答
0
投票

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

// 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

enter image description here

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

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

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


0
投票

不幸的是,此问题最终归因于顶点着色器中的一个错误,该错误将Z轴上的所有几何+1推入了视线。

对于任何将来的OpenGL到金属搬运工:上面的投影矩阵更改(考虑到归一化设备坐标的差异,就足够了。

© www.soinside.com 2019 - 2024. All rights reserved.