C++ Z缓冲区算法的实现

C++ Z缓冲区算法的实现,c++,graphics,3d,rendering,zbuffer,C++,Graphics,3d,Rendering,Zbuffer,我正在尝试计算机图形学,并希望在软件中实现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

我正在尝试计算机图形学,并希望在软件中实现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法线

现在,对于每个顶部或底部三角形,我检查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
//三角形的顶部

对于(int y=y0;y,在实现Z缓冲时,不需要对面法线进行任何处理。只需要投影三角形的逐顶点“深度”

此外,我很抱歉只浏览了一下你的问题代码,但是如果你想做透视投影,那么确保你线性插值的每像素“深度”不是世界/相机深度,而是与1/Z_世界或1/W成比例的(什么?没有mathjax

也就是说,有一个投影三角形,其中每个顶点Vi都有
{Vi_screenX,Vi_screenY,Vi_projectedDepth}和
Vi_projectedDepth=线性函数(1/Vi_Z_摄像机)。

非常简单的例子包括:

Vi_projectedDepth=1/Vi_Z_摄像机或
Vi_projectedDepth=1.0-1/Vi_Z_摄像头

然后,必须在三角形上线性插值Vi_投影深度值,但不需要取这些插值的倒数(至少不需要Z缓冲区排序。如果要进行透视校正纹理,OTOH,可能最终需要计算倒数)


如果不这样做,当几何体有隐式相交时,就会得到非常奇怪的结果-我刚刚记得我在中对此做了评论。

float D=-(nx*vx,+ny*vy+nz*vz)中间有一个额外逗号。而且,一旦你在光栅化器中实现了透视插值,这是免费的。<代码> z 直接从脸部顶点直接插入,与“代码> x,y < /代码>相同……同时光栅化。不需要使用平面方程……