C++自制3D引擎三角形光栅化器Z Buffer异常问题求助
3D引擎Z Buffer特定视角失效问题求助
我是C++及编程领域的新手,代码写法可能存在怪异之处还请见谅。近期我正在开发自制3D引擎,却遇到了Z Buffer相关问题:通常情况下所有像素显示正常,但在特定视角下Z Buffer似乎无法正常工作。我怀疑这与浮点舍入有关,但缺乏相关经验无法确定。以下附上相关代码及问题说明,若能得到帮助将万分感谢!
相关代码
void Triangle::draw(Screen screen, Camera& camera, float* zbuffer) { //drawTriangle(screen, camera, sP1, sP2, sP3, color, mP1, mP2, mP3, zbuffer); draw3(screen, camera, zbuffer); } void Triangle::draw3(Screen screen, Camera& camera, float* zbuffer) { //check if the triangle is visible on screen if (sP1.x < 0 && sP2.x < 0 && sP3.x < 0 || sP1.y < 0 && sP2.y < 0 && sP3.y < 0 || sP1.x > Screen::SCREEN_WIDTH && sP2.x > Screen::SCREEN_WIDTH && sP3.x > Screen::SCREEN_WIDTH || sP1.y > Screen::SCREEN_HEIGHT && sP2.y > Screen::SCREEN_HEIGHT && sP3.y > Screen::SCREEN_HEIGHT) { return; } //sort points based on height Point2D temp2d; Point3D temp3d; if (sP1.y > sP2.y) { temp2d = sP1; sP1 = sP2; sP2 = temp2d; temp3d = mP1; mP1 = mP2; mP2 = temp3d; } if (sP1.y > sP3.y) { temp2d = sP1; sP1 = sP3; sP3 = temp2d; temp3d = mP1; mP1 = mP3; mP3 = temp3d; } if (sP2.y > sP3.y) { temp2d = sP2; sP2 = sP3; sP3 = temp2d; temp3d = mP2; mP2 = mP3; mP3 = temp3d; } //dont draw triangle with no area if (sP1.y == sP3.y) { return; } float longSlope = (sP1.x - sP3.x) / (sP3.y - sP1.y); //if the triangle has a flat top, dont calculate the short sloap float shortSlope = 0; float bottomSloap = 0; if (sP1.y != sP2.y) { shortSlope = (sP1.x - sP2.x) / (sP2.y - sP1.y); } if (sP2.y != sP3.y) { bottomSloap = (sP2.x - sP3.x) / (sP3.y - sP2.y); } //start at the peak of the triangle and work down float leftX = sP1.x; float rightX = sP1.x; float bisectX; float leftSlope = longSlope; float rightSlope = shortSlope; float end = sP2.y; bool swap = false; int y = sP1.y; if (sP1.y > 0) { y = sP1.y + 1; } double totalArea = areaOfTriangle(sP1, sP2, sP3), areaP1P2P4, areaP1P3P4, areaP2P3P4; float ratioP1, ratioP2, ratioP3; float mP4Dist; //make sure leftSlope corrosponds to the left most sloap bisectX = sP1.x - (sP1.x - sP3.x) / (sP3.y - sP1.y) * (sP2.y - sP1.y); if (sP2.x < bisectX) { leftSlope = shortSlope; rightSlope = longSlope; swap = true; } if (sP1.y == sP2.y) { y += 1; } if (sP1.y != sP2.y) { for (y; y < sP2.y; ++y) { for (int x = leftX; x < rightX - 1; x++) { sP4.x = x; sP4.y = y; //find bary coords areaP1P2P4 = areaOfTriangle(sP1, sP2, sP4); areaP1P3P4 = areaOfTriangle(sP1, sP3, sP4); areaP2P3P4 = areaOfTriangle(sP2, sP3, sP4); ratioP1 = areaP2P3P4 / totalArea; ratioP2 = areaP1P3P4 / totalArea; ratioP3 = areaP1P2P4 / totalArea; mP4.x = mP1.x * ratioP1 + mP2.x * ratioP2 + mP3.x * ratioP3; mP4.y = mP1.y * ratioP1 + mP2.y * ratioP2 + mP3.y * ratioP3; mP4.z = mP1.z * ratioP1 + mP2.z * ratioP2 + mP3.z * ratioP3; mP4Dist = getLineDist3d(mP4, camera.map); if (x > 0 && x < Screen::SCREEN_WIDTH && y > 0 && y < Screen::SCREEN_HEIGHT) { if (mP4Dist < screen.m_zbuffer[x + y * Screen::SCREEN_WIDTH]) { screen.setPixel(x, y, color); screen.setZBuffer(x, y, mP4Dist); } } } leftX -= leftSlope; rightX -= rightSlope; } } if (swap) { leftSlope = bottomSloap; leftX = sP2.x; } else { rightSlope = bottomSloap; rightX = sP2.x; } if (sP2.y != sP3.y) { for (y; y < sP3.y; y++) { for (int x = leftX; x < rightX - 1; x++) { sP4.x = x; sP4.y = y; //find bary coords areaP1P2P4 = areaOfTriangle(sP1, sP2, sP4); areaP1P3P4 = areaOfTriangle(sP1, sP3, sP4); areaP2P3P4 = areaOfTriangle(sP2, sP3, sP4); ratioP1 = areaP2P3P4 / totalArea; ratioP2 = areaP1P3P4 / totalArea; ratioP3 = areaP1P2P4 / totalArea; mP4.x = mP1.x * ratioP1 + mP2.x * ratioP2 + mP3.x * ratioP3; mP4.y = mP1.y * ratioP1 + mP2.y * ratioP2 + mP3.y * ratioP3; mP4.z = mP1.z * ratioP1 + mP2.z * ratioP2 + mP3.z * ratioP3; mP4Dist = getLineDist3d(mP4, camera.map); if (x > 0 && x < Screen::SCREEN_WIDTH && y > 0 && y < Screen::SCREEN_HEIGHT) { if (mP4Dist < screen.m_zbuffer[x + y * Screen::SCREEN_WIDTH]) { screen.setPixel(x, y, color); screen.setZBuffer(x, y, mP4Dist); } } } leftX -= leftSlope; rightX -= rightSlope; } } } float areaOfTriangle(Point2D p1, Point2D p2, Point2D p3) { //black box Heron's Formula finds area of triangle based on 3 points float area = 0.5 * abs((p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y))); return area; }
问题现象
特定视角下,红色三角形错误地嵌入到棕色三角形内部,说明Z Buffer未正确判断像素的深度优先级。
内容的提问来源于stack exchange,提问作者Sol
相关产品推荐
相关产品推荐

