关于屏幕空间坐标的一些笔记

屏幕(视口)映射以左上为原点的坐标系,是DirectX右手系的视口坐标(原点在左上角,右为x+,下为y+,内为z+)。与之相对的OpenGL视口坐标则是左手系(原点在左下,右为x+,上为y+,内为z+)。

对图形学api稍有了解的便知道“DirectX左手系 OpenGL右手系”这个说法,这句话只适用于模型空间与视角空间,并非放之四海而皆准。首先看DX,这个坐标系变换的原因相对简单,在Direct3D描述视口的结构体里就体现出来了(以D3D12为例):

typedef struct D3D12_VIEWPORT{
FLOAT TopLeftX; //X轴的左上原点FLOAT 
TopLeftY; //Y轴的左上原点
FLOAT Width; 
FLOAT Height;
... ...
}D3D12_VIEWPORT

而DX直到NDC(归一化设备坐标系)还是是左手系(原点在左下,右+z,上+y),但一旦调用视口的结构体,z轴方向没换,y轴指向上却做了个这样的变换,把原点放到左上了,自然改变坐标系旋向性。

OpenGL视口坐标的差异比较复杂,主要来自于处理NDC时的变化伸出右手,并使大拇指朝右,食指朝上当作屏幕,中指与他们各成90度,这是OpenGL的默认坐标系,中指也就是+z轴指向的是屏幕外,-z轴坐标才能描述屏幕内的元素,屏幕内的z坐标取反才得到点到屏幕(摄像机)的距离,而点到屏幕的距离又是算透视时必不可缺的,所以OpenGL的透视投影矩阵里面包含了类似取反的操作,反转了一下z轴这使得OpenGL的NDC已经变成了左手系(DX没有相关操作,是因为DX原来就是左手系,+z轴坐标可以直接描述元素)NDC是左手系,并且在后来的视口变换里,也没有像DX一样作轴指向上的变换,仅仅是坐标值的线性映射导致了OpenGL的视口坐标则是左手系​。

Leave a Reply