GAMES101:作业3
附其他所有作业超链接如下:
Games101 作业0:作业0
Games101 作业1:作业1
Games101 作业2:作业2
Games101 作业3:作业3
Games101 作业4:作业4
Games101 作业5:作业5
Games101 作业6:作业6
Games101 作业7:作业7
完整代码获取途径:
https://github.com/liupeining/Games_101_homework
照旧把这段代码粘贴过来:
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
float n = zNear;
float f = zFar;
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();
float t = -tan((eye_fov/360)*MY_PI)*(abs(n)); //top
float r = t/aspect_ratio;
Eigen::Matrix4f Mp;//透视矩阵
Mp <<
n, 0, 0, 0,
0, n, 0, 0,
0, 0, n+f, -n*f,
0, 0, 1, 0;
Eigen::Matrix4f Mo_tran;//平移矩阵
Mo_tran <<
1, 0, 0, 0,
0, 1, 0, 0, //b=-t;
0, 0, 1, -(n+f)/2 ,
0, 0, 0, 1;
Eigen::Matrix4f Mo_scale;//缩放矩阵
Mo_scale <<
1/r, 0, 0, 0,
0, 1/t, 0, 0,
0, 0, 2/(n-f), 0,
0, 0, 0, 1;
projection = (Mo_scale*Mo_tran)* Mp;//投影矩阵
//这里一定要注意顺序,先透视再正交;正交里面先平移再缩放;否则做出来会是一条直线!
return projection;
}
修改函数 rasterize_triangle(const Triangle& t) in rasterizer.cpp: 在此 处实现与作业 2 类似的插值算法,实现法向量、颜色、纹理颜色的插值。
下面三角形的rasterizer和上次的思路完全一致,这里仍然沿用了MSAA;
大部分都和上次的代码相同,更改以及需要注意的地方均在代码中做了注释。
其实区别就在于添加了用重心坐标各种插值最终返回一个color
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos)
{
auto v = t.toVector4(); //v[0],v[1],v[2]分别为三角形的三个顶点,是四维向量
//比较三个顶点的横纵坐标,确定包围盒的边界并取整
double min_x = std::min(v[0][0], std::min(v[1][0], v[2][0]));
double max_x = std::max(v[0][0], std::max(v[1][0], v[2][0]));
double min_y = std::min(v[0][1], std::min(v[1][1], v[2][1]));
double max_y = std::max(v[0][1], std::max(v[1][1], v[2][1]));
min_x = static_cast<int>(std::floor(min_x));
min_y = static_cast<int>(std::floor(min_y));
max_x = static_cast<int>(std::ceil(max_x));
max_y = static_cast<int>(std::ceil(max_y));
//此处实现的是MSAA
std::vector<Eigen::Vector2f> pos
{
//对一个像素分割四份 当然你还可以分成4x4 8x8等等甚至你还可以为了某种特殊情况设计成不规则的图形来分割单元
{
0.25,0.25}, //左下
{
0.75,0.25}, //右下
{
0.25,0.75}, //左上
{
0.75,0.75} //右上
};
for (int i = min_x; i <= max_x; ++i)
{
for (int j = min_y; j <= max_y; ++j)
{
int count = 0; //开始遍历四个小格子,获得平均值
for (int MSAA_4 = 0; MSAA_4 < 4; ++MSAA_4)
{
if (insideTriangle(static_cast<float>(i+pos[MSAA_4][0]), static_cast<float>(j+pos[MSAA_4][1]),t.v))
++count;
}
if(count) //至少有一个小格子在三角形内
{
//此处是框架中代码,获得z,见原程序注释:
// * v[i].w() is the vertex view space depth value z.
// * Z is interpolated view space depth for the current pixel
// * zp is depth between zNear and zFar, used for z-buffer
auto[alpha, beta, gamma] = computeBarycentric2D(i