一张图带你了解计算机图形渲染管线!再也不怕面试问到图形渲染管线!
图形学是我认为客户端的最重要的两个知识之一。因为你能看到的所有画面都是图形学渲染而来。另一个重要的知识是射线。
下面是各个阶段的详细介绍(文中图片来自实时渲染第4版截图):
应用阶段:
有关术语:图元:构成模型的基本单元,点、线、三角形。图元的基本单元是顶点。
本阶段主要是将与渲染有关的场景数据包括:模型图元数据、光源数据、摄像机数据传递到几何阶段。这个阶段是在CPU中进行的,因此可以由程序员全权控制,比如应用一些算法对渲染性能做一些优化。
几何阶段:
主要是将模型的顶点数据包括位置信息和着色信息转换到屏幕空间。此后的阶段都是位于GPU中,一部分是可由程序员编程的,一部分是高度可配置的,还有一部分是设备自身决定。
顶点着色:
任务有两个:
1、通过坐标转换将模型的顶点位置数据转换到视图空间。
首先顶点着色阶段拿到的顶点坐标数据都是位于模型空间的,要经过模型转换将这些坐标数据转换到世界空间。接着为了方便后面的投影和裁剪,需要将坐标数据从世界空间转换到摄像机空间(摄像机位置为原点,x轴指向右方,y指向上方,z轴是背离摄像机朝向的方向),这称为视图转换。模型转换和视图转换都可以用4x4的矩阵进行操作。
2、计算顶点着色数据。
应用材质,灯光等数据计算出顶点的着色数据,并储存在顶点中。当然这里也可以不用计算任何着色数据,把着色信息存储在顶点中,传递后后续阶段进行处理。
这一阶段是可由程序员编程的,称为顶点着色器。程序员可以自由决定顶点着色的方程式,也可以不处理,只是将着色数据传递到下面阶段。并且,程序员可以在位置变换上做手脚,使模型的位置信息灵活多变,产生一些独特的效果,甚至可以做动画(顶点动画)。
投影:
使用最多的两种投影方式是:透视投影和正交投影。为了方便裁剪,无论采用哪种投影方式,摄像机空间的数据最终会统一转换到单元立方体呢。这个过程称为投影转换,最终物体处于裁剪空间也叫齐次空间。
裁剪:
只有摄像机视锥体内的物体才是可见的。视锥体已经转换成了单元立方体,因此只有位于单元立方体内部的图元才会保留,位于外部的会被舍弃,相交的图元会被裁剪。
屏幕映射:
将上述保留下来的图元映射到屏幕上。这个过程基本上是一个缩放的过程,将单元立方体中的图元,根据屏幕大小,得到图元的屏幕坐标,注意屏幕坐标是二维的,屏幕坐标和z轴构成了窗口坐标系,xy轴储存着屏幕的位置,z轴储存着深度值,深度值主要是表示物体的遮挡关系。
光栅化:
有关术语:片元:独立的一块片段数据,储存着着色信息和深度值。会与屏幕的像素进行比较,最后影响屏幕上的像素颜色。
颜色缓冲区:一块内存,存储着屏幕上每块像素的颜色。
深度缓冲区:一块内存,存储着屏幕上每块像素的深度。
主要是将屏幕上的顶点数据转换成像素数据。
三角形设置:
每三个顶点形成一个三角形。为了后续阶段的计算,会根据顶点的信息以及一些方程计算出三角形边界的信息。
三角形遍历:
遍历所有的三角形,根据上述边界信息,计算其覆盖的像素,并且会生成一个片元。片元中保存着着色信息,以及深度信息。这些数据是通过三角形三个顶点数据的插值运算得到的。注意:片元并不是像素,像素是屏幕上显示颜色的单元,片元只是保存了像素的数据。
像素处理阶段
将片元与原有的像素合并输出到屏幕上。
像素着色:
逐片元的操作,这里跟顶点着色一样属于可编程的,也称为片元着色器(像素着色器)。这里主要作用跟顶点着色很像,计算着色信息,但是主角变了,顶点着色器主要作用于顶点,片元着色器主要作用于片元。可以运用各种计算方式,以及技术,比如贴纹理(图片),重新生成片元的颜色信息。
合并:
合并是指的,前一阶段得到的片元与对应的屏幕像素进行合并。那么具体的合并是怎么操作的?主要的步骤有两个:
1、测试。测试是决定哪些片元有资格与像素颜色合并,哪些片元需要被舍弃掉。
2、合并。将片元颜色与对应的像素颜色合并。具体的合并方式是高度可配置的。我们可以决定直接替换掉原有颜色,也可以用一定的规则混合两个颜色。
有一个算法叫z算法,也称为深度测试。每块像素的颜色储存在颜色缓冲区,深度值储存在深度缓冲区。同时片元中保存着有新的颜色值和深度值,首先深度值会与屏幕上像素的深度值进行比较,如果片元深度值小于屏幕上像素的深度值,那么就代表当前片元是比屏幕上对应的像素要离摄像机更近,此时就是把片元的颜色信息赋值给屏幕对应像素的颜色缓冲区,深度值赋值给屏幕对应像素的深度缓冲区;如果大于屏幕上像素的深度值,那么该片元就不会影响屏幕上的像素信息。这么做保证了渲染出来的画面永远都是摄像机视角可见的元素,被遮挡的物体就被替换了。上述过程是无视渲染顺序的。因此也就有了z算法的一个重大缺点就是处理透明度。
假设屏幕上已经存在一个物体的渲染,接下来要渲染一个透明的物体,这个物体恰好位于已渲染的物体像素上,那么根据z算法要将当前的透明物体的信息覆盖到已有的物体信息。实际生活中,这种情况下,透明物体后面的物体还是可以看得到的,所以仅仅使用z算法不做处理的话,就会得到错误的视觉答案。
好在我们有其他的处理办法。
Alpha通道与颜色缓冲区有紧密联系。我们可以在片元着色器中决定弃除不想要的片元。可以用这种方式设置标准值,所有的片元的Alpha通道都会与该值比较,通过就可以参与后续操作,不通过就可以直接丢弃,不影响屏幕上原有的像素,这个过程称为Alpha测试。
当然还是会存在一定的问题,生活中完全透明的物体几乎不存在,大多都是以半透明的形式存在,比如透过绿色玻璃可以看到后面的物体,首先绿色玻璃是我们可以看得到的,其次后面的物体颜色也会蒙上一层绿色。这里就涉及到合并阶段颜色合并的一种方式,混合。不再是替换原来的像素的颜色,我们可以配置混合的方式,来决定合并阶段最终像素的输出颜色。
为了避免看到屏幕渲染的过程,屏幕渲染成像不是立即显示在屏幕上的,而是采用了前后缓冲区。首先场景会渲染到后置缓冲区,等渲染完毕,就翻转到前置缓冲区,这时候我们在屏幕上看到了完整的渲染画面。
小结:
知识点:能够描述整个过程。关键词已经用加粗显示了。这不仅仅是计算机图形学的基础,也是游戏客户端程序员要必须了解的一个点。很多公司面试都会问到这个问题。
参考资料:Real-Time-Rendering-4th