渲染管线的处理流程开始于建立顶点数组(Vertex Array)。这些数组包括了顶点属性(例如顶点在3D空间中的位置)和顶点纹理信息、颜色信息和如何接受光照(顶点法线)。这些顶点数组和其中包含的数据都是在JavaScript中建立的,建立的方法有以下几种:
自己编写JavaScript代码建立
加载并解析一个描述3D模型的文件(例如.obj文件)
使用第三方图形库内置封装好的几何体形状
然后顶点数组里的数据会被填充到一个或多个顶点缓冲(Vertex Buffer)中,并传递到GPU端。在向GPU提交渲染工作的时候,我们还需要提供一个额外的数组用于描述顶点数组中元素的索引。这个顶点索引数组会在稍后控制顶点如何被装配到三角形中。
好了,GPU开始从顶点缓冲中读取顶点信息,并在顶点着色器(Vertex Shader)中处理这些信息。顶点着色器是一个程序,用于读取顶点属性,并输出一个新的属性集合。顶点着色器最基本的功能是计算顶点在屏幕空间中的位置。但它也会为每个顶点生成其他属性,比如颜色或纹理坐标。你可以编写代码自定义顶点着色器,也可以使用第三方图形库提供的顶点着色器。
然后,GPU会连接这些顶点来形成三角形。这里就用到了顶点索引数组,GPU会根据顶点索引的描述,将这些顶点按照指定顺序每3个分成一组,形成一个三角形。
然后光栅器(Rasterizer)会作用于每个三角形,切出这些三角形并忽略形状之外的其他部分,然后将当前剩余的可见部分打碎,填充到像素大小的片元(Fragment)中。对于其他顶点属性(比如颜色和纹理),顶点着色器会在光栅化之后的三角形表面上,为一个顶点和另一个顶点之间的部分做线性插值,为每一个片元(也就是像素)产生一个平滑的渐变值。举例来说,如果顶点着色器为每个顶点分配了一个颜色值,那么光栅器将会混合这些颜色,并在像素化的表面生成一个新的合适的渐变色。关于本段内容更详细的讲解,请参考我们教程的第2课。
这些生成的像素大小的片元之后会被传递到片元着色器(Fragment Shader)中。片元着色器将会输出每个像素的颜色和深度值,用于在帧缓冲(Frame Buffer)中进行绘制。通常情况下,片元着色器的操作包括纹理映射和光照。因为片元着色器会为每个像素进行独立绘制,这就可以实现很多相当复杂的特殊效果;但也正是因为这样,片元着色器也成为图形管线中和性能最为相关的部分。和顶点着色器一样,你可以编写代码自定义片元着色器,也可以使用第三方图形库提供的片元着色器。
最后,帧缓冲(Frame Buffer)是渲染输出的最终目的地。帧缓冲是一个2D图像,但又不仅仅是一个2D图像这么简单。除了一个或多个颜色缓冲区之外,帧缓冲还包含深度缓冲区(Depth Buffer)和/或模板缓冲区(Stencil Buffer),这两个都是在最终绘制到帧缓冲之前可选的过滤片元的方式,深度检测会忽略被前面已经绘制的物体挡住的后面的物体,模板检测会使用模板缓冲区中绘制的形状约束帧缓冲中的可绘制区域,将渲染工作“模板化”。经过这两层过滤之后依然幸存的片元,它们的颜色值会与在它们覆盖之下的颜色值进行α混合。最终的颜色值、深度值、模板值会写入相应的缓冲区。帧缓冲的输出结果也可以用作纹理输入到其他渲染中去(即渲染到纹理,可以参考教程第16课)。
OpenGL渲染管线
最新推荐文章于 2024-03-28 11:45:52 发布