绘制物体的深度远近会影响最终投射的效果
画家算法:是z值排序所有物体,从远往近全部绘制,近处物体覆盖远处物体。效率低,且无法处理物体相互穿插的情况
维护一个zBuffer,记录每个像素点的最近zBuffer,根据每个像素点的zBuffer决定 绘制哪个物体的颜色
关键点在已知求三角形三个顶点的情况下,求内部任一点的z值。通过重心坐标求解
求重心坐标系数
std::pair<float, float> getBarycentricCoordinates(Vec3f* pts, float x, float y) {
float beta = ((pts[0].y - pts[1].y) * x + (pts[1].x - pts[0].x) * y + pts[0].x * pts[1].y - pts[1].x * pts[0].y)
/ ((pts[0].y - pts[1].y) * pts[2].x + (pts[1].x - pts[0].x) * pts[2].y + pts[0].x * pts[1].y - pts[1].x * pts[0].y);
float gamma = ((pts[0].y - pts[2].y) * x + (pts[2].x - pts[0].x) * y + pts[0].x * pts[2].y - pts[2].x * pts[0].y)
/ ((pts[0].y - pts[2].y) * pts[1].x + (pts[2].x - pts[0].x) * pts[1].y + pts[0].x * pts[2].y - pts[2].x * pts[0].y);
return { beta,gamma };
}
记录zBuffer
std::vector<float> zBuffer(Width * Height, -std::numeric_limits<float>::infinity());
void triangle(Vec3f* pts, TGAImage& image, TGAColor color) {
float minX = image.get_width() - 1;
float minY = image.get_height() - 1;
float maxX = 0;
float maxY = 0;
for (int i = 0; i < 3; i++) {
minX = std::min(minX, pts[i].x);
maxX = std::max(maxX, pts[i].x);
minY = std::min(minY, pts[i].y);
maxY = std::max(maxY, pts[i].y);
}
minX = std::max(0.f, minX);
maxX = std::min(maxX, (float)image.get_width() - 1);
minY = std::max(0.f, minY);
maxY = std::min(maxY, (float)image.get_height() - 1);
for (float x = minX; x <= maxX; x++) {
for (float y = minY; y <= maxY; y++) {
auto data = getBarycentricCoordinates(pts, x, y);
float alpha = 1 - data.first - data.second;
float beta = data.first;
float gamma = data.second;
if (alpha >= 0 && beta >= 0 && gamma >= 0) {
auto z = alpha * pts[0].z + beta * pts[1].z + gamma * pts[2].z;
int idx = int(x) + int(y) * Width;
if (zBuffer[idx] < z) {
zBuffer[idx] = z;
image.set(x, y, color);
}
}
}
}
}
这里传入的顶点数据vp,x轴y轴是经过坐标变换的,z没有变换,因为z在这里的用处是对比大小的,虽然没有换算,但相对大小是不变的
最终效果
项目跟随练习代码地址