boxmoe_header_banner_img

菜就多练喵

文章导读

[C++][图形学]tinyRenderer第四课——不可见面剔除


avatar
Ib_Mccf 2025年11月2日 19

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)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码