CC BY 4.0 (除特别声明或转载文章外)
如果这篇博客帮助到你,可以请我喝一杯咖啡~
作业2简单介绍
作业2 Triangles and Z-buffering
在作业1的基础上,首先还是自己填补MVP算法的代码;实现两个函数,一个是判断点是否在三角形内,一个是光栅化三角形;
提高作业使用MSAA反走样操作,简而言之就是在一个像素点的软件层面上把一个像素点分为4个像素点,然后最后求一个平均 首先是求出三角形的边界,然后循环遍历其中的点,然后求z值,框架代码中已经给出。
判断点是是否在三角形内(利用叉积):
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]
Vector3f p;
p << x,y,0;
Vector3f A,B,C;
A = _v[0];
B = _v[1];
C = _v[2];
Vector3f ans1,ans2,ans3;
ans1 = (B-A).cross(p-A);
ans2 = (C-B).cross(p-B);
ans3 = (A-C).cross(p-C);
if(ans1.z()>0&&ans2.z()>0&&ans3.z()>0){
return true;
}
else return false;
}
光栅化三角形:
//Screen space rasterization
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
// 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;
auto v = t.toVector4();
float x_min = std::min(v[0].x(),std::min(v[1].x(),v[2].x()));
float x_max = std::max(v[0].x(),std::max(v[1].x(),v[2].x()));
float y_min = std::min(v[0].y(),std::min(v[1].y(),v[2].y()));
float y_max = std::max(v[0].y(),std::max(v[1].y(),v[2].y()));
x_min = int(x_min+0.5);
x_max = int(x_max+0.5);
y_min = int(y_min+0.5);
y_max = int(y_max+0.5);
float dx[4] = {0.25,0.25,0.75,0.75};
float dy[4] = {0.25,0.75,0.25,0.75};
// 一个像素划分为4个像素,use MSAA
for(int x = x_min;x <= x_max;++x) {
for(int y = y_min;y <= y_max;++y) {
int cnt = 0;
float min_z = FLT_MAX;
for(int i = 0;i<4;++i){
float xx = x+dx[i] ,yy = y+dy[i];
if(insideTriangle(xx,yy,t.v)) {
auto[alpha, beta, gamma] = computeBarycentric2D(xx, yy, 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;
min_z = std::min(min_z,z_interpolated);
cnt ++;
}
}
if(cnt) {
if(min_z<depth_buf[get_index(x,y)]) {
depth_buf[get_index(x,y)] = min_z;
auto color = t.getColor();
auto point = Eigen::Vector3f(x,y,cnt); //在set_pixel中有求平均操作
set_pixel(point,color);
}
}
}
}
// for(int x = x_min;x <= x_max;++x) {
// for(int y = y_min;y <= y_max;++y) {
// float xx = x+0.5 ,yy = y+0.5;
// if(insideTriangle(xx,yy,t.v)) {
// auto[alpha, beta, gamma] = computeBarycentric2D(xx, yy, 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;
// if(z_interpolated<depth_buf[get_index(x,y)]) {
// depth_buf[get_index(x,y)] = z_interpolated;
// auto color = t.getColor();
// auto point = Eigen::Vector3f(x,y,0);
// set_pixel(point,color);
// }
// }
// }
// }
}