这一篇来谈一下渲染流程中存在的几个缓冲区。
在日常的cpu程序开发中,缓冲区也就是堆内存区。我做过视频帧的单帧缓存,消息的队列缓存等,都是缓冲区的用法,其主要作用是存储数据后提供对外访问,比如用ffmpeg解码出一帧视频画面并用swscale转为RGB位图数据,储存在一个开辟好大小为width*height*3byte的内存区域中,并提供内存指针供调用者进行mencpy或directdraw,这样的话我只需要做解码和纹理储存的过程就可以了,而不需要管后续别人拿我的纹理数据去具体干嘛。
这种做法很符合软件工程的解耦性,也特别符合大公司螺丝钉政策,一人只负责好自己那一块,哈哈。(俗话说面试造航母,入职拧螺丝)
在图形渲染流程中,就存在三个缓冲区,下面一一说明:
1.模板缓冲区
图形流水线中有一个叫模板测试的流程,作用就是限制绘制的图元区域,其做法是按照窗口宽高创建一个矩阵,矩阵由0,1组成,其中由1组成的区域代表相匹配的图元需要提交到后续流程进行测试和绘制,而由0组成的区域的片元则直接被丢弃,起到一个筛选作用,而这个0,1数值矩阵所在的显存区域则称为模版缓冲区。
0 0 0 0 0 0 0 0 0 0 x x x x x x x x x x
0 0 0 0 0 1 1 1 1 0 x x x x x o o o o x
0 0 0 0 0 1 1 1 1 0 使用左边的模板进行测试后就只显示 x x x x x o o o o x 中o覆盖的区域了。
0 0 0 0 0 0 0 0 0 0 x x x x x x x x x x x
模版测试在shader中很重要的应用就是遮罩mask。
2.深度缓冲区
前面我们也看了渲染流程了,其中顶点变换阶段,通过视口变换就产生了“前后”关系(也就是顶点距离eyeCamera的远近),最后裁剪变换到标准立方体中,就给予了每个顶点附带一个-1到1的z(depth)值,而这个z值保存的显存区域就是深度缓冲区。
像素的深度值可以让GPU高效的渲染画面,因为现实世界中我们人眼观察一个物体,物体正对着我们的面被看见,而背对着我们的面则看不到。从GPU渲染画面的角度来讲就是:从裁剪空间到标准设备空间之后的渲染流程,如果两个不同的片段具有相同的xy坐标值,那么我们可以根据这两个片段的z值选择性丢弃,因为z值更大的那个片段实际上被“遮挡”了,GPU则可以根据z值判断是否需要渲染,这就提高了效率,这在图形学中叫做z消隐。
而比较判断相同xy坐标的片段(经过顶点光栅化,插值贴图着色后片段)的z值的过程叫做深度测试,深度测试成功,则渲染新像素,失败则丢弃。
当然如果我们涉及到透明效果的时候,比如眼前是一个玻璃橱柜,而玻璃橱柜有一个甜甜圈,那么我们还要涉及颜色混合的操作,也就是将玻璃的颜色和甜甜圈的颜色混合起来再更新渲染像素。
3.颜色缓冲区
颜色缓冲区就是最终在显示屏硬件上显示颜色的GPU显存区域了,这个缓冲区储存了每帧更新后的最终颜色值,图形流水线经过一系列测试,包括片段丢弃、颜色混合等,最终生成的像素颜色值就储存在这里,然后提交给显示硬件显示。
这个缓冲区实时更新储存颜色数据,然后GPU通过图形输出口(vga/dvi/hdmi/dp)输出这些数据,不管显示硬件是什么品牌(DELL/宏基/AOC/HKC),亦或者什么设备(CRT/液晶/VR),输出画面颜色数据就行了。