OpenGL ES系列六--坐标系

概述

首先说明一下本篇文章主要是说明空间坐标系转换相关的知识点,主要涉及以下两个个方面:

  1. 五个坐标系统(哪五个,存在的意义,什么时候使用)
  2. 这五个坐标系统,我们是通过什么来实现其转化的

五个坐标系

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

在渲染流水线中,物体的顶点在最终转化为屏幕坐标之前还会被变换到多个坐标系统(Coordinate System)。将物体的坐标变换到几个过渡坐标系(Intermediate Coordinate System)的优点在于,在这些特定的坐标系统中,一些操作或运算更加方便和容易。对我们来说比较重要的总共有5个不同的坐标系统:

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

这就是一个顶点在最终被转化为片段之前需要经历的所有不同状态。

为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到变换矩阵,最重要的几个变换矩阵分别是模型(Model)、观察(View)、投影(Projection)。我们的顶点坐标起始于局部空间(Local Space),在这里它称为局部坐标(Local Coordinate),它在之后会变为世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)的形式结束。下面的这张图展示了整个流程以及各个变换过程做了什么:

OpenGL ES坐标转换过程

下面我们针对开头说到的那些空间进行说明、讲解:

  1. 局部空间

    局部空间是指物体所在的坐标空间,即对象最开始所在的地方。比如你在一个建模软件(比如说3DMAX)中创建了一个立方体,你假设以某一个点为立方体的原点(0, 0, 0),然后以原点为参考绘制出一个立方体,即便它有可能最后在程序中处于完全不同的位置。我们在绘制立方体时,以自己定的原点为参考定义顶点,都是在局部空间中定义的局部坐标。

  2. 世界空间(模型矩阵)

    如果我们将局部空间中定义的所有物体导入OpenGL程序,它们可能会挤在世界的原点(0,0,0)上,为了避免出现这种情况,我们需要将在局部空间中的物体在世界空间中重新摆放,这个摆放变换是由模型矩阵(Model Matrix)来实现的。

    模型矩阵:一种变换矩阵,它能够通过对物体进行缩放、旋转、平移来将它置于它本应该在的位置或朝向(世界坐标系中)。你可以将它想像为变换一个房子,你需要先将它缩小(它在局部空间中太大了),并将其位移至郊区的一个小镇,然后在y轴上往左旋转一点以搭配附近的房子。

  3. 观察空间-视觉坐标(观察矩阵)

    观察空间经常被人们称之OpenGL的摄像机(Camera)(所以有时也称为摄像机空间(Camera Space)或视觉空间(Eye Space))。观察空间是将世界空间坐标转化为相对于观察者视角而言的坐标的结果。因此观察空间就是从摄像机(观察者)的视角所观察到的空间。视觉坐标通常作为参考坐标系使用。

  4. 裁剪空间(投影矩阵)

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

    为了将顶点坐标从观察变换到裁剪空间,我们需要定义一个投影矩阵(Projection Matrix),它指定了一个范围的坐标,比如在每个维度上的-1000到1000。投影矩阵接着会将在这个指定的范围内的坐标变换为标准化设备坐标的范围(-1.0, 1.0)。所有在范围外的坐标不会被映射到在-1.0到1.0的范围之间,所以会被裁剪掉。在上面这个投影矩阵所指定的范围内,坐标(1250, 500, 750)将是不可见的,这是由于它的x坐标超出了范围,它被转化为一个大于1.0的标准化设备坐标,所以被裁剪掉了。

    由投影矩阵创建的观察箱(Viewing Box)被称为平截头体(Frustum)、视景体,每个出现在平截头体范围内的坐标都会最终出现在用户的屏幕上。将特定范围内的坐标转化到标准化设备坐标系的过程(而且它很容易被映射到2D观察空间坐标)被称之为投影(Projection),因为使用投影矩阵能将3D坐标很容易映射到2D的标准化设备坐标系中。

  5. 屏幕空间

    屏幕空间就相当于我们的设备屏幕,比如移动端的手机屏幕、PC端的显示器屏幕等。

如何转化

介绍完了各个空间,现在我们就完整的讲述一下坐标的变化。

  1. 模型变换:包含缩放、旋转和平移,应用在所有物体的顶点上(局部坐标系),将物体变换到世界空间中。通过顶点坐标乘以模型矩阵实现。结果是物体坐标转换为以世界坐标系为参考的坐标

  2. 观察变换:在世界空间中,默认情况下,透视投影中的观察点位于原点(0,0,0),并沿着z轴负方向进行观察(向显示器内部“看进去”),为了使物体更方便得可见,我们需要设置相机(观察者)的位置和方向,它是由观察矩阵来实现的。结果是物体坐标转换为以视图坐标系(观察视觉坐标系)为参考的坐标注意摄像机后移(z轴正方向),或者物体前移(z轴负方向),两者效果是相同的。

    摄像机位置:简单来说就是世界空间中一个指向摄像机位置的向量

    摄像机方向(摄像机指向哪个方向):假设让摄像机指向场景原点(0, 0, 0),用场景原点向量减去摄像机位置向量的结果就是摄像机的指向向量。

    注意:在正交投影中,观察者默认被认为是在z轴正方向无穷远的位置,能够看到视景体红的任何东西

  3. 投影变换:定义了一个视景体(平截头体),落在这个视景体之外的顶点都会被裁减掉,剩下的坐标将转变为屏幕上可见的片段(将3D坐标映射到2D的标准化设备坐标系中)。结果是物体坐标系转换为裁剪空间坐标系(归一化)

  4. 视口变换:将裁剪空间转换到屏幕空间,我们只要指定了视口的其实坐标和大小,其它的OpenGL会在光栅化阶段自动完成

你可能感兴趣的:(OpenGL-ES)