欢迎来到NiceSpace!祝大家开心每一天!
  • C++
  • 图形学
3D图形学总结(十一)—深度缓存

    在前面的学习中,总是用一个箱子来进行各种测试,但是在世界中如果有很多个物体,然后将物体都加入渲染列表中后,发现渲染出来的效果跟想象中的不一样。

    这是因为渲染接口接受到渲染列表中的三角形面是无序的,没有顺序先后之分,总是把新收到的三角形渲染到屏幕上并覆盖到屏幕本来像素点的颜色。也许我们可以为插入到渲染列表中的三角形排序,但是如果两个三角形相互交叉互相遮盖,对于这样的情况排序还是无法解决,如图:

    对于图中这种情况对于排序是无用的,因为即使排了序无论先渲染哪个三角形都会覆盖掉另一个,并不能保证真实的3d效果,可以看下面效果图:

    这是很多个箱子重叠在一起,渲染出来的结果是乱乱的根本看不出先后之分,这并不是我们想要的。

    z缓存算法可以解决这个问题,算法基于像素进行z排序。

    对于一个大小为MxN的屏幕,创建一个z缓存zbuffer[M][N],其中包含每个多边形中每个像素被光栅化扫描转换后的z值。

    算法的思路:

    1、创建一个二维数组zbuffer,大小为屏幕大小MxN,将所有的数据全部初始化为远裁剪面的值。

    2、对三角形进行光栅化,计算三角形在屏幕上每个像素点的xi, yi, zi的值,其中xi和yi表示的是像素点的屏幕坐标,范围是xi(0 - M),yi(0 - N),zi表示该点在三维空间的z坐标。

    3、对于每个像素点,如果该点的z值小于z缓存中对应zbuffer[xi][yi]中的z值,表示渲染当前的像素点距离我们的视点更近,所以可以直接将该点的颜色值覆盖掉屏幕上当前点的颜色,并且用该点的值更新到zbuffer[xi][yi],对于渲染列表中都这样操作后就可以保证屏幕上我们看到的结果,就是3d世界中真实的样子。

    结合图示我们可以更清晰的明白z缓存的工作原理。

    下面要说下有问题的地方,我们在传递给渲染接口的只有三角形3个点的信息,所以三角形面所有的像素点的z值都是插值计算出来的,然而我们之前的透视矫正过程说过,视平面的透视坐标是与1/z成线性的,所以我们用z来进行缓存是有误差的。我们应该对1/z进行缓存,这样才是最后正确的结果。

    修正后的算法,我们只需要在之前的算法中zbuffer全都初始化为0,并且在光栅化阶段时判断每个像素点的1/z值是否大于zbuffer中的1/z值,大于的话就刷新屏幕兵刷新zbuffer,这样就ok了。

    下面是经过1/z深度缓存处理后的效果图,与我们世界中真实的一样:

随机文章
一个简单的CSS加载动画 3D图形学总结(七)—Gouraud着色和仿射纹理映射 深入理解字符串(编码,解码,乱码问题) 阿里云ECS(win server2008)部署Django 3D图形学总结(十二)—纹理滤波
推荐文章