boxmoe_header_banner_img

菜就多练喵

文章导读

[C++][图形学]TinyRenderer第三课——重心坐标


avatar
Ib_Mccf 2025年11月2日 13

tinyrenderer项目地址: Barycentric coordinates – Playing with code

一维重心坐标可以用来表示一个线段所在直线上的一个点P。已知线段AB的两个端点,可知P = uA + vB (u + v = 1)。当u和v都不<0时,P在线段AB上。经过变化得到 u = (B – P) / (B – A), v = 1 – u = (P – A) / (B – A)。

二维中心坐标可以用来表示一个三角形所在平面上的一个点P。已知三角形ABC的三个顶点,可知P = uA + vB + wC (u + v + w = 1)。当u,v,w都不<0时,P在三角形ABC内部。u,v,w可以通过子三角形面积和总面积的比值得出(面积计算是有向的,可能会的出负数),u = Area(PBC) / Area(ABC) , v = Area(PCA) / Area(ABC) , w = Area(PAB) / Area(ABC)。

鞋带配方 – 维基百科:通过三个顶点计算三角形面积。下方的公式是有向的,根据顶点的顺序可能会产生负数。

Area(ABC) = 0.5f * ((bx*cy – cx*by) – (ax*cy – cx*ay) + (ax*by – bx*ay))

或者Area(ABC) = 0.5f * ((ax*by + bx*cy + cx*ay) – (ay*bx + by*cx + cy*ax))

通过重心坐标对颜色进行插值,并绘制线框。

#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 u = static_cast<unsigned char>(alpha * az);
            unsigned char v = static_cast<unsigned char>(beta * bz);
            unsigned char w = static_cast<unsigned char> (gamma * cz);
            if(u < 15 ||v< 15 || w < 15)
                framebuffer.set(x, y,  {{u, v,w, 255}});
        }
    }


评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码