OpenGL坐标系
在学习坐标系之前,我们先来了解下图形的维度:
2D笛卡尔积坐标系
3D笛卡尔积坐标系
下面,我们先来简单了解一下OpenGL中的几个坐标系的概念:
OpenGL摄像机坐标系
局部坐标系(物体坐标系),世界坐标系,惯性坐标系
世界坐标系:世界坐标系是一个特殊的坐标系,它建立了描述其他坐标系所需要的参考系。也就是说,可以用世界坐标系去描述其他所有坐标系或者物体的位置。而且世界坐标系是固定不变的。
惯性坐标系:惯性坐标系是为了简化世界坐标系到惯性坐标系的转化而产生的。惯性坐标系的原点与物体坐标系的原点重合,惯性坐标系的轴平行于世界坐标系的轴。引入了惯性坐标系之后,物体坐标系转换到惯性坐标系只需旋转,从惯性坐标系转换到世界坐标系只需平移。
那么,一个图形从坐标顶点数据显示到屏幕上,会经历多少坐标系空间的转换呢?
1.模型变换
我们将一个物体放在一个场景中,应该就相当于模型变换。模型变换是在世界坐标系中进行的,物体模型的中心定位在坐标系的中心处,通过对物体模型执行平移(glTranslate)、缩放(glScale)、旋转(glRotate)等操作,来调整物体模型在世界坐标系中的位置。
2.视变换
将相机置于三角架上,让它对准三维物体,它相当于OpenGL中调整视点的位置,即视变换。经过模型变换,物体的坐标都处于世界坐标系中,视变换就是确定了场景中物体的视点位置和方向。在实际拍摄物体时,我们可以保持物体的位置不动,调整相机距离物体的距离和角度,这就相当于视点变换,我们也可以保持相机的固定位置,将物体远离相机,这就相当于模型转换。其实可以看出,在OpenGL中,以逆时针旋转物体就相当于以顺时针旋转相机。
3.投影变换
经过模型变换和视变换之后,物体已经处在了场景中所希望存在的位置上,此时我们选择相机镜头并调整相机焦距,使得三维物体投影在二维胶片上,它相当于OpenGL中把三维模型投影到二维屏幕上的过程,即OpenGL的投影变换。 下面来看一下OpenGL的投影方式:
4.透视除法 透视除法这个步骤是OpenGL自动执行的,在顶点着色器处理后的阶段完成,无需我们开发者来处理。
着色器的渲染流程
在顶点着色器处理图元顶点之后进入图元装配阶段。这一阶段,执行裁剪、透视分割和视口变换操作。
1.坐标系统:
顶点以物体或者本地坐标空间输入到OpenGL中,这是最可能用来建模和存储一个对象的坐标空间。在顶点着色器执行之后,顶点位置被认为是在裁剪坐标空间内。顶点位置从本地坐标系统(也就是物体坐标) 到裁剪坐标的变换通过加载执行这一行转换的对应矩阵来完成,这些矩阵保存在顶点着色器中定义的对应统一变量中。
为了避免在可视景体之外处理图元,图元被裁剪到裁剪空间。执行顶点着色器之后的顶点位置处于裁剪坐标空间内。裁剪坐标是由(x, y, z, w)指定的同类坐标。在裁剪空间(x, y, z, w)中定义的顶点坐标根据视景体裁剪。下图是一个裁剪体,由6个裁剪平面定义,称作近、远、左、右、上、下裁剪平面。
3.透视分割
透视分割将裁剪坐标(x, yy, z, w) 指定的点投影到屏幕或者视口上。投影动作将(x, y, z)执行(x/w)、(y/w)、(z/w) 之后,我们得到规范化的设备坐标(x’, y‘, z’)。这些坐标被称为规范化设备坐标。这些规范化的坐标根据视口的大小将被转换为真正的屏幕(或窗口)坐标。规范化的z坐标将用glDepthRangef 指定的near 和far深度值转换为屏幕的z值。这些转换在视口变换阶段进行。
4.视口变换
视口变换专业解释为:OpenGL 对裁剪坐标执行透视除法从而将它们变换到标准化设备坐标。OpenGL 会使用 glViewPort 内部的参数来将标准化设备坐标映射到屏幕坐标,每个坐标都关联了一个屏幕上的点。这个过程称为视口变换。 视口变换就是将视景体内投影的物体显示在二维的视口平面上。就是我们在使用照相机拍摄完成后,进行冲洗底片,决定相片的放大与缩小,它相当与OpenGL中的视口变换。
void glViewport(GLint x, GLint y, GLsizei w, GLsizei h)
x, y, 指定视口左下角的窗口坐标,以像素表示
w, h,指定视口的宽度和高度,这些值必须大于0
从上面图元装配的流程图可以知道:在渲染过程中,必须存储2种着⾊器,分别是顶点着⾊器、片元着⾊器。顶点着⾊器是第⼀个着色器、⽚元着⾊器是最后⼀个。顶点着⾊器中处理顶点、片元着⾊器处理像素点颜色。下面我们换一种直观的方式来看渲染流程图:
2.然后通过顶点着色器渲染。
3.连接信息条,通过各个顶点连接成几何图形。
4.光栅化:其实是确定像素点在屏幕上绘制的位置,然后这些片段由片元着色器处理(输入给片元着色器)。
5.光栅化阶段生成每个片元执行这个着色器。
6.最终呈现出图形。
5.光栅化: 在顶点变换和图元裁剪之后,光栅化管线取得单独图元并为该图元生成对应的片段。每个片段由屏幕空间中的整数位置(x, y)标识。