gams101 作业2


这次的作业要求实现两个函数

1. insideTriangle函数,用于测试一个点是否在三角形内

2. rasterize_triangle函数,在屏幕空间上光栅化

1.计算三角形三个顶点之间组成的向量和三个点和被测试点组成向量的叉积,若是符号相同,则这个点在三角形内

static bool insideTriangle(int x, int 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]
    // 计算叉积,三个叉积方向相同v02v1内
    // 1. 计算三角形三条边的向量
    Eigen::Vector2f v0_v1, v1_v2, v2_v0;
    v0_v1 << _v[1].x() - _v[0].x(), _v[1].y() - _v[0].y();
    v1_v2 << _v[2].x() - _v[1].x(), _v[2].y() - _v[1].y();
    v2_v0 << _v[0].x() - _v[2].x(), _v[0].y() - _v[2].y();
    // 2. 计算定点到点p的向量
    Eigen::Vector2f v0_p, v1_p, v2_p;
    v0_p << x - _v[0].x(), y - _v[0].y();
    v1_p << x - _v[1].x(), y - _v[1].y();
    v2_p << x - _v[2].x(), y - _v[2].y();
    // 3. 叉乘计算结果
    auto z0 = v0_v1.x() * v0_p.y() - v0_p.x() * v0_v1.y();
    auto z1 = v1_v2.x() * v1_p.y() - v1_p.x() * v1_v2.y();
    auto z2 = v2_v0.x() * v2_p.y() - v2_p.x() * v2_v0.y();

    return (z0 > 0 && z1 > 0 && z2 > 0) || (z0 < 0 && z1 <0 && z2 < 0);
}
  1. 深度测试那一部分的代码是框架里面提供的
//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
    // 1. 找到bounding box
    auto min_x = std::min(v[0].x(), std::min(v[1].x(), v[2].x()));
    auto min_y = std::min(v[0].y(), std::min(v[1].y(), v[2].y()));
    auto max_x = std::max(v[0].x(), std::max(v[1].x(), v[2].x()));
    auto max_y = std::max(v[0].y(), std::max(v[1].y(), v[2].y()));
    // 2. 迭代测试现在的像素是否在三角形内
    for (int x = min_x; x <= int(max_x + 1); x++)
    {
        for (int y = min_y; y <= int(max_y + 1); y++)
        {
            // 如果在三角形内,就深度插值
            if (insideTriangle(x, y, t.v))
            {
                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;

                // 如果点的深度小于z-buffer的深度
                if (depth_buf[get_index(x, y)] > z_interpolated)
                {
                    depth_buf[get_index(x, y)] = z_interpolated;//更新深度
                    Eigen::Vector3f color = t.getColor();
                    Eigen::Vector3f point;
                    point << static_cast(x), static_cast(y), z_interpolated;
                    set_pixel(point, color);//设置颜色
                } 
            }
        }
    } 
}

后记

最近总是觉得特别疲惫,没有动力学习了,科研压力很大,找工作的压力也很大,做人好难。
这个三角形光栅化如果是倒着的,那么就把perp2ortho矩阵的最后一行写成0, 0, -1, 0
具体为什么,见http://games-cn.org/forums/topic/zuoye1sanjiaoxingdiandaowenti/