Loading

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());
}

no MSAA

使用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);
			}
		}
}

MSAA WITH BLACK

黑边出现的原因

对于边缘重叠部分,由于绿色三角形的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);

image

posted @   XTG111  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示