需要填写三个地方的代码:
main.cpp 里面的 get_projection_matrix函数:
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
// TODO: Copy-paste your implementation from the previous assignment.
Eigen::Matrix4f projection;
float n = zNear;
float f = zFar;
float t = tan(eye_fov/2) * abs(n);
float b = -t;
float r = aspect_ratio * t;
float l = -r;
Eigen::Matrix4f M_ortho_1,M_ortho_2,M_ortho;
M_ortho_2 << 2/(r-l), 0.0, 0.0, 0.0,
0.0, 2/(t-b), 0.0, 0.0,
0.0, 0.0, 2/(n-f), 0.0,
0.0, 0.0, 0.0, 1.0;
M_ortho_1 << 1.0, 0.0, 0.0, -(r+l)/2,
0.0, 1.0, 0.0, -(t+b)/2,
0.0, 0.0, 1.0, -(n+f)/2,
0.0, 0.0, 0.0, 1.0;
M_ortho = M_ortho_2 * M_ortho_1;
Eigen::Matrix4f M_persp_ortho;
M_persp_ortho << n, 0.0, 0.0, 0.0,
0.0, n, 0.0, 0.0,
0.0, 0.0, n+f, -n*f,
0.0, 0.0, 1.0, 0.0;
M_ortho = M_ortho_2 * M_ortho_1;
projection = M_ortho * M_persp_ortho * projection;
return projection;
}
rasterizer.cpp里面的 insideTriangle 函数:
static bool mySymbol(float x){
return x > 0;
}
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]
// t1 = PA^PB,
// t2 = PB^PC,
// t3 = PC^PA,
// t1=t2=t3同号,则在三角形内部
auto A = _v[0];
auto B = _v[1];
auto C = _v[2];
auto P = Vector2f(x,y);
auto PA = Vector2f(A[0]-P[0],A[1]-P[1]);
auto PB = Vector2f(B[0]-P[0],B[1]-P[1]);
auto PC = Vector2f(C[0]-P[0],C[1]-P[1]);
auto PA_PB = PA[0]*PB[1]-PA[1]*PB[0];
auto PB_PC = PB[0]*PC[1]-PB[1]*PC[0];
auto PC_PA = PC[0]*PA[1]-PC[1]*PA[0];
return mySymbol(PA_PB) == mySymbol(PB_PC) == mySymbol(PC_PA);
}
rasterizer.cpp里面的 rasterize_triangle 函数:
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// cout << t.v <<endl;
// cout << insideTriangle(0,1,t.v) <<endl;
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
// 找bounding box
int left=INT32_MAX,right=INT32_MIN,top=INT32_MIN,buttom=INT32_MAX;
for (int i = 0; i < 3; i++)
{
float x = t.v[i][0];
float y = t.v[i][1];
left = left > floor(x) ? floor(x):left;
right = right < ceil(x) ? ceil(x):right;
buttom = buttom > floor(y) ? floor(y):buttom;
top = top < ceil(y) ? ceil(y):top;
}
for (int x = left; x <= right; x++)
{
for (int y = buttom; y <= top; y++)
{
bool isInside = insideTriangle(x+0.5,y+0.5,t.v);
if(isInside){
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;
bool shouldBePainted = depth_buf[get_index(x,y) ] > z_interpolated;
if(shouldBePainted){
Vector3f point(x+0.5,y+0.5,z_interpolated);
depth_buf[get_index(x,y) ] = z_interpolated;
set_pixel(point,t.getColor());
}
}
}
}
// 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.
}
结果:
由于使用的远程软件有点问题,看起来上下颠倒了。