Example #1
0
        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);
                        }
                    }
                }
            }
        }