tinyRenderer项目地址:Hidden faces removal – Playing with code
在第二课三角形光栅化中将模型的每个三角面进行了绘制,将有向面积<1的面进行了剔除,得到的图像看起来有些杂乱,尤其是左下角大腿与尾巴的交接处。

通过绘画家算法,将所有的像素点从后向前绘制,即可剔除不可见的面,保证正确的绘制顺序。
可以将所有的三角面按三个顶点的最大z轴进行排序,再进行绘制,可以看到比上图效果好了很多。

但是排序z轴的方法在性能消耗上是很大的,而且只选择三个顶点中最大的z轴排序得到的顺序并不是一定正确的,如下图。

这是没有经过z轴排序,也就是最开始图片的灰度图,灰度代表了z的深度

可以通过深度缓存存储深度值,若当前像素的z轴小于缓存中的值,则说明已经有像素绘制在更前面(接近相机),直接丢弃当前像素,否则绘制该像素并计入缓存。
void triangle(int ax, int ay, int az, int bx, int by, int bz, int cx, int cy, int cz, TGAImage &zbuffer, TGAImage &framebuffer, TGAColor color) {
int bbminx = std::min(std::min(ax, bx), cx); // bounding box for the triangle
int bbminy = std::min(std::min(ay, by), cy); // defined by its top left and bottom right corners
int bbmaxx = std::max(std::max(ax, bx), cx);
int bbmaxy = std::max(std::max(ay, by), cy);
double total_area = signed_triangle_area(ax, ay, bx, by, cx, cy);
if (total_area<1) return; // backface culling + discarding triangles that cover less than a pixel
#pragma omp parallel for
for (int x=bbminx; x<=bbmaxx; x++) {
for (int y=bbminy; y<=bbmaxy; y++) {
double alpha = signed_triangle_area(x, y, bx, by, cx, cy) / total_area;
double beta = signed_triangle_area(x, y, cx, cy, ax, ay) / total_area;
double gamma = signed_triangle_area(x, y, ax, ay, bx, by) / total_area;
if (alpha<0 || beta<0 || gamma<0) continue; // negative barycentric coordinate => the pixel is outside the triangle
unsigned char z = static_cast<unsigned char> (alpha * az +beta * bz + gamma * cz);
//若比缓存值小,直接丢弃
if (z <= zbuffer.get(x, y)[0]) continue;
zbuffer.set(x, y, {z});
framebuffer.set(x, y, color);
}
}
}


评论(0)
暂无评论