首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从OpenGL移植到MetalKit -投影矩阵(?)问题

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

Stack Overflow用户
提问于 2019-10-26 18:39:31
回答 2查看 826关注 0票数 0

问题

我正在努力从OpenGL (OGL)移植到iOS上的MetalKit (MTK)。我没有得到相同的显示在MetalKit版本的应用程序。我修改了投影矩阵,以说明两个框架之间在规范化设备坐标方面的差异,但不知道还需要更改什么才能获得相同的显示。有什么想法需要更改为从OpenGL到MetalKit的端口吗?

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

我了解到,在OGL和MTK中,规范化设备坐标(NDC)是不同的:

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

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

我很想知道还能做些什么。

背景

作为参考,以下是一些misc的背景信息:

  • 视图矩阵非常简单(单位矩阵),即摄像机在(0, 0, 0)上,面向(0, 0, -1)
  • 在遗留的OpenGL代码中,我使用GLKMatrix4MakeFrustum生成投影矩阵,使用leftrighttopbottomnear=1far=1000的屏幕边界。

在调试过程中,我把场景简化到了底层,下面是2幅图像,第一幅来自遗留OGL代码,第二幅来自MTK,它们都只是显示带有调试纹理和黑色背景的“地面”平面。

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

截图

OpenGL (遗产)

MetalKit

编辑1

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

代码语言:javascript
复制
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];
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-06 17:48:47

可悲的是,这个问题最终是由于顶点着色器的错误,它推动所有的几何+1在Z轴,导致视觉差异。

对于任何未来的OpenGL-对金属搬运工:投影矩阵的变化,考虑到归一化的设备坐标的差异,是足够的。

票数 1
EN

Stack Overflow用户

发布于 2019-10-27 13:54:42

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

代码语言:javascript
复制
// Set the region of the drawable to draw into.
[renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, 0.0, 1.0 }];

视图端口的默认值为:

代码语言:javascript
复制
originX = 0.0
originY = 0.0
width = w
height = h
znear = 0.0
zfar = 1.0

金属:= minZ,zfar = maxZ.

MinZ和MaxZ表示场景将呈现到的深度范围,而不是用于裁剪。大多数应用程序将这些成员设置为0.0和1.0,以使系统能够在深度缓冲区中呈现整个深度值。在某些情况下,您可以通过使用其他深度范围实现特殊效果。例如,要在游戏中呈现提示显示,可以将这两个值设置为0.0,以强制系统在前景场景中呈现对象,或者将它们都设置为1.0以呈现应该始终处于后台的对象。 应用程序通常将MinZ和MaxZ分别设置为0.0和1.0,以使系统呈现到整个深度范围。但是,您可以使用其他值来实现某些影响。例如,可以将这两个值设置为0.0以强制所有对象进入前台,或者将其设置为1.0以将所有对象呈现到后台。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58573636

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档