1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| main() {
TGAImage Texture(1024, 1024, TGAImage::RGB); Texture.read_tga_file("african_head_diffuse.tga"); Texture.flip_vertically();
std::shared_ptr<float> ZBuffer(new float[WIDTH * HEIGHT], std::default_delete<float[]>()); for (int i = 0; i < (WIDTH * HEIGHT); i++) { ZBuffer.get()[i] = std::numeric_limits<int>::min(); }
const Vec3f LightDir(0.f, 0.f, -1.f);
for (int i = 0; i < ModelInstance->GetFacesNumber(); i++) { Face Face = ModelInstance->GetFace(i); Vec3f Pts[3]; Vec3f UVs[3]; Vec3f WorldCoords[3]; for (int j = 0; j < 3; j++) { const Vec3f V = ModelInstance->GetVertex(Face[j]); Pts[j] = WorldToScreen(V);
UVs[j] = Vec3f(ModelInstance->GetUV(Face.VTIndex[j]).x * 1024, ModelInstance->GetUV(Face.VTIndex[j]).y * 1024, 0); WorldCoords[j] = V; } Vec3f N = (WorldCoords[2] - WorldCoords[0]) ^ (WorldCoords[1] - WorldCoords[0]); N.normalize(); const float Intensity = N * LightDir; DrawTriangleEdgeFunc(Pts, UVs, Image, Texture, ZBuffer.get(), Intensity); printf("\r %f [%.2lf%%]", Intensity, i * 100.0f / ModelInstance->GetFacesNumber()); } } void DrawTriangleEdgeFunc(Vec3f Pts[3], Vec3f UVs[3], TGAImage& Image, TGAImage& TextureImage, float* ZBuffer, const float& Intensity) { Vec3f t0, t1, t2, uv0, uv1, uv2; t0 = (Pts[0]); t1 = (Pts[1]); t2 = (Pts[2]); uv0 = (UVs[0]); uv1 = (UVs[1]); uv2 = (UVs[2]);
if (t0.y == t1.y && t0.y == t2.y) return; if (t0.y > t1.y) { std::swap(t0, t1); std::swap(uv0, uv1); } if (t0.y > t2.y) { std::swap(t0, t2); std::swap(uv0, uv2); } if (t1.y > t2.y) { std::swap(t1, t2); std::swap(uv1, uv2); }
int total_height = t2.y - t0.y; for (int i = 0; i < total_height; i++) { bool second_half = i > t1.y - t0.y || t1.y == t0.y; int segment_height = second_half ? t2.y - t1.y : t1.y - t0.y; float alpha = (float)i / total_height; float beta = (float)(i - (second_half ? t1.y - t0.y : 0)) / segment_height; Vec3f A = t0 + Vec3f(t2 - t0) * alpha; Vec3f B = second_half ? t1 + Vec3f(t2 - t1) * beta : t0 + Vec3f(t1 - t0) * beta; Vec3f uvA = uv0 + (uv2 - uv0) * alpha; Vec3f uvB = second_half ? uv1 + (uv2 - uv1) * beta : uv0 + (uv1 - uv0) * beta; if (A.x > B.x) { std::swap(A, B); std::swap(uvA, uvB); } for (int j = A.x; j <= B.x; j++) { float phi = B.x == A.x ? 1. : (float)(j - A.x) / (float)(B.x - A.x); Vec3f P = Vec3f(A) + Vec3f(B - A) * phi; Vec3f uvP = uvA + (uvB - uvA) * phi; int idx = P.x + P.y * WIDTH; if (ZBuffer[idx] < P.z) { ZBuffer[idx] = P.z; TGAColor color = TextureImage.get(uvP.x, uvP.y) * Intensity; Image.set(P.x, P.y, color); } } } }
|