来自OpenGL的规范化设备坐标金属

时间:2019-02-22 12:57:13

标签: math matrix 3d opengl-es metal

好的,所以我知道在SO上有很多关于规范化设备坐标的问题,但是这些问题都没有解决我的特定问题。

因此,我绘制的所有内容均在2D屏幕坐标中指定,其中top,left为(0,0),右下为(screenWidth,screenHeight),然后在我的顶点着色器中进行此计算以得出NDC(基本上,我'm渲染UI元素):

float ndcX = (screenX - ScreenHalfWidth) / ScreenHalfWidth;
float ndcY = 1.0 - (screenY / ScreenHalfHeight);

其中ScreenX / ScreenY是像素坐标,例如(600,700),而screenHalf_____是屏幕宽度/高度的一半。

从顶点着色器返回的栅格化状态的最终位置是:

gl_Position = vec4(ndcX, ndcY, Depth, 1.0);

哪个在Opengl ES中可以正常工作。

现在的问题是,当我在Metal 2中像这样尝试时,它不起作用。

我知道Metal的NDC是2x2x1,而Opengl的NDC是2x2x2,但是我认为这里的深度在这个方程式中并不重要,因为我在每个顶点将其传递给自己。

我尝试了this linkthis so question,但感到困惑,并且链接并不是那么有用,因为由于我现在正在渲染所有2D图像,所以我试图避免在顶点着色器中进行矩阵计算。

所以我的问题...在Metal中将像素坐标转换为NDC的公式是什么?是否可以不使用正交投影矩阵?为什么我的方程式不适用于Metal?

1 个答案:

答案 0 :(得分:1)

当然可以没有投影矩阵。矩阵只是应用转换的有用便利。但是,重要的是要了解当出现这种情况时它们是如何工作的,因为使用一般的正交投影矩阵会执行不必​​要的操作以获得相同的结果。

以下是我可能用来执行此操作的公式:

float xScale =  2.0f / drawableSize.x;
float yScale = -2.0f / drawableSize.y;
float xBias = -1.0f;
float yBias =  1.0f;

float clipX = position.x * xScale + xBias;
float clipY = position.y * yScale + yBias;

drawableSize是渲染缓冲区的尺寸(以像素为单位),可以在缓冲区中传递给顶点着色器。您还可以预先计算比例因子,然后传递比例因子而不是屏幕尺寸,以节省GPU上的一些计算。