Games101 作业2 shading

按照工作流程来写

首先创建三角形的bounding box,就是找一个正好放下三角形的矩形,方便之后进行遍历

之后,遍历这个box内的所有像素,找出在三角形内的像素;

首先,需要判断一个点是否在三角形内,可以通过叉乘的方法进行计算

遍历box内每一个像素,如果在三角形内,计算插值深度值,然后再判断像素的深度值,对于更靠前的像素,就更新像素的颜色与深度缓冲区

完整的代码:

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]
    Vector2f p(x,y);
    // x.head(2) 取前n个值
    Vector2f AB = _v[1].head(2) - _v[0].head(2);
    Vector2f BC = _v[2].head(2) - _v[1].head(2);
    Vector2f CA = _v[0].head(2) - _v[2].head(2);

    Vector2f AP = p - _v[0].head(2);
    Vector2f BP = p - _v[1].head(2);
    Vector2f CP = p - _v[2].head(2);
    //叉乘计算点在不在三角形内
    return  AB[0]*AP[1] - AB[1]*AP[0]>0 &&
            BC[0]*BP[1] - BC[1]*BP[0]>0 &&
            CA[0]*CP[1] - CA[1]*CP[0]>0 ;
}

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    float x_min,y_min,x_max,y_max;
    // TODO : Find out the bounding box of current triangle.
    //bounding box  找出一个正好放下三角形的矩形
    x_min = min( v[0][0] , min( v[1][0] , v[2][0] ) );
    x_max = max( v[0][0] , max( v[1][0] , v[2][0] ) );
    y_min = min( v[0][1] , min( v[1][1] , v[2][1] ) );
    y_max = max( v[0][1] , max( v[1][1] , v[2][1] ) );
    //floor 向下取整   ceil 向上取整 
    x_min = (int)floor(x_min);
    y_min = (int)floor(y_min);
    x_max = (int)ceil(x_max);
    y_max = (int)ceil(y_max);
    // iterate through the pixel and find if the current pixel is inside the triangle
    //遍历矩形内的每一个像素,判断这个像素在不在三角形内
    for(int x=x_min;x<=x_max;x++)
        for(int y=y_min;y<=y_max;y++){
            //如果在三角形内,计算它的插值深度值,比较插值深度值与深度缓冲区的大小
            if(insideTriangle(x+0.5f,y+0.5f,t.v)){
                float alpha,beta,gamma;
                auto ans = computeBarycentric2D(x+0.5f,y+0.5f,t.v);
                tie(alpha,beta,gamma)=ans;
                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(depth_buf[get_index(x,y)]>z_interpolated){
                    Vector3f color = t.getColor();
                    Vector3f point(3);
                    point<<x , y , z_interpolated;
                    depth_buf[get_index(x,y)] = z_interpolated;
                    set_pixel(point,color);
                }
            }
        }
    // 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;
  
    // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
}

最终的结果