坐标系(COORDINATE SYSTEMS)


屏幕坐标系 (Screen Coordinate System)

不管是 iOS 还是 Windows 等等 GUI 编程,都是采用屏幕坐标系。

窗口的左上角为原点,X轴正向向右,Y轴正向向下。


世界坐标系(World Coordinate System)

又被称为「Cartesian Coordinate System」(笛卡尔坐标系),分为左手和右手。


窗口坐标系(Window Coordinate System)

原点在屏幕左下角。

OPENGL


在 OpenGL 中,采用的是右手笛卡尔坐标系。

OpenGL 2D 世界坐标系:

OpenGL 3D 世界坐标系:

我们使用世界坐标来描述图形的位置,它总是不变的。

原点在屏幕中心,范围从(-1,1),表示的是比例。

又被称为「Normalized Device Coordinates」,这个术语有很多强行翻译,譬如「规范化设备坐标」、「归一化设备坐标」等等,不妨简称 NDC。

我们在传入顶点坐标时,使用的就是世界坐标系。它需要经过转换,最终变为屏幕坐标系。过程为:

世界坐标系 「normalized device coordinates」 -> 窗口坐标系 「window coordinates」 -> 屏幕坐标系 「screen coordinates」

为何中间有一个窗口坐标系呢?原因是 OpenGL 中有一个叫做 「Viewport」 的概念。

VIEWPORT


该术语被翻译成「视口」,可以想象成一个投影区域,我们在世界坐标系描述图形,将被投影到这个区域。

Viewport 采用的是「窗口坐标系」,也就是原点在左下角,X、Y轴分别向右和向上,采用和屏幕坐标一样的像素计算长度。

默认的 Viewport,原点在屏幕左下角,长、宽和窗口一样。

在 OpenGL 中,我们可以使用接口 glViewport 设置其原点和长宽。

void glViewport(GLint x,
                GLint y,
                GLsizei width,
                GLsizei height);

假设有世界坐标系的某一点 (x~nd~, y~nd~),其对应的窗口坐标 (x~w~, y~w~) 计算公式为:

其中,(x, y) 为 viewport 原点,(width, height) 为 viewport 的宽度和长度。

纹理坐标(TEXTURE COORDINATES)


纹理坐标采用了类似「Normalized Device Coordinates」一样的做法,范围是 (0, 1),表示的是比例。

注意到我们的图片,其像素排列,是与「屏幕坐标系」一致的,也就是说,它们的 Y 轴方向是相反的。因此,如果我们要正确的把一张图片「贴图」,需要注意 Y 坐标上相反这一事实。