实现 Z 缓冲区算法

Implementing Z Buffer Algorithm

我正在尝试使用计算机图形进行实验,并希望在软件中实现用于渲染的 Z 缓冲区算法。

所以我正在尝试使用以下平面方程:

z = -(ax + by + d)/c

使用平面形式方程计算像素的 Z 坐标 我应该计算三角形的面法线吗?或者一个顶点的法线就足够了?

我是这样计算的:

double zValueOfPoint(float vx, float vy, float vz, float x, float y, float nx, float ny, float nz)
{
    float A = nx;
    float B = ny;
    float C = nz;
    float D = -(nx*vx, +ny * vy + nz * vz);
    float z = -(A*x + B * y + D) / C;
    return z;
}

vx,vy,vz顶点,x,y像素坐标,nx,ny,nz顶点法线

现在,对于每个 TOP 或 Bottom 三角形,我检查 Z 像素到 ZBuffer 像素

// Top of the triangle
    for (int y = y0; y<y2; y++)
    {

        for (int x = xl_edge; x<xr_edge; x++)
        {
            float zOfPixel = zValueOfPoint(vx, vy, vz, x, y, nx, ny, nz);
            if (zOfPixel < zbuffer[int(x + y * m_Width)]) {
                zbuffer[int(x + y*m_Width)] = zOfPixel;
                SetPixel((unsigned int)x, (unsigned int)y, color);
            }

        }//end for loop x

底部三角形相同

现在我的模型完全坏了。 Z 缓冲区已正确初始化。

在实施 Z 缓冲时,您不需要对面法线做任何事情。对于投影三角形,每个顶点 "depths" 只需要

此外,我很抱歉只浏览了你问题的代码,但如果你想做一个 perspective 投影,那么确保 "depth" 你是线性的每个像素的插值是 不是 world/camera 深度,而是与 成比例的东西(什么?没有 mathjax on SO?) 到 1/Z_world 或 1/W.

也就是说,您有一个投影三角形,其中每个顶点 Vi 具有
{Vi_screenX, Vi_screenY、Vi_projectedDepth}
Vi_projectedDepth = linear_function_of(1 / Vi_Z_camera).

非常简单的例子包括:

Vi_projectedDepth = 1/Vi_Z_camera or
Vi_projectedDepth = 1.0 - 1/Vi_Z_camera

然后您必须对整个三角形的 Vi_projectedDepth 值进行线性插值,但您 不需要 需要取这些插值的倒数(至少对于 Z-buffer 排序不是。如果你想做透视正确的纹理,OTOH,你_可能_最终需要计算倒数)。

如果不这样做,只要几何图形具有隐式交集,就会得到非常奇怪的结果 - 我只记得我在 SE Graphics.

中对此发表了评论