Games101 作业2

作业目标:

  1. 正确实现三角形栅格化算法。
  2. 正确测试点是否在三角形内。
  3. 正确实现 z-buffer 算法, 将三角形按顺序画在屏幕上。

 

  • rasterize_triangle(const Triangle& t):三角形光栅化
  1. 创建三角形的 2 维 bounding box。
  2. 遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中 心的屏幕空间坐标来检查中心点是否在三角形内。
  3. 如果在内部,则将其位置处的插值深度值 (interpolated depth value) 与深度 缓冲区 (depth buffer) 中的相应值进行比较。
  4. 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区 (depth buffer)。
void rst::rasterizer::rasterize_triangle(const Triangle& tri) {
    auto v = tri.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 l, r, b, t; //bounding box 边界,注意向上和向下的取整
    l = floor(std::min(v[0][0], std::min(v[1][0], v[2][0])));
    r = ceil(std::max(v[0][0], std::max(v[1][0], v[2][0])));
    b = floor(std::min(v[0][1], std::min(v[1][1], v[2][1])));
    t = ceil(std::max(v[0][1], std::max(v[1][1], v[2][1])));

    for (int i = l; i < r; i++) {
        for (int j = b; j < t; j++) {
            if (insideTriangle(i+0.5, j+0.5, &v[0])) {
                auto [alpha, beta, gamma] = computeBarycentric2D(i, j, tri.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 (depth_buf[get_index(i, j)] > z_interpolated) {
                    depth_buf[get_index(i, j)] = z_interpolated;
                    Vector3f point(3);
                    point << (float)i, (float)j, 0;
                    set_pixel(point, tri.getColor());
                }
            }
        }
    }
}

 

  • static bool insideTriangle(): 判断点是否在三角形内。
static float _cross(const Vector4f& a, const Vector4f& b, Vector4f& c) {
    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
}

static bool insideTriangle(int x, int y, const Vector4f* _v)
{   
    Vector4f p(x, y, 1.0, 1.0);
    // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
    float res[3];
    for (int i = 0; i < 3; i++) {
        res[i] = _cross(_v[i], _v[(i + 1) % 3], p);
    }
    for (int i = 0; i < 3; i++) {
        if (res[i] * res[(i + 1) % 3] <= 0) {
            return false;
        }
    }
    // TODO 还可以加一个_v是否构成三角形的判断,即res!=0
    return true;
}

 

输出:

 

 可以看到三角形边缘有明显锯齿,锯齿可以通过再次细分像素进行判断来弱化,作业建议里是对每个像素进行 2 * 2 采样来解决,注意每个采样点都要维护自己的深度值。

这样相对的会提高时间成本。

posted @ 2021-02-24 21:18  一语子  阅读(185)  评论(0)    收藏  举报