好吧,所以我知道在SO上有很多关于标准化设备坐标的问题,但它们都没有解决我的特定问题。
所以,我绘制的所有内容都是在2D屏幕坐标中指定的,其中顶部,左边是(0,0),右下角是(screenWidth,screenHeight)然后在我的顶点着色器中我做这个计算以得出NDC(基本上,我正在渲染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 link和this so question但是很困惑,因为我试图避免顶点着色器中的矩阵计算,因为我现在正在渲染所有2D,因此链接没有用。
所以我的问题......在Metal中将像素坐标转换为NDC的公式是什么?是否可以不使用正交投影矩阵?为什么我的方程式不适用于Metal?
当然可以没有投影矩阵。矩阵只是应用转换的一种有用的便利。但是,当出现这种情况时,了解它们如何工作是很重要的,因为使用一般的正交投影矩阵会执行不必要的操作以得到相同的结果。
以下是我可能用来执行此操作的公式:
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上保存一些计算。