private unsafe void DrawTriangle(Vec3i t0, Vec3i t1, Vec3i t2, uint color, ref int[] zBuffer) { if (t0.Y == t1.Y && t0.Y == t2.Y) { return; } if (t0.Y > t1.Y) { Swap(ref t0, ref t1); } if (t0.Y > t2.Y) { Swap(ref t0, ref t2); } if (t1.Y > t2.Y) { Swap(ref t1, ref t2); } int total_height = t2.Y - t0.Y; fixed(int *zBufferPtr = &zBuffer[0]) { 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 = i / (float)total_height; float beta = (i - (second_half ? t1.Y - t0.Y : 0)) / (float)segment_height; Vec3i t2t0 = (t2 - t0); Vec3i t2t1 = (t2 - t1); Vec3i t1t0 = (t1 - t0); Vec3i A = new Vec3i(new Vector3(t0.X, t0.Y, t0.Z) + new Vector3(t2t0.X, t2t0.Y, t2t0.Z) * alpha); Vec3i B = second_half ? new Vec3i(new Vector3(t1.X, t1.Y, t1.Z) + new Vector3(t2t1.X, t2t1.Y, t2t1.Z) * beta) : new Vec3i(new Vector3(t0.X, t0.Y, t0.Z) + new Vector3(t1t0.X, t1t0.Y, t1t0.Z) * beta); if (A.X > B.X) { Swap(ref A, ref B); } for (int j = A.X; j <= B.X; j++) { float phi = B.X == A.X ? 1f : (j - A.X) / (float)(B.X - A.X); Vec3i ba = (B - A); Vec3i P = new Vec3i(new Vector3(A.X, A.Y, A.Z) + new Vector3(ba.X, ba.Y, ba.Z) * phi); int idx = P.X + P.Y * _width; if (idx >= 0 && idx < _width * _height && *(zBufferPtr + idx) < P.Z) { *(zBufferPtr + idx) = P.Z; _viewport.SetPixel(P.X, P.Y, color); } } } } }