1.0 3D图形渲染流水线
一个通用渲染流水线的渲染流程,如下:
渲染流水线流程图
- 建立场景:在真正开始渲染之前,需要对整个场景惊喜预先设置,如:摄像机视角,灯光设置以及雾化设置等。
- 可见性检测:有了摄像机,就可以基于摄像机视角检测场景中所有物体的可见性。
- 设置渲染状态:一旦检测到某个物体是可见的,接下来就需要把它绘制出来了。但是由于不同物体的渲染状态可能不同(如何进行深度测试,如何与背景图像进行混合等),因此在开始渲染该物体之前首先需要设置该物体的渲染状态。
- 几何体生成与提交:接着,就需要向渲染API提交几何体数据了,一般所提交的数据为三角形的顶点数据。如:顶点坐标,法线向量,UV等。
- 变换与光照:当渲染API获取到三角形顶点数据之后,就需要将顶点坐标从模型空间变换到摄像机空间,并且同时进行顶点光照计算。
- 背面剔除与裁切:变换到摄像机空间之后,那些背对着摄像机的三角形会被剔除,然后再被变换到裁切空间中,将视椎体之外的部分裁切掉。
- 投影到屏幕空间:在裁切空间中经过裁切之后的多边形会通过投影从三维变为平面,输出到屏幕空间中。
- 光栅化:屏幕空间的几何体还需要经过光栅化处理才能转变为2D的像素信息。
- 像素着色:最后,计算每个像素的颜色,并把这些颜色信息输出到屏幕上。
2.0 空间变换
空间变换流程图与变换矩阵2.1 模型空间
物体的顶点数据最开始是以模型空间(Model Space)作为参考进行描述的,顶点数据一般包含顶点的位置坐标,法线向量,UV(纹理坐标)等。
模型空间还会被称为物体空间(Object Space)或本地空间(Local Space)
2.2 世界空间
如果描述的是不同物体之间的相对位置,则需要使用一个共同的坐标空间,这个共同的坐标空间被称为世界空间(World Space)。 把顶点坐标从模型空间转变到世界空间的过程被称为模型变换,需要使用模型变换矩阵。
2.3 摄像机空间
引擎在进行渲染的时候是以摄像机作为观察视角的,这就像是人的眼睛。因此需要将世界空间中的物体转换到摄像机空间(World Space)中,这个转换的过程称为视变换,需要使用视变换矩阵。
摄像机空间也被称为观察空间(View Space)。
2.4 裁切空间
摄像机的视椎体决定了摄像机可以看到区域,但是如果直接使用摄像机的视椎体进行裁剪,计算视椎体与几何体的求交过程太过复杂,所以需要将顶点坐标变换到裁剪空间(Clip Space)在进行裁切,这个变换的过程叫做投影变换,需要使用裁切矩阵,也被称为投影矩阵。
这个过程虽被称为投影变换,但是几何体在裁切空间中其实并没有进行投影,该操作只是为接下来的投影操作提前做好准备。
顶点在裁剪空间中主要做了以下事情:
(1)计算顶点坐标的w分量,用于接下来的透视除法
(2)对摄像机的视椎体进行不均等缩放,使视椎体的梯形结构变为正方体
缩放后的视椎体被称为标准化视椎体。
2.5 屏幕空间
到目前阶段,顶点坐标都还是3D数据。但是如果想要在屏幕上呈现出最终的效果,还需要通过投影的方式将顶点坐标从3D转变为2D。
- 首先将顶点的x,y,z坐标分别除以w分量,得到标准化的设备坐标(Normalized Device Coordinate,NDC)。
- 然后将标准化的设备坐标在屏幕像素上进行映射,得到屏幕空间(Screen Space)下的像素坐标。
虽然像素作为平面显示并不需要z分量,但仍需要将z分量保存下来,以便在后续深度测试(Depth Test)阶段惊喜深度值比较和其他处理。
3.0 现代GPU渲染流水线
GPU中图形渲染流水线流程,如下:
GPU流水线
- 图形渲染流水线以顶点数据作为开始,当GPU获取到CPU传递的顶点数据之后,这个图形渲染流水线正式开始运作。
- 图形渲染流水线的第一个“站点”是顶点着色器(Vertex Shader),它允许使用者通过程序进行配置。在顶点着色器中,顶点坐标会从模型空间转换到裁剪空间。
- 装配图元(Primitive Assembly)阶段将顶点着色器输出的顶点数据装配成指定的几何图元,基本图元包括:点,线,面。
- 光栅化(Rasterization)是将几何图元转变为片段(Fragment)的过程。
屏幕上显示的图像都是由像素组成,而3D物体是由点,线,面这些基本图元组成的,要让几何图元能在屏幕上显示为像素就需要经过光栅化处理。该阶段包含俩部分的工作:
(1)确定屏幕坐标中的哪些整型栅格区域被基本图元占用。
(2)分配颜色值和深度值到各个区域。
- 片段在经过视椎体裁切之后就会被传递到片段着色器(Fragment Shader),它的主要目的是计算每一个像素的颜色,这个阶段可以通过Shader程序进行配置。在这个阶段中,片段着色器会计算光照,阴影,纹理等所有的颜色数据,最终计算出像素的颜色。
- 当所有像素的颜色都确定下来之后,最后进入测试(Test)和混合(Blending)阶段。在这个阶段会测试所有像素的深度值,将当前片段的深度值与深度缓存中的数值对比,从而判断这个像素的前面是否有物体对它进行遮挡,进而决定这个像素是否应该被丢弃。通过测试的像素会与已经绘制好的图像进行混合,从而得到最终的颜色。
- 帧缓存(Frame Buffer)是图形渲染流水线的最后一个“站点”,帧缓存中存储这用于渲染到屏幕上的像素,等待下一步输出到屏幕上。
网友评论