ZBuffer是像空间消隐算法,首先在三维空间中记住物体的深度信息,将物体投影到二维平面后,用一个全局的缓冲器存储每个像素对应的Z值,这样只绘制距离相机最近的表面。

讯享网
关键是要有一个缓冲器,然后是计算每个像素对应的Z值,这个Z值是在相机坐标系下的距离。
坐标转换
bool CCamera::getZbufferPoint(CPoint3D& ScreenPoint, CPoint3D& localPoint, double screenHeight, double screenWidth) {
arma::Mat<double> point3DMat({
localPoint.x,localPoint.y,localPoint.z,1 }); arma::Mat<double> point3DMatTemp = point3DMat * localRotateMat * ModelMat * CameraMat; arma::Mat<double> point2DMat = point3DMatTemp * perspectiveMat; CPoint2D viewPoint(point2DMat(0), point2DMat(1)); CPoint2D ScreenPoint2D; if (viewToScreen(ScreenPoint2D, viewPoint, angle, screenHeight, screenWidth)) {
ScreenPoint.x = ScreenPoint2D.x; ScreenPoint.y = ScreenPoint2D.y; ScreenPoint.z = point3DMatTemp(2); //相机坐标系下的Z值 ScreenPoint.rgb = localPoint.rgb; return true; } return false; }
讯享网
缓冲器的初始化和释放

讯享网void CZBuffer::initZdeep(int width, int height, int deepth) {
Zdeep = new double* [width]; for (int i = 0; i < width; i++) {
Zdeep[i] = new double[height]; for (int j = 0; j < height; j++) Zdeep[i][j] = deepth; } } void CZBuffer::releaseZdeep(int width) {
for (int i = 0; i < width; i++) delete[] Zdeep[i]; if (Zdeep != NULL) delete Zdeep; }
根据Z值和缓冲器中的存储值判断是否要填充像素
void CZBuffer::drawFaceZ(int ScreenWidth, int ScreenHeight, CDC* pDC) {
CBucketZ* currentCBucket = this->PCBucket; //一条扫描线一条扫描线的解决 while ((currentCBucket != NULL)) {
CAETZ* currentpET = currentCBucket->pET; while ((currentpET != NULL) && (currentpET->pNext != NULL)) {
CPoint3D tempStart3D(currentpET->x, currentpET->y, currentpET->z, currentpET->rgb); CPoint3D tempEnd3D(currentpET->pNext->x, currentpET->pNext->y, currentpET->pNext->z, currentpET->pNext->rgb); //CPoint3D currentpoint3D = tempEnd3D; //沿着y扫描线,x从小到大的坐标,逐个像素给屏幕像素填充颜色 for (int ix = tempStart3D.x; ix <= tempEnd3D.x; ix++) {
//计算像素坐标的z值 double z; if (tempEnd3D.x != tempStart3D.x) {
z = (tempEnd3D.z - tempStart3D.z) * (ix - tempStart3D.x) / (tempEnd3D.x - tempStart3D.x) + tempStart3D.z; } else {
tempEnd3D.z > tempStart3D.z ? z = tempStart3D.z : z = tempEnd3D.z; } //比较Zdeep中的Zbuffel int iys = (int)(currentpET->y + ScreenHeight / 2);//将屏幕坐标系中所有点平移到第一象限中 int ixs = (int)(ix + ScreenWidth / 2); if (z < Zdeep[ixs][iys])//ix iy 的值可能变化 {
Zdeep[ixs][iys] = z; //计算像素值 CRGB tempRgb; if (tempEnd3D.x != tempStart3D.x) {
/*CRGB temp((tempEnd3D.rgb - tempStart3D.rgb) * (ix - tempStart3D.x) / (tempEnd3D.x - tempStart3D.x) + tempStart3D.rgb);*/ double r = (ix - tempStart3D.x) / (tempEnd3D.x - tempStart3D.x); tempRgb = r * tempEnd3D.rgb + (1-r)* tempStart3D.rgb; } else tempRgb = tempStart3D.rgb; //设置屏幕像素颜色 pDC->SetPixelV(ix, currentpET->y, RGB(tempRgb.red, tempRgb.green, tempRgb.blue)); } } currentpET = currentpET->pNext; } currentCBucket = currentCBucket->pNext; } }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/53584.html