GAMES101 Assignment2 (对应Lecture5-6)

课程作业框架来自GAMES

基础部分:

目标要求:正确实现三角形得栅格化算法,测试点是否在三角形内,正确实现z-buffer算法

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
/*
* 在三角形内检测函数
* 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)
{
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;

p.x() = x;
p.y() = y;
if(z_interpolated < depth_buf[get_index(x,y)]){
set_pixel(p,t.getColor(),percent);
depth_buf[get_index(x,y)] = z_interpolated;
}
}
}
}
}

提高部分:

目标要求:实现super-sampling处理反走样

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
/* 
* 指定每个像素使用多少个采样点
* parameters:
* place: x,y
* vector: _v
* density: num of sampling
**/
static float insideTrianglePercent(int x, int y, const Vector3f* _v, int density){
float percent = 0;
float step = sqrt(density);

// 计算每个采样点的位置参数
float fragment_spacing = 1.0/step;
float margin = fragment_spacing/2;
float weight = 1.0/density;

for(int i=0;i<step; i++){
for (int j = 0; j < step; j++)
{
percent += insideTriangle(x+margin+fragment_spacing*i,
y+margin+fragment_spacing*j,_v)*weight;
}

}
return percent;
}