图形笔记-OpenGL坐标系介绍

前言

OpenGL最终的渲染设备是2D的,我们需要将3D表示的场景转换为最终的2D形式。其中涉及到一些常用坐标系通过一定的变换完成转换。

大致流程如图所示:

为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。物体顶点的起始坐标在局部空间(Local Space),这里称它为局部坐标(Local Coordinate),它在之后会变成世界坐标(world Coordinate),观测坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Corrdinate)的形式结束。

我们之所以通过多个坐标系过渡,是因为以下原因:

  • 在这些特定的坐标系统中进行一些操作或运算更加方便和容易,这一点很快将会变得很明显。
  • 直接转换会失去灵活性,不同的修改在不同的坐标系统中具有不同的意义。

需要注意的是:

  • 图中过程包括模型变换、视变换,投影变换,这些变换可以由用户根据需要自行指定,这些内容在顶点着色器中完成;
  • 图中右边的两个步骤,包括透视除法、视口变换,这两个步骤是OpenGL自动执行的,在顶点着色器处理后的阶段完成。

坐标系统

OpenGL希望在所有顶点着色器运行后,所有我们可见的顶点都变为标准化设备坐标(Normalized Device Coordinate, NDC)。也就是说,每个顶点的x,y,z坐标都应该在-1.0到1.0之间,超出这个坐标范围的顶点都将不可见(裁剪坐标)。我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将这些坐标转换为标准化设备坐标。然后将这些标准化设备坐标传入光栅器(Rasterizer),再将他们转换为屏幕上的二维坐标或像素。

对我们来说比较重要的总共有5个不同的坐标系统:

  • 局部空间(Local Space,或者称为物体空间(Object Space))
  • 世界空间(World Space)
  • 观察空间(View Space,或者称为视觉空间(Eye Space))
  • 裁剪空间(Clip Space)
  • 屏幕空间(Screen Space)

这些就是我们将所有顶点转换为片段之前,顶点需要处于的不同的状态。如下图所示:

同本文第一图类似,这里展示了坐标空间的转换,流程如下

1
2
3
4
5
1、局部坐标是对象相对于局部原点的坐标;也是对象开始的坐标。
2、将局部坐标转换为世界坐标,世界坐标是作为一个更大空间范围的坐标系统。这些坐标是相对于世界的原点的。
3、接下来我们将世界坐标转换为观察坐标,观察坐标是指以摄像机或观察者的角度观察的坐标。
4、在将坐标处理到观察空间之后,我们需要将其投影到裁剪坐标。裁剪坐标是处理-1.0到1.0范围内并判断哪些顶点将会出现在屏幕上。
5、最后,我们需要将裁剪坐标转换为屏幕坐标,我们将这一过程成为视口变换(Viewport Transform)。视口变换将位于-1.0到1.0范围的坐标转换到由glViewport函数所定义的坐标范围内。最后转换的坐标将会送到光栅器,由光栅器将其转化为片段。

坐标名词解析

局部空间

指对象所在的坐标空间,例如,对象最开始所在的地方。模型的所有顶点都是在局部空间,他们相对于你的对象来说都是局部的。基于物体本身的空间参考而建立的坐标系为局部坐标系

世界空间

需要注意的是,从物体坐标系=>世界坐标系的过程中,引入了惯性坐标系的概念。

因为物体坐标系转换到惯性坐标系只需要旋转,从惯性坐标系转换到世界坐标系只需要平移。

我们将对象置于更大的一个世界中,以绝对不变的世界坐标系来定义物体的位置。物体变换到的最终空间就是世界坐标系,并且你会想让这些物体分散开来摆放(从而显得更真实)。

观察空间

将对象的世界空间的坐标转换为观察者视野前面的坐标。因此观察空间就是从摄像机的角度观察到的空间。其对应的摄像机坐标系处于3D空间中。

裁剪空间

在一个顶点着色器运行的最后,OpenGL期望所有的坐标都能落在一个给定的范围内,且任何在这个范围之外的点都应该被裁剪掉(Clipped)。被裁剪掉的坐标就被忽略了,所以剩下的坐标就将变为屏幕上可见的片段。

因为将所有可见的坐标都放置在-1.0到1.0的范围内不是很直观,所以我们会指定自己的坐标集(Coordinate Set)并将它转换回标准化设备坐标系。这里需要用到投影矩阵。

投影

将一定范围内的坐标转化到标准化设备坐标系的过程(而且它很容易被映射到2D观察空间坐标)被称之为投影(Projection),使用投影矩阵能将3维坐标投影(Project)到很容易映射的2D标准化设备坐标系中。

投影分为以下两种

正射投影

使用正投影时,需要指定一个正方形/长方形的视景体. 在视景体以外的任何物体都不会被绘制. 并且使用正投影所以实际大小相同的物体在屏幕上都具有相同的大小.不管它们是否存在远近问题. 正投影比较适合平面图形/2D图形渲染时使用.

透视投影

在3D开发中更为常见. 同样需要指定视景体的.而这个视景体并不是类似于正方体,看起来像平截体. 透视投影一般会使用于3D图像渲染.因为它会更加逼真,会有远小近大的真实效果。

左右手坐标系

OpenGL中坐标系 OpenGL中的物体、世界、照相机坐标系都属于右手坐标系,而规范化设备坐标系使用左手坐标系。

如何分清左右手坐标系

伸出手,打开食指和大拇指,食指指向Y轴正方向,大拇指指向X轴正方向。

这时左右手哪只能满足Z轴从掌心穿入,掌背穿出。以此来判断左右手坐标系。

参考

Learn OpenGL - 原文

Learn OpenGL - 汉译