• rasterize_triangle(): 执行三角形栅格化算法
• static bool insideTriangle(): 测试点是否在三角形内
通过计算重心坐标,得到alpha,beta,gamma的值,将其与零进行比较,如果其中存在一个值小于零,那么就可以判断此点不在三角形之内,之后就只需要对内部的点进行深度测试与颜色赋值
数学原理:重心坐标计算出来的三个值实际上是任意一点对三角形的三个顶点的权重,而位于三角形内的点,其权重必然大于等于零
1static bool insideTriangle(float x, float y, const Vector3f* _v)
2{
3 // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
4
5 auto bar = computeBarycentric2D(x, y, _v);
6 if (std::get<0>(bar) < 0 || std::get<1>(bar) < 0 || std::get<2>(bar) < 0)
7 return false;
8 return true;
9}
光栅化在rasterize_triangle()函数内进行,在这个函数中需要执行是否在内部的判断以及深度测试(extra:双重采样)
这里使用的是包围盒算法——找出恰好能够将三角形包围在内的包围盒,之后就只需要在这和盒子内进行每一个像素点的遍历,而不是遍历整个画面
1void rst::rasterizer::rasterize_triangle(const Triangle& t) {
2 auto v = t.toVector4();
3
4 // TODO : Find out the bounding box of current triangle.
5 // iterate through the pixel and find if the current pixel is inside the triangle
6
7 // Create Bounding Box
8 float X_max = (std::max(std::max(v[0].x(), v[1].x()), v[2].x()));
9 float X_min = (std::min(std::min(v[0].x(), v[1].x()), v[2].x()));
10 float Y_max = (std::max(std::max(v[0].y(), v[1].y()), v[2].y()));
11 float Y_min = (std::min(std::min(v[0].y(), v[1].y()), v[2].y()));
12
13 for (int x = X_min; x <= X_max; x++)
14 {
15 for (int y = Y_min; y < Y_max; y++)
16 {
17 if (insideTriangle(x, y, t.v))
18 {
19 auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
20 float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
21 float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
22 z_interpolated *= w_reciprocal;
23
24 if (z_interpolated < depth_buf[get_index(x, y)])
25 {
26 depth_buf[get_index(x, y)] = z_interpolated;
27 Vector3f point = { (float)x,(float)y, z_interpolated }, color = t.getColor();
28 set_pixel(point, color);
29 }
30 }
31 }
32 }
33}
原文:2