实现 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.
中对此发表了评论
我正在尝试使用计算机图形进行实验,并希望在软件中实现用于渲染的 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.
中对此发表了评论