主要代码思路来自大佬:https://blog.csdn.net/qq_36242312/article/details/105758619
然后有个插值计算,好像下节课才讲。
转发的文章的代码不能直接改true来实现MSAA,因为insideTriangle的参数他写的是int,改成float就可以了。
color那里写成t.getColor() * count / 4.0f + (4 - count) * frame_buf[get_index(x,y)] / 4.0f貌似还可以减黑边
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]
Eigen::Vector2f p;
p<<x,y;
Eigen::Vector2f AB=_v[1].head(2)-_v[0].head(2);
Eigen::Vector2f BC=_v[2].head(2)-_v[1].head(2);
Eigen::Vector2f CA=_v[0].head(2)-_v[2].head(2);
Eigen::Vector2f AP=p-_v[0].head(2);
Eigen::Vector2f BP=p-_v[1].head(2);
Eigen::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;
}
void rst::rasterizer::rasterize_triangle(const Triangle& t) {
auto v = t.toVector4();
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=true;
if(MSAA)
{
float pos[4][2]=
{
{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[alpha, beta, gamma] = computeBarycentric2D((float)x+pos[i][0],(float)y+pos[i][1],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;
minDepth=std::min(minDepth,z_interpolated);
count++;
}
}
if(count!=0)
{
if(depth_buf[get_index(x,y)]>minDepth)
{
Vector3f color=t.getColor()*(float)count/4.0;
Vector3f point;
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[alpha, beta, gamma] = computeBarycentric2D((float)x+0.5,(float)y+0.5,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(depth_buf[get_index(x,y)]>z_interpolated)
{
Vector3f color=t.getColor();
Vector3f point;
point<<(float)x,(float)y,z_interpolated;
depth_buf[get_index(x,y)]=z_interpolated;
set_pixel(point,color);
}
}
}
}
}
// 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.
}
left is using MSAA while right is not