games101 homework2 详解过程
games101 homework2 详解过程
未使用MSAA来抗锯齿:
1.根据三角形顶点position首先获得三角形像素边界
2.遍历所有像素点,进行判断是否在三角形内部
3.计算重心computeBarycentric2D(),返回重心坐标alpha,beta,gamma,三者之和为1;(这个先要听完渲染和材质那几节)
4.根据重心坐标计算z-buffer值
5.比较当前像素的重心坐标和已存储的z-buffer,替换成z值更大的(depth更小的),如果改变了zbuffer值还需要着色一遍。
使用MSAA:
1.将一个像素虚拟成四个小的bounding box
2.计算4个bounding box 中心的重心坐标,并计算zbuffer 的depth值。
3.以4个bounding box中最小的depth 值进行更新。
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
// bounding box
float min_x = std::min(v[0][0], std::min(v[1][0], v[2][0]));
float max_x = std::max(v[0][0], std::max(v[1][0], v[2][0]));
float min_y = std::min(v[0][1], std::min(v[1][1], v[2][1]));
float max_y = std::max(v[0][1], std::max(v[1][1], v[2][1]));
min_x = (int)std::floor(min_x);
max_x = (int)std::ceil(max_x);
min_y = (int)std::floor(min_y);
max_y = (int)std::ceil(max_y);
bool MSAA = false;
//MSAA 4X
if (MSAA) {
std::vector<Eigen::Vector2f> pos
{
{0.25,0.25},
{0.75,0.25},
{0.25,0.75},
{0.75,0.75},
};
for (int x = min_x; x <= max_x; x++) {
for (int y = min_y; y <= max_y; y++) {
float minDepth = FLT_MAX;
int count = 0;
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;
minDepth = std::min(minDepth, z_interpolated);
count++;
}
}
if (count != 0) {
if (depth_buf[get_index(x, y)] > minDepth) {
Vector3f color = t.getColor() * count / 4.0;
Vector3f point(3);
point << (float)x, (float)y, minDepth;
depth_buf[get_index(x, y)] = minDepth;
set_pixel(point, color);
}
}
}
}
}
else {
for (int x = min_x; x <= max_x; x++) {
for (int y = min_y; y <= max_y; y++) {
if (insideTriangle((float)x + 0.5, (float)y + 0.5, t.v)) {
auto tup = computeBarycentric2D((float)x + 0.5, (float)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;
if (depth_buf[get_index(x, y)] > z_interpolated) {
Vector3f color = t.getColor();
Vector3f point(3);
point << (float)x, (float)y, z_interpolated;
depth_buf[get_index(x, y)] = z_interpolated;
set_pixel(point, color);
}
}
}
}
}
}