框架修改
//把rasterizer.cpp第83行的vert.z() = vert.z() * f1 + f2改为vert.z() = -vert.z() * f1 + f2
重心坐标推导
rasterize_triangle
void rst::rasterizer::rasterize_triangle(const Triangle& t)
{
/*
// TODO : Find out the bounding box of current triangle.
// iterate through the pixel and find if the current pixel is inside the triangle
// 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.
//TODO:找出当前三角形的边界框。
//遍历像素并找出当前像素是否在三角形内
//如果是这样,请使用以下代码获得插值的z值。
//自动[α,β,γ]=计算中心2d(x,y,t.v);
//浮点数w_倒数=1.0/(α/v[0].w()+β/v[1].w()+γ/v[2].w());
//浮点z_插值=alpha*v[0].z()/v[0].w()+beta*v[1].z()/v[1].w()+gamma*v[2].z()/v[2].w();
//z_插值*=w_倒数;
//TODO:如果要绘制三角形,请将当前像素(使用set\ pixel函数)设置为三角形的颜色(使用getColor函数)。
*/
auto v = t.toVector4();
//创建三角形的2维bounding box。
//找出最小和最大的的x和y
float min_x = std::min(v[0][0], std::min(v[1][0], v[2][0]));
float min_y = std::min(v[0][1], std::min(v[1][1], v[2][1]));
float max_x = std::max(v[0][0], std::max(v[1][0], v[2][0]));
float max_y = std::max(v[0][1], std::max(v[1][1], v[2][1]));
bool MSAA = true;
if (MSAA)
{
//4*4
std::vector pos =
{
{0.25,0.25},
{0.25,0.75},
{0.75,0.25},
{0.75,0.75}
};
for (int x = min_x; x < max_x; x++)
{
for (int y = min_y; y < max_y; y++)
{
int count = 0;
//最小深度,默认是无穷远
float mindpth = FLT_MAX;
for (int i = 0; i < 4; i++)
{
//判断像素点中心是不是在三角形内部
if (insideTriangle((float)x + pos[i][0], (float)y + pos[i][1], t.v))
{
auto tup = computeBarycentric2D((float)x + pos[i][0], (float)y + pos[i][1], t.v);
float alpha;
float beta;
float gamma;
std::tie(alpha, beta, gamma) = tup;
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;
mindpth = std::min(mindpth, z_interpolated);
count++;
}
}
if (count != 0)
{
if (depth_buf[get_index(x, y)] > mindpth)
{
Vector3f color = t.getColor() * count / 4.0;
Vector3f point(3);
point << (float)x, (float)y, mindpth;
// 替换深度
depth_buf[get_index(x, y)] = mindpth;
// 修改颜色
set_pixel(point, color);
}
}
}
}
}
else
{
//遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中 心的屏幕空间坐标来检查中心点是否在三角形内
for (int x = min_x; x < max_x; x++)
{
for (int y = min_y; y < max_y; y++)
{
//判断像素点中心是不是在三角形内部
if (insideTriangle(x + 0.5, y + 0.5, t.v))
{
//最小深度,默认是无穷远
float mindpth = FLT_MAX;
//如果在三角形内部,算插值,然后更新Z插值
//计算插值 alpha, beta, gamma
auto tup = computeBarycentric2D(x + 0.5, y + 0.5, t.v);
float alpha;
float beta;
float gamma;
std::tie(alpha, beta, gamma) = tup;
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;
mindpth = std::min(mindpth, z_interpolated);
//如果x,y所在点的深度小于z-buffer的深度,
if (depth_buf[get_index(x, y)] > mindpth)
{
//获得颜色
Vector3f color = t.getColor();
Vector3f point;
point << x, y, mindpth;
//更新深度
depth_buf[get_index(x, y)] = mindpth;
//更新所在点的颜色
set_pixel(point, color);
}
}
}
}
}
}
insideTriangle(判断一个点是否在三角形内部)
//测试点是否在三角形内。你可以修改此函 数的定义,这意味着,你可以按照自己的方式更新返回类型或函数参数
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]
TODO:实现此函数以检查点(x,y)是否位于由_v[0]、_v[1]、_v[2]表示的三角形内
Eigen::Vector3f p;
p << x, y,1;
Vector3f v[3];
for (int i = 0; i < 3; i++)
v[i] = {_v[i].x(),_v[i].y(), 1.0};
//向量
Eigen::Vector3f ab;
Eigen::Vector3f bc;
Eigen::Vector3f ca;
ab = v[1] - v[0];
bc = v[2] - v[1];
ca = v[0]- v[2];
Eigen::Vector3f ap;
Eigen::Vector3f bp;
Eigen::Vector3f cp;
ap=p- v[0];
bp=p - v[1];
cp = p - v[2];
if((ab.cross(bc)).dot(ab.cross(ap)) > 0 &&
(bc.cross(ca)).dot(bc.cross(bp)) > 0 &&
(ca.cross(ab)).dot(ca.cross(cp))>0)
{
return true;
}
else
{
return false;
}
}