Games101--作业2
说明
该作业主要想实现两个三角形的绘制
绘制结果走样
按照课上所讲的方法,对包围盒里面的所有像素进行判断是否在三角形内,然后着色,这样的结果由于采样频率的问题将导致边缘走样现象的发生
if(!insideTriangle(P.x(),P.y(),t.v)) continue;
int cur_index = get_index(P.x(),P.y());
//重心坐标
auto[alpha, beta, gamma] = computeBarycentric2D(P.x(), P.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 -- zbuffer
z_interpolated *= w_reciprocal;
if(z_interpolated < depth_buf[cur_index])
{
depth_buf[cur_index] = z_interpolated;
P.z() = z_interpolated;
set_pixel(P,t.getColor());
}
使用MSAA处理结果 -- 有黑边的情况
采用4xMSAA来进行卷积模糊,即将一个像素块分成4个采样区域。然后分别计算这个4个采样区域能否被三角形覆盖,最后最终的像素颜色就是这4块区域的平均值。
float basec = 4.0f;
float dir[4][2] = {0.25,0.25,0.25,0.75,0.75,0.25,0.75,0.75};
for(P.x()=minx;P.x()<=maxx;P.x()++)
{
for(P.y() = miny;P.y() <= maxy;P.y()++)
{
float count = 0.0;
for(float x = 0.25;x<1.0;x+=0.5)
{
for(float y = 0.25;y<1.0;y+=0.5)
{
//统计有多少个采样点在三角形内
if(insideTriangle(P.x()+x,P.y()+y,t.v))
{
count += 1.0;
}
}
}
if(insideTriangle(P.x()+0.5,P.y()+0.5,t.v))
{
auto[alpha, beta, gamma] = computeBarycentric2D(P.x()+0.5, P.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(z_interpolated < depth_buf[get_index(P.x(),P.y())])
{
depth_buf[get_index(P.x(),P.y())] = z_interpolated;
P.z() = z_interpolated;
// TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
set_pixel(P,t.getColor());
//最终颜色为平均值
Eigen::Vector3f color = t.getColor() * (count/basec);
//black edge -- the edge color is averge by green and blue but last code not do this
set_pixel(P,color);
}
}
}
黑边出现的原因
对于边缘重叠部分,由于绿色三角形的z值小,所以体现出绘制颜色为绿色,而当考虑4个采样点的情况,当只有一个采样点在绿色三角形内,其余三个在蓝色三角形内。实际最终颜色应该为1/4 green + 3/4 blue。
而上述代码只考虑覆盖,所以导致最终颜色为1/4 green 出现黑边
MSAA -- 解决黑边
在作业中说到需要为每个像素点存储颜色和深度。
最终一个像素的颜色应当是存储的这四个颜色的平均值。
//the start loc of this 2*2 area
int loc_start = get_index(P.x(),P.y())*4;
//this pixel real dep
float mindep = FLT_MAX;
//4xMSAA
float count = 0.0;
for(int k = 0;k<4;k++)
{
float curx = P.x()+dir[k][0];
float cury = P.y()+dir[k][1];
if(insideTriangle(curx,cury,t.v))
{
//calculate every sample color and dep save in sample_dep and sample_color
auto[alpha, beta, gamma] = computeBarycentric2D(curx, cury, 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;
//one sample
if(z_interpolated < sample_dep[loc_start+k])
{
sample_dep[loc_start+k] = z_interpolated;
sample_color[loc_start+k] = t.getColor()/4;
}
//this pixel dep == min(4 sample dep)
mindep = std::min(mindep,sample_dep[loc_start+k]);
}
}
//set color for this pixel
Eigen::Vector3f color = sample_color[loc_start]+sample_color[loc_start+1]+sample_color[loc_start+2]+sample_color[loc_start+3];
//get dep of this pixel
depth_buf[get_index(P.x(),P.y())] = std::min(mindep,depth_buf[get_index(P.x(),P.y())]);
P.z() = depth_buf[get_index(P.x(),P.y())];
set_pixel(P,color);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了