Games101--Assignment2

Gams101的Assignment2的要求如下:

修改函數rasterize_triangle(const Triangle& t)。
該函數的內部工作流程如下:

  1. 創建三角形的2 維bounding box。
  2. 遍歷此bounding box 內的所有像素(使用其整數索引)。然後,使用像素中心的屏幕空間座標來檢查中心點是否在三角形內。
  3. 如果在內部,則將其位置處的插值深度值(interpolated depth value) 與深度緩衝區(depth buffer) 中的相應值進行比較。
  4. 如果當前點更靠近相機,請設置像素顏色並更新深度緩衝區(depth buffer)。

需要修改的函數如下:
• rasterize_triangle(): 執行三角形柵格化算法
• static bool insideTriangle(): 測試點是否在三角形內。

判斷點是否在三角形內,只要用叉積來判斷方向即可。

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]
    float a=_v[0].x(),b=_v[0].y(),c=_v[1].x(),d=_v[1].y(),e=_v[2].x(),f=_v[2].y();
    float t1=(c-a)*(y-b)-(d-b)*(x-a);
    float t2=(e-c)*(y-d)-(f-d)*(x-c);
    float t3=(a-e)*(y-f)-(b-f)*(x-e);
    bool x1=true?t1>0.0:false,x2=true?t2>0.0:false,x3=true?t3>0.0:false;
    bool ret=false;
    if((x1 &x2&x3) || (!x1)&(!x2)&(!x3)) ret=true;
    return ret;
}

rasterize_triangle(),使用MSAA,用的是4x4的supersampling。

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    
    // TODO : Find out the bounding box of current triangle.
    // iterate through the pixel and find if the current pixel is inside the triangle
    int left=MIN(v[0].x(),MIN(v[1].x(),v[2].x()))-1;
    int right=MAX(v[0].x(),MAX(v[1].x(),v[2].x()))+1;
    int bottom=MIN(v[0].y(),MIN(v[1].y(),v[2].y()))-1;
    int top=MAX(v[0].y(),MIN(v[1].y(),v[2].y()))+1;

    //4x4 SuperSampling
    float dir[16][2]={
        {0.125,0.125},
        {0.125,0.375},
        {0.125,0.625},
        {0.125,0.875},
        {0.375,0.125},
        {0.375,0.375},
        {0.375,0.625},
        {0.375,0.875},
        {0.625,0.125},
        {0.625,0.375},
        {0.625,0.625},
        {0.625,0.875},
        {0.875,0.125},
        {0.875,0.375},
        {0.875,0.625},
        {0.875,0.875},
    };
    for(int x=left;x<=right;x++){
        for(int y=bottom;y<=top;y++){
            float min_dep=0x7f7ffff;
            int count=0;
            for(int i=0;i<16;i++){
                if(insideTriangle(x+dir[i][0],y+dir[i][1],t.v)){
                    count++;
                    std::tuple<float, float, float> alpha= computeBarycentric2D(x, y, t.v);
                    float w_reciprocal = 1.0/(std::get<0>(alpha) / v[0].w() + std::get<1>(alpha) / v[1].w() + std::get<2>(alpha) / v[2].w());
                    float z_interpolated = std::get<0>(alpha)* v[0].z() / v[0].w() + std::get<1>(alpha) * v[1].z() / v[1].w() + std::get<2>(alpha) * v[2].z() / v[2].w();
                    z_interpolated *= w_reciprocal;
                    min_dep=MIN(min_dep,z_interpolated);
                }
            }
            if(count==0)continue;
            if(min_dep < depth_buf[get_index(x,y)]){
                depth_buf[get_index(x,y)]=min_dep;
                set_pixel(Vector3f(x,y,min_dep),t.getColor()*count/16.0);
            }
        }
    }
    // If so, use the following code to get the interpolated z value.
    //auto tpp = computeBarycentric2D(x, y, t.v);
    //float alpha, beta, gamma;
    //std::tie(alpha, beta, gamma)=tpp;
    //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;

    // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}

如果不用MSAA,則代碼如下:

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    
    // TODO : Find out the bounding box of current triangle.
    // iterate through the pixel and find if the current pixel is inside the triangle
    int left=MIN(v[0].x(),MIN(v[1].x(),v[2].x()))-1;
    int right=MAX(v[0].x(),MAX(v[1].x(),v[2].x()))+1;
    int bottom=MIN(v[0].y(),MIN(v[1].y(),v[2].y()))-1;
    int top=MAX(v[0].y(),MIN(v[1].y(),v[2].y()))+1;
    for(int x=left;x<=right;x++)
    {
        for(int y=bottom;y<=top;y++)
        {
           if(insideTriangle(x,y,t.v))
           {
               std::tuple<float, float, float> alpha= computeBarycentric2D(x, y, t.v);
               float w_reciprocal = 1.0/(std::get<0>(alpha) / v[0].w() + std::get<1>(alpha) / v[1].w() + std::get<2>(alpha) / v[2].w());
                float z_interpolated = std::get<0>(alpha)* v[0].z() / v[0].w() + std::get<1>(alpha) * v[1].z() / v[1].w() + std::get<2>(alpha) * 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;
                    set_pixel(Vector3f(x,y,z_interpolated),t.getColor());
                }
            }
        }   
    }
    // If so, use the following code to get the interpolated z value.
    //auto tpp = computeBarycentric2D(x, y, t.v);
    //float alpha, beta, gamma;
    //std::tie(alpha, beta, gamma)=tpp;
    //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;

    // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}

兩者對比結果如下:

without_MSAA with_MSAA
在這裏插入圖片描述 在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章