#16631 Score: 0
CheapMeow
Participant

用面积计算是合适的

比如我这里使用面积计算重心坐标,可以得到预期的效果


static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector4f* v){
    Eigen::Vector2f p(x, y);

    Eigen::Vector2f tri_node_coords[3];
    for (int i = 0; i < 3; ++i) {
        tri_node_coords[i] = v[i].head<2>();
    }

    Eigen::Vector2f edge_1, edge_2;
    float s_sub_tri[3];
    for (int i = 0; i < 3; ++i) {
        edge_1 = tri_node_coords[(i + 1) % 3] - p;
        edge_2 = tri_node_coords[(i + 2) % 3] - p;
        s_sub_tri[i] = edge_1.x() * edge_2.y() - edge_2.x() * edge_1.y();
    }

    float s_sum = 0;
    for (int i = 0; i < 3; ++i) {
        s_sum += s_sub_tri[i];
    }

    return { s_sub_tri[0] / s_sum, s_sub_tri[1] / s_sum, s_sub_tri[2] / s_sum };
}

如果担心计算出来的重心坐标为负会不会不正确,那么可以试着在 rasterize_triangle() 光栅化三角形的时候就剔除掉那些重心坐标为负的点


void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos) 
{
    int x_screen_min = width - 1;
    int x_screen_max = 0;
    int y_screen_min = height - 1;
    int y_screen_max = 0;

    for (int i = 0; i < 3; i++) {
        x_screen_min = std::min(x_screen_min, (int)t.v[i][0]);
        y_screen_min = std::min(y_screen_min, (int)t.v[i][1]);
        x_screen_max = std::max(x_screen_max, (int)t.v[i][0]);
        y_screen_max = std::max(y_screen_max, (int)t.v[i][1]);
    }

    // temp var

    Eigen::Vector3f interpolated_color;
    Eigen::Vector3f interpolated_normal;
    Eigen::Vector2f interpolated_texcoords;
    Eigen::Vector3f interpolated_shadingcoords;

    for (int x = x_screen_min; x <= x_screen_max; ++x) {
        for (int y = y_screen_min; y <= y_screen_max; ++y) {
            if (insideTriangle(x + 0.5f, y + 0.5f, t.v)) {
                auto [alpha, beta, gamma] = computeBarycentric2D(x + 0.5f, y + 0.5f, t.v);
                if (alpha < 0.0f || alpha > 1.0f) continue;
                if (beta < 0.0f || beta > 1.0f) continue;
                if (gamma < 0.0f || gamma > 1.0f) continue;

可见,在模型的每一个三角面的边上显示出缝隙

也就是说,重心坐标为负的点也可能位于三角形的边上

如果去掉了这些点,就相当于在三角形的边上没有颜色,那么渲染出来的就会在模型的每一个三角面的边上显示出缝隙

所以只要你的 insideTriangle() 写对了,就不需要考虑 computeBarycentric2D() 算出来的重心坐标为负还是为正

Attachments:
You must be logged in to view attached files.