GAMES101作业(更新中)

lz最近在学习图形学Graphics,现已学完GAMES101课程,为回顾课程重要内容故将作业总结发布至此,欢迎各位同学交流。

作业0:虚拟机的使用

关于虚拟机如何搭建,请大家自行参考bilibili视频这里主要对知识点和作业做一个结合说明。

作业描述

给定一个点P=(2,1),将该点绕原点先逆时针旋转45°,再平移(1,2),计算出变换后点的坐标(要求用齐次坐标进行计算)

算法与理论

  1. 齐次坐标的表示
    2D point = (x, y, 1)T
    2D vector = (x, y, 0)T
    所以,题目中的点P的齐次坐标形式表示为(2, 1, 1)T

  2. 2D变换矩阵的表示(Scale, Ratate, Transformation)
    可见第一行描述的是x方向,第二行描述的是y方向,第三行描述齐次坐标保持不变

    • Scale: 表示物体(向量、点)的放缩;
    • Rotation: 表示物体(向量、点)的旋转;
    • Translation: 表示物体(向量、点)的平移,可见向量平移前后不变,点平移后才变化。

在这里插入图片描述

作业源码

以下是实现作业0功能的源代码
main.cpp

#include<cmath>
#include<eigen3/Eigen/Core>
#include<eigen3/Eigen/Dense>
#include<iostream>

int main(){

	// Init point
	Eigen::Vector3f p(2.0f,1.0f,1.0f);

	// Rotate and transformation matrix
	Eigen::Matrix3f R, T;
	float ftheta = sqrt(2.0f) / 2;
	R << ftheta, -ftheta, 0,
		 ftheta, ftheta, 0,
		 0, 0, 1.0f;
	T << 1.0f, 0, 1.0f,
		 0, 1.0f, 2.0f,
		 0, 0, 1.0f;

	p = R * p;
	std::cout << "After rotate \n"
	std::cout << p << std::endl;


	p = T * p;
	std::cout << "After transformation \n"
	std::cout << p << std::endl;
	
	return 0;
}

结果展示

输出齐次坐标表示的结果

作业1:旋转与投影

作业描述

本次作业的任务是填写一个旋转矩阵和一个透视投影矩阵。给定三维下三个点v0(2.0,0.0,−2.0) v1(0.0,2.0,−2.0) v2(−2.0,0.0,−2.0), 你需要将这三个点的坐标变换为屏幕坐标,并在屏幕上绘制出对应的线框三角形(在代码框架中,我们已经提供了 draw_triangle 函数,所以你只需要去构建变换矩阵即可)。

简而言之,我们需要进行模型、视图、投影、视口等变换来将三角形显示在屏幕上。在提供的代码框架中,我们留下了模型变换和投影变换的部分给你去完成。

核心任务

  1. get_model_matrix(float rotation_angle): 实现返回三维绕z轴旋转的变换矩阵;
  2. get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar): 实现返回投影矩阵;

算法与理论

这里我们从作业要求出发,复习以下两个概念

3D Transformation
与2D类似,常见的矩阵变换包括:Scale(缩放)、Rotation(旋转)、Translation(平移),而Scale和Translation可以根据2D简单推演得到,此处重点复习Rotation。

  1. 绕坐标轴旋转
    在这里插入图片描述

  2. 绕任意轴旋转
    我们知道,任意的旋转都可以用坐标轴旋转的方法集成得到,因此我们可以推导下列公式:
    Rxyz(α, β, γ) = Rx(α) Ry(β) Rz(γ)

    对于任意的旋转角α,和任意的旋转轴n,可以使用Rodrigues’ Rotation Formula得到:
    在这里插入图片描述

MVP Transformation
MVP变换即Model(模型)、View(视图)、Projection(投影)变换。

  1. ModelView(模型视图)Transformation:把随机的相机摆放和朝向转换到相机在原点处、看向-z方向、向上方向为y。

    • 相机位置从e移动到原点——T_view矩阵
    • 朝向从g移动到-z,向上方向从t移动到y,所以g×t移动到x——R_view矩阵
    • M_view = R_view·T_view
      在这里插入图片描述
  2. Projection(投影)Transformation

    • Orthographic projection(正交投影) :从任意位置的[l,r]×[b,t]×[f,n]长方体映射为[-1,1]³的正方体,得到M_ortho
      在这里插入图片描述

    • Perspective projection(透视投影),得到M_persp

    • M_persp=M_ortho·M_persp->ortho
      在这里插入图片描述

    • 当已知条件为aspect ratio(宽高比)和fovY(Y方向视角)时,我们可以将aspect和fovY转换到r、t上。 在这里插入图片描述

