将屏幕坐标转换为Metal的规范化设备坐标

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

我正在尝试使用用户触摸来渲染2D三角形。因此,我将让用户触摸屏幕上的三个点,这些点将用作三角形的顶点。

swift 3d metal
1个回答
0
投票

您已经知道需要从顶点着色器返回剪贴空间坐标(技术上为not normalized device coordinates)。问题是从UIKit坐标到Metal的剪贴空间坐标的方式和位置。

让我们开始定义这些不同的空间。请注意,下面,我为简化起见实际上使用了[DC]坐标,因为在这种特殊情况下,我们没有通过用w != 1返回顶点位置来引入透视图。 (这里我指的是剪辑空间位置的w坐标;在下面的讨论中,w始终指的是视图宽度)。UIKit to Metal NDC transform

进行此转换的常规方法是在方便的任何空间(通常称为

model space

)将顶点传递到我们的顶点着色器中。由于我们是在2D模式下工作,因此我们不需要通常的一系列到世界空间的变换,而是到眼空间的变换。本质上,UIKit视图的坐标是我们的模型空间,世界空间和眼睛空间全部合为一体。我们确实需要一种正投影投影矩阵才能从该空间移至剪辑坐标。如果我们剔除与z轴相关的不必要部分,并假定视图边界的原点为(0,0),则可以进行以下转换:

UIKit to NDC transformation as a matrix

我们可以将此矩阵传递到顶点着色器中,也可以在将顶点发送到GPU之前进行转换。考虑到所涉及的数据很少,此时实际上并不重要。实际上,完全使用矩阵是有点浪费的,因为我们可以通过几个乘法和一个加法来变换每个坐标。这是在Metal顶点函数中的外观:

float2 inverseViewSize(1.0f / width, 1.0f / height); // passed in a buffer float clipX = (2.0f * in.position.x * inverseViewSize.x) - 1.0f; float clipY = (2.0f * -in.position.y * inverseViewSize.y) + 1.0f; float4 clipPosition(clipX, clipY, 0.0f, 1.0f);

只是为了验证我们从此变换中获得了正确的结果,让我们插入视图的左上角和右下角点,以确保它们在剪辑空间的末端处弯曲(如果线性,则这些点可以正确变换) ,其他所有人也将如此):

Some sample points transformed

这些观点似乎正确,所以我们完成了。如果您担心此转换带来的明显失真,请注意,它已被光栅化之前发生的viewport transformation完全消除了。]

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