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);
            }
        }
    }
}