Games101 作业2 shading
按照工作流程来写
首先创建三角形的bounding box,就是找一个正好放下三角形的矩形,方便之后进行遍历
之后,遍历这个box内的所有像素,找出在三角形内的像素;
首先,需要判断一个点是否在三角形内,可以通过叉乘的方法进行计算
遍历box内每一个像素,如果在三角形内,计算插值深度值,然后再判断像素的深度值,对于更靠前的像素,就更新像素的颜色与深度缓冲区
完整的代码:
static bool insideTriangle(float x, float 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]
Vector2f p(x,y);
// x.head(2) 取前n个值
Vector2f AB = _v[1].head(2) - _v[0].head(2);
Vector2f BC = _v[2].head(2) - _v[1].head(2);
Vector2f CA = _v[0].head(2) - _v[2].head(2);
Vector2f AP = p - _v[0].head(2);
Vector2f BP = p - _v[1].head(2);
Vector2f CP = p - _v[2].head(2);
//叉乘计算点在不在三角形内
return AB[0]*AP[1] - AB[1]*AP[0]>0 &&
BC[0]*BP[1] - BC[1]*BP[0]>0 &&
CA[0]*CP[1] - CA[1]*CP[0]>0 ;
}
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
float x_min,y_min,x_max,y_max;
// TODO : Find out the bounding box of current triangle.
//bounding box 找出一个正好放下三角形的矩形
x_min = min( v[0][0] , min( v[1][0] , v[2][0] ) );
x_max = max( v[0][0] , max( v[1][0] , v[2][0] ) );
y_min = min( v[0][1] , min( v[1][1] , v[2][1] ) );
y_max = max( v[0][1] , max( v[1][1] , v[2][1] ) );
//floor 向下取整 ceil 向上取整
x_min = (int)floor(x_min);
y_min = (int)floor(y_min);
x_max = (int)ceil(x_max);
y_max = (int)ceil(y_max);
// iterate through the pixel and find if the current pixel is inside the triangle
//遍历矩形内的每一个像素,判断这个像素在不在三角形内
for(int x=x_min;x<=x_max;x++)
for(int y=y_min;y<=y_max;y++){
//如果在三角形内,计算它的插值深度值,比较插值深度值与深度缓冲区的大小
if(insideTriangle(x+0.5f,y+0.5f,t.v)){
float alpha,beta,gamma;
auto ans = computeBarycentric2D(x+0.5f,y+0.5f,t.v);
tie(alpha,beta,gamma)=ans;
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;
//对于更靠前的像素,设置像素的颜色,并且更新深度缓冲区
if(depth_buf[get_index(x,y)]>z_interpolated){
Vector3f color = t.getColor();
Vector3f point(3);
point<<x , y , z_interpolated;
depth_buf[get_index(x,y)] = z_interpolated;
set_pixel(point,color);
}
}
}
// 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.
}
最终的结果