作业2 Triangles and Z-buffering

作业2简单介绍

作业2 Triangles and Z-buffering

在作业1的基础上,首先还是自己填补MVP算法的代码;实现两个函数,一个是判断点是否在三角形内,一个是光栅化三角形;

提高作业使用MSAA反走样操作,简而言之就是在一个像素点的软件层面上把一个像素点分为4个像素点,然后最后求一个平均 首先是求出三角形的边界,然后循环遍历其中的点,然后求z值,框架代码中已经给出。

判断点是是否在三角形内(利用叉积):

static bool insideTriangle(float x, float y, const Vector3f* _v)
{   
    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
    Vector3f p;
    p << x,y,0;
    Vector3f A,B,C;
    A = _v[0];
    B = _v[1];
    C = _v[2];
    Vector3f ans1,ans2,ans3;
    ans1 = (B-A).cross(p-A);
    ans2 = (C-B).cross(p-B);
    ans3 = (A-C).cross(p-C);
    if(ans1.z()>0&&ans2.z()>0&&ans3.z()>0){
        return true;
    }
    else return false;
}

光栅化三角形:

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    // iterate through the pixel and find if the current pixel is inside the triangle
    // If so, use the following code to get the interpolated z value.
    //auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
    //float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
    //float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
    //z_interpolated *= w_reciprocal;
    auto v = t.toVector4();
    float x_min = std::min(v[0].x(),std::min(v[1].x(),v[2].x()));
    float x_max = std::max(v[0].x(),std::max(v[1].x(),v[2].x()));
    float y_min = std::min(v[0].y(),std::min(v[1].y(),v[2].y()));
    float y_max = std::max(v[0].y(),std::max(v[1].y(),v[2].y()));
    
    x_min = int(x_min+0.5);
    x_max = int(x_max+0.5);
    y_min = int(y_min+0.5);
    y_max = int(y_max+0.5);

    float dx[4] = {0.25,0.25,0.75,0.75};
    float dy[4] = {0.25,0.75,0.25,0.75};

    // 一个像素划分为4个像素,use MSAA
    for(int x = x_min;x <= x_max;++x) {
        for(int y = y_min;y <= y_max;++y) {
            int cnt = 0;
            float min_z = FLT_MAX;
            for(int i = 0;i<4;++i){
                float xx = x+dx[i] ,yy = y+dy[i];
                if(insideTriangle(xx,yy,t.v)) {
                    auto[alpha, beta, gamma] = computeBarycentric2D(xx, yy, t.v);
                    float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
                    float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
                    z_interpolated *= w_reciprocal;
                    min_z = std::min(min_z,z_interpolated);
                    cnt ++;
                }
            }
            if(cnt) {
                if(min_z<depth_buf[get_index(x,y)]) {
                        depth_buf[get_index(x,y)] = min_z;
                        auto color = t.getColor();
                        auto point = Eigen::Vector3f(x,y,cnt); //在set_pixel中有求平均操作
                        set_pixel(point,color);
                    }
            }
        }
    }

    // for(int x = x_min;x <= x_max;++x) {
    //     for(int y = y_min;y <= y_max;++y) {
    //         float xx = x+0.5 ,yy = y+0.5;
    //         if(insideTriangle(xx,yy,t.v)) {
    //             auto[alpha, beta, gamma] = computeBarycentric2D(xx, yy, t.v);
    //             float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
    //             float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
    //             z_interpolated *= w_reciprocal;

    //             if(z_interpolated<depth_buf[get_index(x,y)]) {
    //                 depth_buf[get_index(x,y)] = z_interpolated;
    //                 auto color = t.getColor();
    //                 auto point = Eigen::Vector3f(x,y,0);
    //                 set_pixel(point,color);
    //             }
    //         }
    //     }
    // }
}