作业源码

  1. get_model_matrix(float rotation_angle)
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.

    float rotation_angle_radian = rotation_angle * MY_PI / 180;
    
    Eigen::Matrix4f rotation;
    rotation << cos(rotation_angle_radian), -sin(rotation_angle_radian), 0, 0,
                sin(rotation_angle_radian), cos(rotation_angle_radian), 0, 0,
                0, 0, 1, 0,
                0, 0, 0, 1;

    model = rotation * model;

    return model;
}
  1. get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar): 实现返回投影矩阵;
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.
    float eye_fov_radian = eye_fov * MY_PI / 180;

    float t = tan(eye_fov_radian / 2) * abs(zNear);
    float r = t * aspect_ratio;
    float b = -t;
    float l = -r;

    Eigen::Matrix4f translation;
    translation << 1, 0, 0, -(r+l)/2.0f,
                   0, 1, 0,-(t+b)/2.0f,
                   0, 0, 1, -(zNear+zFar)/2.0f,
                   0, 0, 0, 1;

    Eigen::Matrix4f scale;
    scale << 2.0f/(r-l), 0, 0, 0,
             0, 2.0f/(t-b), 0, 0,
             0, 0, 2.0f/(zNear-zFar), 0,
             0, 0, 0, 1;

    // Orthographic projection
    projection = scale * translation;

    Eigen::Matrix4f M_persp_ortho;
    M_persp_ortho << zNear, 0, 0, 0,
                     0, zNear, 0, 0,
                     0, 0, zNear+zFar, -zFar*zNear,
                     0, 0, 1, 0;

    // Perspective projection
    projection = projection * M_persp_ortho;

    return projection;
}
  1. get_rotation(Vector3f axis, float angle):绕着过原点的axis轴旋转angle角度
Eigen::Matrix4f get_rotation(Vector3f axis, float angle)
{
    // rotation around axis and angle
    float rotation_angle_radian = angle * MY_PI / 180;

    Eigen::Matrix3f I = Eigen::Matrix3f::Identity();
    Eigen::Matrix3f N; // axis product matrix
    N << 0, -axis(2), axis(1),
         axis(2), 0, -axis(0),
         -axis(1), axis(0), 0;
    
    Eigen::Matrix3f r3 = cos(rotation_angle_radian) * I
        + (1 - cos(rotation_angle_radian)) * (axis * axis.transpose())
        + sin(rotation_angle_radian) * N;

    Eigen::Matrix4f rotation = Eigen::Matrix4f::Identity();
    rotation.block(0,0,3,3) << r3;
    
    return rotation;
}

结果展示

编译后执行
./Rasterizer -r 20输出旋转20°到output.png
./Rasterizer -r 20 image.png输出旋转20°到image.png

在这里插入图片描述

作业2:Triangles and Z-buffering

作业描述

本次作业主要目标是在屏幕上画出一个实心三角形,换言之,栅格化一个三角形。需要自己填写并调用函数rasterize_triangle(const Triangle& t),该函数的内部工作流程如下:

核心任务

  1. rasterize_triangle(): 执行三角形栅格化算法
    • 创建三角形的2维bounding box。
    • 遍历此 bounding box 内的所有像素(使用其整数索引)然后,使用像素中心的屏幕空间坐标来检查中心点是否在三角形内。
    • 如果在内部,则将其位置处的插值深度值(interpolated depth value) 与深度缓冲区(depth buffer) 中的相应值进行比较。
    • 如果当前点更靠近相机,请设置像素颜色并更新深度缓冲区(depthbuffer)。
  2. static bool insideTriangle(): 测试点是否在三角形内。

算法与理论

这里我们从作业要求出发,复习以下概念
判断点与三角形位置关系——Cross Product

Bounding box

深度测试(Z-Buffer/Depth-Buffer)
由于场景中的物体有远有近,Z-Buffer用于表示可见性以及遮挡的场景,先光栅化远的,后近的以覆盖近的物体。

  1. 画家算法(Painter’s Algorithm):先画场景中远的物体,后画近的以覆盖近的物体;即对物体进行深度排序,但对于相互覆盖的物体不适用。
  2. Z-Buffer:对每个像素最浅的z进行排序,借助于深度图(Z/Depth-Buffer).注意,我们同时存两个数据:Frame buffer(颜色数据),Z/Depth-Buffer(深度数据)
    • 对于每一个obj及其每一个像素(Sampling)
    • 判定z是否小于Z-Buffer[point]:是–更新Z-Buffer和颜色,否–Do nothing

*假定z是正数

反走样(Antialiasing)
先把三角形变模糊后采样结果,即对三角形的像素值在一个区域内取平均(卷积)。在实际中,我们采取Antialiasing By Supersampling(MSAA)方法来近似。

  1. Supersampling:将一个像素划分成若干个小像素(N×N),每一个小像素有一个中心,逐个判断是否在三角形内,然后将结果求平均。
  2. Sample:直接取每个像素的中心。

作业源码

结果展示

走样结果:可以看出明显的走样(锯齿)
在这里插入图片描述
MASS(反走样)后结果:可以看出没有锯齿,有清晰的边界
在这里插入图片描述

参考资料
MSAA反走样

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值