shs1992shs

Forum Replies Created

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • in reply to: 作业二图片异常 #12096 Score: 0
    shs1992shs
    Participant

    透视投影错了,main函数里输入的zNear和zFar都是正值,透视投影的n和f是负值,令n = -zNear, f = -zFar再代入计算,而且你再检查下你那个正视投影矩阵正确吗?
    修正后,你应该还会遇到三角形绘制顺序颠倒的问题,参考下面的回答
    https://games-cn.org/forums/topic/guanyuzuoye2lianggesanjiaoxingzhongdiebufendez-bufferwenti/

    in reply to: 关于作业2两个三角形重叠部分的Z-Buffer问题 #12095 Score: 0
    shs1992shs
    Participant

    我的理解是mvp变换后z坐标就在[-1,1]之内,那么经过放大f1倍后(vert.z()*f1),如果z值是负的,就是还是负的。第二个三角形原始的z为-5,小于第一个三角形原始z值-2,mvp变换后还是符合这种情况。
    那么加上f2之后,就是所有点都平移到了z轴正方向,此时所有的z坐标都是正值,那么此时第二个三角形的z值假设由最初的-5变为1,第一个三角形的z值此时必然比1要大,可能为8,还是符合靠近相机的z值大于远离相机的z值,这会覆盖后面的z值。那么判断深度值,坚持以这个关系进行比较,即若当前的z值大于z缓冲,那么就以当前的三角形的颜色绘制,并更新z缓冲,这样理解起来是非常直观的。
    此处出现问题,主要是代码框架的depth_buf初始化的问题,初始化值是正无穷大, 那么从第一个三角形开始比较,其z值小于初始 z缓冲(无穷大),认为在目前深度后面,不用更新,那么最终就什么都没有绘制,为黑屏。
    如果直接把判断关系改为作业提示中的z值越大表示离视点越远,即若当前z值小于z缓冲,则以当前颜色绘制并更新,那么此时第一个三角形满足情况,顺利绘制并更新z缓冲。但是第二个三角形中的部分z值小于和第一个三角形重叠部分的z值,即小于z缓冲值,那么满足判断关系,进行绘制覆盖并更新,从而颠倒了两个三角形的绘制顺序。所以最简单的修改,就是把初始化的z缓冲设为负无穷大,这样就是z值越小,离相机越远。参考下面的代码。
    如果坚持以作业提示中的方法,初始化的z缓冲还是正无穷大,那就需要修改原代码框架里的视口变换的z坐标变换了,即把 vert.z() * f1进行放大时,前面加一负号,完成z值镜像反转。此时原来离视点最远的z值由负变正,数值上变为最大,那么判断关系就符合作业要求了,z值越小离视点越近,若当前z值小于z缓冲,则绘制覆盖并更新,顺序就正确了。这个方法我认为理解起来不是那么直观,因为前面的mvp推导过程都是坚持z值为负值的,突然一下转为正值,很容易让人混淆,理解起来困难。
    两种方法都试一下之后,相信就会加深理解了。

    修改后的代码如下:

    int pixel_index = get_index(x, y);
    float depth = depth_buf[pixel_index];
    if (depth < z_interpolated)  {
        set_pixel(Vector3f(x, y, z_interpolated), t.getColor());
        depth_buf[pixel_index] = z_interpolated; // update depth
    }
    void rst::rasterizer::clear(rst::Buffers buff)
    {
        if ((buff & rst::Buffers::Color) == rst::Buffers::Color)
        {
            std::fill(frame_buf.begin(), frame_buf.end(), Eigen::Vector3f{0, 0, 0});
        }
        if ((buff & rst::Buffers::Depth) == rst::Buffers::Depth)
        {
            //std::fill(depth_buf.begin(), depth_buf.end(), std::numeric_limits<float>::infinity()); //原框架初始深度值为∞
            std::fill(depth_buf.begin(), depth_buf.end(), -std::numeric_limits<float>::infinity());//初始深度值改为-∞,z轴最远处。
        }
    }

    修改视口变换的代码:

    // Viewport transformation
    for (auto &vert : v)
    {
        vert.x() = 0.5 * width * (vert.x() + 1.0);
        vert.y() = 0.5 * height * (vert.y() + 1.0);
        vert.z() = -vert.z() * f1 + f2; // 负号是为了实现镜像反转(reflection )
        // vert.z() = vert.z() * f1 + f2;
    }
    in reply to: 关于作业2insideTriangle函数问题 #12094 Score: 0
    shs1992shs
    Participant

    是的,会有问题,最好是在函数内,对x+0.5,不然会被截断,而在内部声明一个Vector2f,输入x+0.5时,会进行隐式转换,转换成float型,就不存在问题。可以写个小函数测试一下

Viewing 3 posts - 1 through 3 (of 3 total)