GAMES101 Assignment3 (对应Lecture7-9)

课程作业框架来自GAMES

基础部分:

目标要求:实现与作业2 类似的插值算法,实现法向量、颜色、纹理颜色的插值。

Rasterizer.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
* 在三角形内检测函数
* parameters:
* point:x,y
* triangle:_v
*/
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]
// float xp = x, yp = y;
// float xa = _v[0].x(), ya = _v[0].y();
// float xb = _v[1].x(), yb = _v[1].y();
// float xc = _v[2].x(), yc = _v[2].y();

// float gamma = ((xb-xa)*(yp-ya)-(xp-xa)*(yb-ya))/((xb-xa)*(yc-ya)-(xc-xa)*(yb-ya));

// float beta = (xp-xa-gamma*(xc-xa))/(xb-xa);

// float alpha = 1.0f - gamma - beta;

// return alpha>0 && alpha<1;

Vector3f P(x,y,0);
return ((_v[0]-_v[1]).cross(P-_v[1]).z()<0&&
(_v[2]-_v[0]).cross(P-_v[0]).z()<0&&
(_v[1]-_v[2]).cross(P-_v[2]).z()<0);
}

//Screen space rasterization
//此版本为使用MSAA版本,如不使用直接使用insideTriangle函数同时判断z-buffer即可
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
int left_bound = std::min(v[0].x(), std::min(v[1].x(), v[2].x()));
int right_bound = std::max(v[0].x(), std::max(v[1].x(), v[2].x()));
int bottom_bound = std::min(v[0].y(), std::min(v[1].y(), v[2].y()));
int up_bound = std::max(v[0].y(), std::max(v[1].y(), v[2].y()));

// If so, use the following code to get the interpolated z value.
//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;

// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.

Eigen::Vector3f p;
for(int x = left_bound;x<=right_bound;x++){
for (int y = bottom_bound; y <= up_bound; y++)
{
// 使用MSAA
float percent = insideTrianglePercent(x,y,t.v,4);
if (percent>0)
{
//Depth interpolated
auto[alpha, beta, gamma] = computeBarycentric2D(i+0.5, j+0.5, t.v);

float Z = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
float zp = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
zp*=Z;

if(zp < depth_buf[get_index(i,j)])
{
depth_buf[get_index(i,j)] = zp;
auto interpolated_color = interpolate(alpha, beta, gamma, t.color[0], t.color[1], t.color[2], 1);
auto interpolated_normal = interpolate(alpha, beta, gamma,t.normal[0],t.normal[1],t.normal[2],1).normalized();
auto interpolated_texcoords = interpolate(alpha, beta, gamma,t.tex_coords[0],t.tex_coords[1],t.tex_coords[2],1);
auto interpolated_shadingcoords = interpolate(alpha, beta, gamma,view_pos[0],view_pos[1],view_pos[2],1);
fragment_shader_payload payload(interpolated_color,interpolated_normal,interpolated_texcoords,texture ? &*texture : nullptr);
payload.view_pos = interpolated_shadingcoords;
auto pixel_color = fragment_shader(payload);
set_pixel(Eigen::Vector2i(i,j),pixel_color);
}
}
}
}
}