透视正确的纹理映射; z距离计算可能是错误的

时间:2010-01-14 22:51:59

标签: c++ rasterizing zbuffer

我正在制作一个软件光栅化器,我遇到了一些障碍:我似乎无法使透视校正纹理映射起作用。

我的算法是先按y对坐标进行排序。这将返回最高,最低和中心点。然后我使用delta's遍历扫描线:

// ordering by y is put here

order[0] = &a_Triangle.p[v_order[0]];
order[1] = &a_Triangle.p[v_order[1]];
order[2] = &a_Triangle.p[v_order[2]];

float height1, height2, height3;

height1 = (float)((int)(order[2]->y + 1) - (int)(order[0]->y));
height2 = (float)((int)(order[1]->y + 1) - (int)(order[0]->y));
height3 = (float)((int)(order[2]->y + 1) - (int)(order[1]->y));

// x 

float x_start, x_end;
float x[3];
float x_delta[3];

x_delta[0] = (order[2]->x - order[0]->x) / height1;
x_delta[1] = (order[1]->x - order[0]->x) / height2;
x_delta[2] = (order[2]->x - order[1]->x) / height3;

x[0] = order[0]->x;
x[1] = order[0]->x;
x[2] = order[1]->x;

然后我们从order[0]->y渲染到order[2]->y,将x_startx_end增加一个增量。渲染顶部时,delta是x_delta[0]x_delta[1]。渲染底部时,delta为x_delta[0]x_delta[2]。然后我们在扫描线上的x_start和x_end之间进行线性插值。 UV坐标以相同的方式进行插值,以y开始排序,从开始和结束开始,每步都应用delta。

除非我尝试对透视进行正确的UV贴图,否则此工作正常。基本算法是为每个顶点取UV/z1/z并在它们之间进行插值。对于每个像素,UV坐标变为UV_current * z_current。但是,这就是结果:

alt text

反转部分会告诉您三角形的翻转位置。如您所见,这两个三角形似乎都朝向地平线中的不同点。

这是我用来计算空间中某点的Z:

float GetZToPoint(Vec3 a_Point)
{
    Vec3 projected = m_Rotation * (a_Point - m_Position);

    // #define FOV_ANGLE 60.f
    // static const float FOCAL_LENGTH = 1 / tanf(_RadToDeg(FOV_ANGLE) / 2);
    // static const float DEPTH = HALFHEIGHT * FOCAL_LENGTH; 
    float zcamera = DEPTH / projected.z;

    return zcamera;
}

我是对的,这是一个z缓冲区问题吗?

3 个答案:

答案 0 :(得分:4)

答案 1 :(得分:0)

我不知道我可以帮助解决您的问题,但我当时阅读的关于软件渲染的最佳书籍之一可由Michael Abrash在线Graphics Programming Black Book获取。

答案 2 :(得分:0)

如果要插入1/z,则需要将UV/z乘以z,而不是1/z。假设你有这个:

UV = UV_current * z_current

z_current正在插入1/z,您应该将其更改为:

UV = UV_current / z_current

然后您可能希望将z_current重命名为one_over_z_current