3.1 Lession 3 纹理
[TOC]
实际上通过纹理坐标找到纹理上的颜色,
但是只有顶点有纹理坐标,具体面填充的颜色,需要通过顶点之间的插值进行计算,找到对应的插值后的坐标再找到纹理上的颜色
{
int width = 1000;
int height = 1000;
int depth = 255;
TGAImage image(width, height, TGAImage::RGB);
Model model("../obj/african_head.obj");
Vec3f lightDir(0,0,-1);
int zbuffer[width * height];
for (int i = 0; i < width * height; i++) {
zbuffer[i] = std::numeric_limits<int>::min();
}
for (int face = 0; face < model.nfaces(); face++) {
Vec3i screenCordinates[3];
Vec3f worldCordinates[3];
Vec2i uv[3];
for (int j =0; j < 3; j++) {
Vec3f v = model.vert(face, j);
uv[j] = model.uv(face, j);
screenCordinates[j] = Vec3i ((v.x + 1.) /2. * image.get_width(), (v.y + 1.) /2. * image.get_height(), (v.z+1.)*depth/2.);
worldCordinates[j] = v;
}
Vec3f norm = (worldCordinates[2] - worldCordinates[0]) ^ (worldCordinates[1] - worldCordinates[0]);
norm.normalize();
float intensity = norm.dotProduct(lightDir);
if (intensity > 0) {
triangle_line_sweeping_texture_3d(screenCordinates[0], screenCordinates[1], screenCordinates[2], uv[0], uv[1],uv[2], &model, intensity, image, zbuffer);
}
}
image.flip_vertically();
image.write_tga_file("l3_zbuffer_texture.tga");
}
void triangle_line_sweeping_texture_3d(Vec3i p0, Vec3i p1, Vec3i p2, Vec2i uv0, Vec2i uv1, Vec2i uv2, Model *model, int intensity, TGAImage &image, int* zbuffer) {
//冒泡
if (p0.y > p1.y) {
std::swap(p0, p1);
std::swap(uv0, uv1);
}
if (p0.y > p2.y) {
std::swap(p0, p2);
std::swap(uv0, uv2);
}
if (p1.y > p2.y) {
std::swap(p1, p2);
std::swap(uv1, uv2);
}
std::cout << "after swap\n" << p0 << p1 << p2;
//总高度
int totalHeight = p2.y - p0.y + 1;
//第一段三角形高度
int segmentHeight_1 = p1.y - p0.y + 1;
//第二段三角形高度
int segmentHeight_2 = p2.y - p1.y + 1;
std::cout << "totalHeight=" << totalHeight << " segmentHeight=" << segmentHeight_1 << "\n";
for (int y = p0.y; y <= p2.y; y++) {
bool isPart1 = y > p1.y - 1 ? false : true;
float alpha = isPart1 ? ((float) (y - p0.y + 1) / segmentHeight_1) : ((float) (y - p1.y + 1) / segmentHeight_2);
Vec3i A = isPart1 ? p0 + (p1 - p0) * alpha : p1 + (p2 - p1) * alpha;
Vec2i uvA = isPart1 ? uv0 + (uv1 - uv0) * alpha : uv1 + (uv2 - uv1) * alpha;
//注意这里beta计算变换高度是 y - p0.y + 1,最后的+1很重要
float beta = ((float) (y - p0.y + 1) / totalHeight);
Vec3i B = p0 + (p2 - p0) * beta;
Vec2i uvB = uv0 + (uv2 - uv0) * beta;
std::cout << "A = " << A << "B= " << B;
if (A.x > B.x) {
std::swap(A, B);
std::swap(uvA, uvB);
}
for (int x = A.x; x <= B.x; x++) {
float t = (x - A.x)/(float)(B.x - A.x);
int z = A.z * (1-t) + B.z * t + .5f;
int bufferIdx = x + image.get_width() * y;
if (zbuffer[bufferIdx] < z) {
zbuffer[bufferIdx] = z;
Vec2i uv = uvA + (uvB - uvA) * t;
TGAColor color = model->diffuse(uv);
image.set(x, y, color);
}
}
}
}