目录
三角形颠倒和前后问题
MSAA抗锯齿
处理黑边问题
· 颠倒
三角形颠倒是因为在透视投影中,按严令琪老师课上内容,摄像机默认看向Z轴负方向,主函数中传的参数50和0.1代表了摄像机与远近平面的距离,而不代表坐标值,用50和0.1直接进行运算则会出现如下图所示中心对称现象,即颠倒问题,所以需要进行取负操作再运算
图片来源:
闫令琪:Games101 现代计算机图形学-作业Assignment02解析 - 灰信网(软件开发博客聚合) (freesion.com)https://www.freesion.com/article/4973968295/· 前后
完成光栅化函数并运行后,发现与给的示例图中三角形的前后正好相反,这是因为光栅化函数中,是利用正值进行深度判断,越小的代表离Z轴越近,而我们的三角形位于Z轴负方向,正好相反,有两种办法可以解决:
void rst::rasterizer::draw(...)
{
......
for (auto& i : ind)
{
//Viewport transformation
for (auto& vert : v)
{
vert.x() = 0.5*width*(vert.x()+1.0);
vert.y() = 0.5*height*(vert.y()+1.0);
//here revise
vert.z() = -vert.z() * f1 + f2;
}
......
}
通过编写代码,在网上学习其他大佬的教程,对MSAA有了更深入的了解,以为在课堂上已经理解的东西,其实还是没有理解完全,这里踩了一个坑,在bool insideTriangle(int x, int y, const Vector3f* _v)函数中参数为int型,出现了运行后没有抗锯齿效果的问题,将x,y参数改为float型,这个问题就被解决了,我是这样理解的:因为将像素分为2*2,每次加0.25/0.75传入后,float型转为int型,导致四个点其实仍然为x,y的取整值。
处理黑边主要参考了网上教程,来源如下:
(1条消息) 【GAMES101】作业2(提高)(附带解决黑边问题)_ycrsw的博客-CSDN博客_games101作业2https://blog.csdn.net/ycrsw/article/details/123910834我遇到的主要问题是为什么最后不再进行深度判断“if(depth_buf[get_index(x,y)] > mindep)”再进行Set_Pixel(point,color)等操作
这是因为我们先处理的是黄色的三角形,它离Z轴近,如果一个点1/4为黄,3/4为黑色,则我们所定义的super_frame_buf[ ]就记录了这个信息,且更新depth_buf[get_index(x,y)为此黄色三角形的值,当再处理蓝色的三角形时,虽然更新了super_frame_buf[ ]的值为1/4为黄,3/4为蓝,但因为蓝色三角形比黄色三角形远,不符合判断条件,无法更新color的值,所以我们最后不在加深度判断条件,深度判断转移到了四次小循环之中去存储颜色。代码如下,完整代码参考上述教程链接:
void rst::rasterizer::rasterize_triangle(const Triangle& t)
{
auto v = t.toVector4();
std::vector a{0.25,0.25,0.75,0.75,0.25};
// TODO : Find out the bounding box of current triangle.
float min_x = min(v[0].x(),min(v[1].x(),v[2].x()));
float max_x = max(v[0].x(),max(v[1].x(),v[2].x()));
float min_y = min(v[0].y(),min(v[1].y(),v[2].y()));
float max_y = max(v[0].y(),max(v[1].y(),v[2].y()));
min_x = floor(min_x); //floor() Round down
max_x = ceil(max_x);
min_y = floor(min_y);
max_y = ceil(max_y);
// iterate through the pixel and find if the current pixel is inside the triangle
for(float x = min_x; x <= max_x; x++)
for(float y = min_y; y <= max_y; y++)
{
float count=0;
float mindep=INT_MAX;
float eid=get_index(x,y)*4;
for(int k=0;k<4;k++)
{
//with MSAA
if(insideTriangle(x + a[k],y + a[k+1],t.v))
{
// If so, use the following code to get the interpolated z value.
auto tup=computeBarycentric2D(x + a[k],y + a[k+1],t.v);
float alpha,beta,gamma;
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(z_interpolated mindep)":
if use, the system handle the yellow Triangle firstly beacause its depth is lower, other 3/4 is black,
the blue Triangle will not make effect.
*/
Vector3f color=super_frame_buf[eid]+super_frame_buf[eid+1]+super_frame_buf[eid+2]+super_frame_buf[eid+3];
set_pixel({x,y,mindep},color);
depth_buf[get_index(x,y)] = min(depth_buf[get_index(x,y)],mindep);
}
}