我正在尝试对计算机图形进行试验,并希望实现Z Buffer算法以在软件中进行渲染。
因此,我尝试使用以下平面方程式:
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
底部三角形相同
现在,我完全打破了模型。 Z缓冲区已正确初始化。
最佳答案
在实现Z缓冲时,您无需对面法线做任何事情。您只需要每个三角形的顶点“深度”即可。
此外,我只为您浏览问题代码而道歉,但是如果您要进行透视投影,请确保每个像素线性插值的“深度”不是世界/相机深度,而是成比例的( ?SO上没有mathjax?)到1 / Z_world或1 / W。
也就是说,您有一个投影三角形,其中每个顶点Vi都有{Vi_screenX,Vi_screenY,Vi_projectedDepth}和
Vi_projectedDepth = linear_function_of(1 / Vi_Z_camera)。
非常简单的示例包括:
然后,您必须在整个三角形上线性插值Vi_projectedDepth值,但不必取这些插值的倒数(至少不需要Z缓冲区顺序。如果要进行透视校正贴图,OTOH,则_may_需要最终计算出倒数)。
如果不执行此操作,则每当几何体具有隐式相交时,您都会得到非常奇怪的结果-我只记得我在SE Graphics中对此发表了评论。
关于c++ - 实现Z缓冲区算法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59707984/