[Games101笔记] 作业1-2

作业1 基础版

    //视图转换
    Eigen::Matrix4f get_view_matrix(Eigen::Vector3f eye_pos)
    {
        // 定义 4 * 4 的单位矩阵
        Eigen::Matrix4f view = Eigen::Matrix4f::Identity();
     
        Eigen::Matrix4f translate;
        // 初始化视角变换矩阵
        translate << 1, 0, 0, -eye_pos[0], 
                     0, 1, 0, -eye_pos[1], 
                     0, 0, 1,-eye_pos[2], 
                     0, 0, 0, 1;
     
        view = translate * view;
     
        return view;
    }

透视投影变换矩阵

1 .将视锥压缩成正交投影变换矩阵可处理的形式

image

2 .正交投影

image

// 绕 z 轴旋转的变换矩阵
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
    // 初始化一个单位矩阵model
    Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
    // TODO: Implement this function
    // Create the model matrix for rotating the triangle around the Z axis.
    // Then return it.

    // ---------
    Eigen::Matrix4f M_rotation;
    // 弧度制
    float rotation_radian = rotation_angle * MY_PI / 180;
    // 绕z轴的旋转矩阵
    M_rotation << cos(rotation_radian), -sin(rotation_radian), 0, 0,
                    sin(rotation_radian), cos(rotation_radian), 0, 0,
                    0, 0, 1, 0,
                    0, 0, 0, 1;
    
    model *= M_rotation;
    // ---------

    return model;
   
}

//eye_fov:纵向视野(度), aspect_ratio:宽高比
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
    float zNear, float zFar)
{

    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

    // TODO: Implement this function
    // Create the projection matrix for the given parameters.
    // Then return it.

    // ---------
    Eigen::Matrix4f M_perToOrtho(4, 4);
    Eigen::Matrix4f M_ortho_scale(4, 4);
    Eigen::Matrix4f M_ortho_trans(4, 4);

    // 纵向视野的一半,eye_fov * MY_PI / 2 / 180.0
    float half_angle = eye_fov * MY_PI / 360.0; 
    float top = zNear * tan(half_angle);
    float bottom = -top;
    float right = top * aspect_ratio;
    float left = -right;
    
    M_ortho_trans << 1, 0, 0, -(right+left) / 2,
                    0, 1, 0, -(top+bottom) / 2,
                    0, 0, 1, -(zNear+zFar) / 2,
                    0, 0, 0, 1;
    M_ortho_scale << 2 / (right-left), 0, 0, 0,
                    0, 2 / (top-bottom), 0, 0,
                    0, 0, 2 / (zNear-zFar), 0,
                    0, 0, 0, 1;
    M_perToOrtho << zNear, 0, 0, 0,
                    0, zNear, 0, 0,
                    0 ,0, zNear+zFar, -zNear*zFar,
                    0, 0, 1, 0;
                    
    Eigen::Matrix4f M_ortho = M_ortho_scale * M_ortho_trans;
    projection = M_ortho * M_perToOrtho;
    // ---------

    return projection;
}

效果

image

作业2

insideTriangle

//判断是否在三角形内
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]
    std::vector<Vector3f> vecTriangle, vecInner;
    vecTriangle.push_back({_v[1].x()-_v[0].x(), _v[1].y()-_v[0].y(), 0});
    vecTriangle.push_back({_v[2].x()-_v[1].x(), _v[2].y()-_v[1].y(), 0});
    vecTriangle.push_back({_v[0].x()-_v[2].x(), _v[0].y()-_v[2].y(), 0});

    vecInner.push_back({x-_v[0].x(), y-_v[0].y(), 0});
    vecInner.push_back({x-_v[1].x(), y-_v[1].y(), 0});
    vecInner.push_back({x-_v[2].x(), y-_v[2].y(), 0});

    int cntPosi = 0, cntNega = 0;
    for(int i = 0; i < 3; i ++)
    {
        if(vecTriangle[i].cross(vecInner[i]).z() < 0) 
            cntNega ++;
        else
            cntPosi ++;
    }
    // 判断该点是否在三个向量同侧, 即内部
    if(cntNega == 3 || cntPosi == 3) return true;
    else return false;
}

rasterize_triangle

//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
    auto v = t.toVector4();
    
    // TODO : Find out the bounding box of current triangle.
    //找bounding box的边界
    int vertical_min, vertical_max, cross_min, cross_max;
    vertical_min = v[0].y() < v[1].y() ? v[0].y() : v[1].y();
    vertical_min = vertical_min < v[2].y() ? vertical_min : v[2].y();

    vertical_max = v[0].y() > v[1].y() ? v[0].y() : v[1].y();
    vertical_max = vertical_max > v[2].y() ? vertical_max : v[2].y();

    cross_min = v[0].x() < v[1].x() ? v[0].x() : v[1].x();
    cross_min = cross_min < v[2].x() ? cross_min : v[2].x();

    cross_max = v[0].x() > v[1].x() ? v[0].x() : v[1].x();
    cross_max = cross_max > v[2].x() ? cross_max : v[2].x();

    // iterate through the pixel and find if the current pixel is inside the triangle
    float alpha, beta, gamma;
    for(float i = int(cross_min)-1; i <= int(cross_max)+1; i ++)
    {
        for(float j = int(vertical_min)-1; j <= int(vertical_max)+1; j ++)
        {
            // iterate through the pixel and find if the current pixel is inside the triangle
            if(insideTriangle(i, j, t.v))
            {
                // If so, use the following code to get the interpolated z value.
                std::tie(alpha, beta, gamma) = computeBarycentric2D(i+0.5, j+0.5, 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;

                // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
                if(-z_interpolated < depth_buf[get_index(i, j)]){
                    set_pixel({i, j, 0}, t.getColor());
                    depth_buf[get_index(i, j)] = -z_interpolated;
                }
            }
        }
    }
}

效果

image

posted @ 2022-10-04 19:10  泥烟  阅读(80)  评论(0编辑  收藏  举报