Games101 作业2

目录

三角形颠倒和前后问题

MSAA抗锯齿

处理黑边问题


三角形颠倒和前后问题

· 颠倒

三角形颠倒是因为在透视投影中,按严令琪老师课上内容,摄像机默认看向Z轴负方向,主函数中传的参数50和0.1代表了摄像机与远近平面的距离,而不代表坐标值,用50和0.1直接进行运算则会出现如下图所示中心对称现象,即颠倒问题,所以需要进行取负操作再运算

Games101 作业2_第1张图片

图片来源:

闫令琪:Games101 现代计算机图形学-作业Assignment02解析 - 灰信网(软件开发博客聚合) (freesion.com)icon-default.png?t=M666https://www.freesion.com/article/4973968295/· 前后

完成光栅化函数并运行后,发现与给的示例图中三角形的前后正好相反,这是因为光栅化函数中,是利用正值进行深度判断,越小的代表离Z轴越近,而我们的三角形位于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;
        }
    ......
}
  • 第二种是将depth_buf初始化(在Rasterizer()函数中)为负无穷大,而不是正无穷大,再用负值进行深度判断

MSAA抗锯齿

通过编写代码,在网上学习其他大佬的教程,对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作业2icon-default.png?t=M666https://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);
        }
}

 

你可能感兴趣的:(图形渲染)