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<float>(x), static_cast<float>(y), z_interpolated;
                    set_pixel(point, color);//设置颜色
                } 
            }
        }
    } 
}
posted @   yuzuki_n  阅读(62)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示