GAMES101-现代计算机图形学学习笔记(2)作业1

前言

作业0

本篇继续更新作业1相关,本专栏预计2个星期内搞定。

作业1相关链接

games的作业1链接

我的源码

作业1简述

  1. 模拟基于CPU的光栅化渲染器
  2. 绘制要求中的三角形

作业1相关知识笔记

  • 2D仿射变换和3D仿射变换矩阵推导

  • 坐标系转化

  • 视口变换

  • 正交投影与透视投影

  • 屏幕像素表示

  • 光栅化算法:

    直线:DDA数值微分算法、中点Bresenham算法

    三角形:BoundingBox

作业1思路
注意:后面有代码展示,一定要自己先做一遍再看,而且我的设计不一定正确规范高效。

  • 熟悉整个框架

    最好先熟悉渲染器是怎么工作的。

在这里插入图片描述

整个框架结构如上图所示。其中rastrizer.hpp生成渲染器。大佬提供的框架还实现了安全绘制防止绘图顺序混淆。框架中DrawLine使用的是DDA数值微分算法,想了解怎么实现的可以看一下。

rastrizer.hpp中主要功能函数声明:

class rasterizer
{
  public:
    rasterizer(int w, int h);
    pos_buf_id load_positions(const std::vector<Eigen::Vector3f>& positions);
    ind_buf_id load_indices(const std::vector<Eigen::Vector3i>& indices);

    void set_model(const Eigen::Matrix4f& m);
    void set_view(const Eigen::Matrix4f& v);
    void set_projection(const Eigen::Matrix4f& p);

    void set_pixel(const Eigen::Vector3f& point, const Eigen::Vector3f& color);

    void clear(Buffers buff);

    void draw(pos_buf_id pos_buffer, ind_buf_id ind_buffer, Primitive type);

    std::vector<Eigen::Vector3f>& frame_buffer() { return frame_buf; }

  private:
    void draw_line(Eigen::Vector3f begin, Eigen::Vector3f end);
    void rasterize_wireframe(const Triangle& t);

  private:
    Eigen::Matrix4f model;
    Eigen::Matrix4f view;
    Eigen::Matrix4f projection;

    std::map<int, std::vector<Eigen::Vector3f>> pos_buf;
    std::map<int, std::vector<Eigen::Vector3i>> ind_buf;

    std::vector<Eigen::Vector3f> frame_buf;
    std::vector<float> depth_buf;
    int get_index(int x, int y);

    int width, height;

    int next_id = 0;
    int get_next_id() { return next_id++; }
};

main.cpp中模拟了render pipline。流程大致为

(1)绘制(700,700)大小的frame buffer和depth buffer.

(2)设置相机位置(0,0,5).

(3)绘制线段(三角形).

(4)下一帧清除buffer,再绘制.

此外要修正框架中rastrizer.cpp中set_pixel()中ind变量,不然会出现越界

void rst::rasterizer::set_pixel(const Eigen::Vector3f& point, const Eigen::Vector3f& color)
{
    //old index: auto ind = point.y() + point.x() * width;
    if (point.x() < 0 || point.x() >= width ||
        point.y() < 0 || point.y() >= height) return;
    auto ind = (height-1-point.y())*width + point.x();
    frame_buf[ind] = color;
}
  • 完善流程

    在视频中已经推导过偏移矩阵,这里就直接套用参数到模型变换矩阵上即可

    Eigen::Matrix4f get_model_matrix(float rotation_angle)
    {
        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 rotating;
        float angle = rotation_angle/180*MY_PI;
        
        rotating<< std::cos(angle),-1*std::sin(angle),0,0,\
                   std::sin(angle),std::cos(angle),0,0,\
                   0,0,1,0,\
                   0,0,0,1;
        
        model=rotating*model;
    
        return model;
    }
    

    构建透视投影矩阵,这个也详细推导过

    (视频P4

    视图矩阵推导33:08

    欢迎补充)

    Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
                                          float zNear, float zFar)
    {
        // Students will implement this function
    
        Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
    
        // TODO: Implement this function
        // Create the projection matrix for the given parameters.
        // Then return it.
    
        Eigen::Matrix4f orthographic_matrix = Eigen::Matrix4f::Identity();    
        Eigen::Matrix4f scale = Eigen::Matrix4f::Identity();
        Eigen::Matrix4f translate = Eigen::Matrix4f::Identity();
        Eigen::Matrix4f presp_to_ortho_matrix = Eigen::Matrix4f::Identity();
        double top = std::tan((eye_fov/2)/180*MY_PI/2)*zNear;
        double right = top*aspect_ratio;
        float bottom = -top;
        float left = -right;
     
        scale<< 2/(right-left),0,0,0,\
                0,2/(top-bottom),0,0,\
                0,0,2/(zNear-zFar),0,\
                0,0,0,1;
        translate<< 1,0,0,-1*(right+left)/2,\
                    0,1,0,-1*(top+bottom)/2,\
                    0,0,1,-1*(zNear+zFar)/2,\
                    0,0,0,1;
    
        orthographic_matrix = scale*translate;
    
        presp_to_ortho_matrix<< zNear,0,0,0,\
                                0,zNear,0,0,\
                                0,0,zNear+zFar,-1*(zNear*zFar),\
                                0,0,1,0;
        projection = orthographic_matrix*presp_to_ortho_matrix;
                            
        return projection;
    }
    

    提高部分:

    Eigen::Matrix4f get_rotation(Vector3f axis,float angle){
        Eigen::Matrix4f rotating = Eigen::Matrix4f::Identity();
        float radian = angle/180*MY_PI;
        float x = axis.x();
        float y = axis.y();
        float z = axis.z();
        float cos_angle = std::cos(radian);
        float sin_angle = std::sin(radian);
    
        rotating << x*x+(1-x*x)*cos_angle,x*y*(1-cos_angle)+z*sin_angle,x*z*(1-cos_angle)-y*sin_angle,0,\
                    x*y*(1-cos_angle)-z*sin_angle,y*y+(1-y*y)*cos_angle,y*z*(1-cos_angle)+sin_angle,0,\
                    x*z*(1-cos_angle)+y*sin_angle,y*z*(1-cos_angle)-x*sin_angle,z*z+(1-z*z)*cos_angle,0,\
                    0,0,0,1;
                    
        return rotating;
    }
    

    最后效果
    在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值