简要的图形绘制流水线
场景中包含一组对象,每个对象由一组图元组成,每个图元又包含一组顶点。我们可以认为是图元的类型和顶点集定义了场景的几何数据 。在一个复杂的场景里,可能会使用数千个甚至数百万个顶点来定义对象。为了生成存储在帧缓存中的图像,我们必须以相似的方式来处理所有这些顶点。成像过程的4个主要步骤:
完整的可编程渲染管线
所谓GPU的渲染管线,听起来好像很高深的样子,其实我们可以把它理解为一个流程,就是我们告诉GPU一堆数据,最后得出来一副二维图像,而这些数据就包括了”视点、三维物体、光源、照明模型、纹理”等元素。
在各种图形学的书中,渲染管线主要分为三个阶段:应用程序阶段、几何阶段、光栅阶段。
1,应用程序阶段。
这个阶段相对比较好理解,就比如我们在Unity里开发了一个游戏,其实很多底层的东西Unity都帮我们实现好了,例如碰撞检测、视锥剪裁等等,这个阶段主要是和CPU、内存打交道,在把该计算的都计算完以后,在这个阶段的末端,这些计算好的数据(顶点坐标、法向量、纹理坐标、纹理)就会通过数据总线传给图形硬件,作为我们进一步处理的源数据。2,几何阶段。
主要负责顶点坐标变换、光照、裁剪、投影以及屏幕映射,该阶段基于GPU进行运算,在该阶段的末端得到了经过变换和投影之后的顶点坐标、颜色、以及纹理坐标。简而言之,几何阶段的主要工作就是“变换三维顶点坐标”和“光照计算”。
问题随之而来,为什么要变换顶点坐标?我是这么理解的,比如你有一个三维游戏场景,场景中的每个模型都可以用一个向量来确定它的位置,但如何让计算机根据这些坐标把模型正确的、有层次的画在屏幕上?这就是我们需要变换三维顶点坐标的原因,最终目的就是让GPU可以将这些三维数据绘制到二维屏幕上。
根据顶点坐标变换的先后顺序,主要有如下几个坐标空间:Object space,模型坐标空间;World space,世界坐标空间;Eye space,观察坐标空间;Clip and Project space,屏幕坐标空间。2.1,从object space到world space
object space有两层核心含义,第一,object space中的坐标值就是模型文件中的顶点值,这些值是在建立模型时得到的,例如一个.max文件,里面包含的数据就是object space的坐标。第二,object space的坐标与其他物体没有任何参照关系,这是object space和world space区分的关键。world space坐标的实际意义就有有一个坐标原点,物体跟坐标原点相比较才能知道自己的确切位置。例如在unity中,我们将一个模型导入到场景中以后,它的transform就是世界坐标。2.2,从world space到eye space
所谓eye space,就是以摄像机为原点,由视线方向、视角和远近平面,共同组成的一个梯形体,如下图,称之为视锥(viewing frustum)。近平面,是梯形体较小的矩形面,也是靠近摄像机的平面,远平面就是梯形体较大的矩形,作为投影平面。在这个梯形体的内的数据是可见的,超出的部分会被视点去除,也叫视锥剪裁。
例如在游戏中的漫游功能,屏幕的内容随摄像机的移动而变化,这是因为GPU将物体的顶点坐标从world space转换到了eye space。
2.3,从eye space到project and clip space
eye space坐标转换到project and clip space坐标的过程其实就是一个透视投影变换、剪裁、映射的过程。因为在不规则的视锥体内剪裁是一件非常困难的事,所以前人们将剪裁安排到一个单位立方体中进行,这个立方体被称为规范立方体(CCV),CVV的近平面(对应视锥体的近平面)的x、y坐标对应屏幕像素坐标(左下角0、0),z代表画面像素深度。所以这个转换过程事实上由三步组成:
(1),用透视变换矩阵把顶点从视锥体变换到CVV中;
(2),在CVV内进行剪裁;
(3),屏幕映射:将经过前两步得到的坐标映射到屏幕坐标系上(设备坐标系)。2.4,primitive assembly(图元装配)和triangle setup(三角形处理)
到目前为止我们得到了一堆顶点的数据,这一步就是根据这些顶点的原始连接关系还原出网格结构。网格由顶点和索引组成,这个阶段就是根据索引将顶点链接到一起,组成线、面单元,然后进行剪裁,如果一个三角形超出屏幕以外,例如两个顶点在屏幕内,一个顶点在屏幕外,这时我们在屏幕上看到的就是一个四边形,然后把这个四边形切成两个小的三角形。
现在我们得到了一堆在屏幕坐标上的三角形面片,这些面片是用于光栅化的。
3,光栅化阶段。
经过上面的步骤之后,我们得到了每个点的屏幕坐标值,和我们需要绘制的图元,但此时还有两个问题:- (1)屏幕坐标是浮点数,但像素是用整数来表示的,如何确定屏幕坐标值所对应的像素?
绘制的位置只能接近两指定端点间的实际线段位置,例如,一条线段的位置是(10.48, 20.51),转换为像素位置就是(10,21)。 - (2)如何根据已确定位置的点,在屏幕上画出线段或者三角形?
画线和填充算法。
1 - 最简单的线段扫描转换算法DDA算法(画线)。
- Bresenham算法(画线)。
- 漫水填充算法
- 种子填充算法
- 奇偶填充算法
这个过程结束后,顶点和图元已经对应到像素,之后的流程就是如何处理像素,即给像素赋予颜色值。
- 给像素赋予颜色的阶段称为Pixel Operation,也叫光栅操作,是在更新帧缓存之前,执行最后一系列针对每个片段的操作,其目的是计算出每个像素的颜色值。在这个阶段,被遮挡的面通过一个被称为深度测试的过程消除。
pixel operation包含下面这些流程:
(1)隐藏面消除(Z-Buffer算法);
(2)Texture operation,纹理操作,根据像素的纹理坐标,查询对应的纹理值;
(3)Blending,通常称为alpha blending,根据目前已经画好的颜色,与正在计算的颜色的alpha值混合,形成新的颜色。
(4)Filtering,将正在计算的颜色经过某种滤镜后输出。
该阶段之后,像素的颜色值被写入帧缓存中。
- (1)屏幕坐标是浮点数,但像素是用整数来表示的,如何确定屏幕坐标值所对应的像素?
坐标系的变换
坐标系引申:
1)世界坐标系(world coordinate Systems),该坐标系统主要用于计算机图形场景中的所有图形对象的空间定位和定义,包括观察者的位置、视线等等。计算机图形系统中涉及的其它坐标系统都是参照它进行定义。
2)局部坐标系(Local Coordinate System),主要为考察物体方便起见,独立于世界坐标系来定义物体几何特性,通常是在不需要指定物体在世界坐标系中的方位的情况下,使用局部坐标系。一旦你定义“局部”物体,通过指定在局部坐标系的原点在世界坐标系中的方位,然后通过几何变换,就可很容易地将“局部”物体放入世界坐标系内,使它由局部上升为全局。
3)观察坐标系(Viewing coordinate systems),观察坐标系通常是以视点的位置为原点,通过用户指定的一个向上的观察向量(view up vector)来定义整个坐标系统,缺省为左手坐标系,观察坐标系主要用于从观察者的角度对整个世界坐标系内的对象进行重新定位和描述,从而简化几何物体在投影面的成像的数学推导和计算。
4)成像面坐标系统,它是一个二维坐标系统,主要用于指定物体在成像面上的所有点,往往是通过指定成像面与视点之间的距离来定义成像面,成像面有时也称投影面,可进一步在构影面上定义称为窗口的方形区域来实现部分成像。
5)屏幕坐标系统,也称设备坐标系统,它主要用于某一特殊的计算机图形显示设备(如光栅显示器)的表面的点的定义,在多数情况下,对于每一个具体的显示设备,都有一个单独的坐标系统,在定义了成像窗口的情况下,可进一步在屏幕坐标系统中定义称为视图区(view port)的有界区域,视图区中的成像即为实际所观察到的。
6)设备坐标系和规格化设备坐标系
设备坐标系(Device Coordinate, DC)是图形设备上采用的与具体设备相关的坐标系。设备坐标系一般采用整数坐标,其坐标范围由具体设备的分辨率决定。设备坐标系上的一个点一般对应图形设备上的一个像素。由于具体设备的限制,设备坐标系的坐标范围一般是有限的。
规格化设备坐标系(Normal Device Coordinate, NDC)是为了避免设备相关性而定义的一种虚拟的设备坐标系。规格化坐标系的坐标范围一般从0到1,也有的是从-1到+1。采用规格化设备坐标系的好处是屏蔽了具体设备的分辨率,使得图形处理能够尽量避开对具体设备坐标的考虑。实际图形处理时,先将世界坐标转换成对应的规格化设备坐标,然后再将规格化设备坐标映射到具体的设备坐标上去。
7)齐次坐标
所谓齐次坐标是指用一个n+1维向量表示一个n维向量。若n维空间中点的位置向量用笛卡儿坐标表示为(p1,p2,…,pn),且是唯一的。若用齐次坐标表示时,此向量有n+1个坐标分量(hp1,hp2,…,hpn,h),且不唯一。非齐次坐标与齐次坐标是一对多的关系,但不影响图形的形状。例如,一个二维空间点[x,y],如果用齐次坐标表示则为[hx,hy,h]。通常,在实际应用中采用规范化齐次坐标,就是取h=1,即用三维向量[x,y,1]表示二维向量[x,y].
采用齐次坐标的优越性主要表现在以下两方面。
(1) 齐次坐标提供了用矩阵运算把二维、三维甚至更高维空间中的一个点集从一个坐标系变换到另一个坐标系的有效方法。
(2) 齐次坐标可以表示无穷远点。例如,在n+1维空间(hp1,hp2,…,hpn,h), h=0的齐次坐标实际上表示了一个n维(p1,p2,…,pn)的无穷远点。在三维情况下,利用齐次坐标表示投影变换,其几何意义会更加清晰。
Directx中使用是左手坐标系,OpenGL中使用的是右手坐标系。
【原文参考】学习shader之前必须知道的东西之计算机图形学(一)渲染管线
【原文参考】3D图形学坐标系变换
【原文参考】图形学笔记 —— 透视除法