第四章:ZBuffer

        本文是《从0开始图形学》笔记的第四章,通过ZBuffer的作用提高渲染的通用性,本章原理很简单,但是作用不小,本章结束后,我们就可以渲染非常复杂的模型。

 问题引入和分析

        上一节中,我们将箱子的三角面片顺序做了一个调整,否则会出现渲染异常,我们这一节就看一下具体是什么原因,有没有应对方法。

        首先,我们把三角面片的顺序改回去

int _planes[12][3] =      // 面的数据,12个3角形
{
    {0, 1, 2},     // 每个面3个角的顶点对应于索引值
    {2, 3, 0},
    {4, 5, 6},
    {6, 7, 4},
    {1, 5, 6},
    {6, 2, 1},
    {3, 2, 6},
    {6, 7, 3},
    {0, 4, 7},
    {7, 3, 0},
    {0, 1, 5},
    {5, 4, 0},
};

        看下结果

第四章:ZBuffer_第1张图片

      可以看到,箱子的显示出现了异常,这是为什么呢?原因其实也简单,我们按顺序一个一个渲染的三角面片,后渲染的三角面片自然会将前面的结果改写掉,所以不同的顺序就会导致不同的结果。

解决方案

        那么,该如何解决这个问题呢?其实看了本节的标题也大概能猜到,就是使用ZBuffer。ZBuffer也是一张图,大小和渲染结果图一样,其用来记录渲染结果图中对应像素点的Z值,故称为ZBuffer。

        使用方式也很简单,在渲染过程中,首先对比当前像素[x, y]坐标对应的面片的Z坐标和ZBuffer中对应的[x, y]坐标的值大小,如果比ZBuffer中的值大,则说明该点距离摄像机更远,被遮挡,那么就不做处理;否则说明该点距离摄像机更新,更新掉前面的处理结果,同时更新ZBuffer的对应值。

C核心代码实现

        首先,定义ZBuffer图像,并将其填上一个很大的值(比如1e6)

float _Zbuffer[gRstImgHei][gRstImgWid];             // ZBuffer

// 先将结果图画上背景色
for (size_t y = 0; y < gRstImgHei; ++y)
{
	for (size_t x = 0; x < gRstImgWid; ++x)
	{
		_Zbuffer[y][x] = 1e6;
	}
}

        然后,在渲染过程中对比ZBuffer的值,要么跳过,要么更新

if (z > _Zbuffer[y][x])
{
	continue;
}

_Zbuffer[y][x] = z;

渲染结果

第四章:ZBuffer_第2张图片

        可见,和上一节的结果一模一样,但是我们已经可以不用顾忌三角面片的渲染顺序,大大提高了通用性。ZBuffer原理很简单,但作用确很大!

        至此,现有的这150行不到的代码已经可以让我们渲染一些非常复杂的模型,例如下面的这个包含了370000个三角面片的高达模型。

第四章:ZBuffer_第3张图片

完整代码和模型数据见开头的下载资源

你可能感兴趣的:(图形渲染)