Games101 作业2
作业目标:
- 正确实现三角形栅格化算法。
- 正确测试点是否在三角形内。
- 正确实现 z-buffer 算法, 将三角形按顺序画在屏幕上。
- rasterize_triangle(const Triangle& t):三角形光栅化
- 创建三角形的 2 维 bounding box。
- 遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中 心的屏幕空间坐标来检查中心点是否在三角形内。
- 如果在内部,则将其位置处的插值深度值 (interpolated depth value) 与深度 缓冲区 (depth buffer) 中的相应值进行比较。
- 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区 (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 采样来解决,注意每个采样点都要维护自己的深度值。
这样相对的会提高时间成本。

浙公网安备 33010602011771号