Пример #1
0
        public void DrawTriangle_PS(Vertex v1, Vertex v2, Vertex v3, Color color, double Time, Vector3 viewerPos, bool blin = false)
        {
            if (v1.Position.y > v2.Position.y)
            {
                Swap(ref v1, ref v2);
            }

            if (v2.Position.y > v3.Position.y)
            {
                Swap(ref v2, ref v3);
            }

            if (v1.Position.y > v2.Position.y)
            {
                Swap(ref v1, ref v2);
            }

            var p1 = v1.Position;
            var p2 = v2.Position;
            var p3 = v3.Position;

            var wp1 = v1.WorldPosition;
            var wp2 = v2.WorldPosition;
            var wp3 = v3.WorldPosition;

            Vector3 lightPos = LP;

            var data = new ScanLineDataPhong {
            };

            double dP1P2, dP1P3;

            if (p2.y - p1.y > 0)
            {
                dP1P2 = (p2.x - p1.x) / (p2.y - p1.y);
            }
            else
            {
                dP1P2 = 0;
            }

            if (p3.y - p1.y > 0)
            {
                dP1P3 = (p3.x - p1.x) / (p3.y - p1.y);
            }
            else
            {
                dP1P3 = 0;
            }

            if (dP1P2 > dP1P3)
            {
                for (var y = (int)p1.y; y <= (int)p3.y; y++)
                {
                    double gradient = (y - p1.y) / (double)(p3.y - p1.y);
                    data.currentWorldY = Interpolate(wp1.y, wp3.y, gradient);
                    data.currentY      = y;
                    if (y < p2.y)
                    {
                        data.Na = v1.Normal;
                        data.Nb = v3.Normal;
                        data.Nc = v1.Normal;
                        data.Nd = v2.Normal;
                        ProcessScanLine_PS(data, v1, v3, v1, v2, color, lightPos, viewerPos, blin);
                    }
                    else
                    {
                        data.Na = v1.Normal;
                        data.Nb = v3.Normal;
                        data.Nc = v2.Normal;
                        data.Nd = v3.Normal;
                        ProcessScanLine_PS(data, v1, v3, v2, v3, color, lightPos, viewerPos, blin);
                    }
                }
            }
            else
            {
                for (var y = (int)p1.y; y <= (int)p3.y; y++)
                {
                    double gradient = (y - p1.y) / (double)(p3.y - p1.y);
                    data.currentWorldY = Interpolate(wp1.y, wp3.y, gradient);
                    data.currentY      = y;
                    if (y < p2.y)
                    {
                        data.Na = v1.Normal;
                        data.Nb = v2.Normal;
                        data.Nc = v1.Normal;
                        data.Nd = v3.Normal;
                        ProcessScanLine_PS(data, v1, v2, v1, v3, color, lightPos, viewerPos, blin);
                    }
                    else
                    {
                        data.Na = v2.Normal;
                        data.Nb = v3.Normal;
                        data.Nc = v1.Normal;
                        data.Nd = v3.Normal;
                        ProcessScanLine_PS(data, v2, v3, v1, v3, color, lightPos, viewerPos, blin);
                    }
                }
            }
        }
Пример #2
0
        void ProcessScanLine_PS(ScanLineDataPhong data, Vertex A, Vertex B, Vertex C, Vertex D, Color color, Vector3 lightPosition, Vector3 viewerPosition, bool blin)
        {
            var pa = A.Position;
            var pb = B.Position;
            var pc = C.Position;
            var pd = D.Position;

            var wpa = A.WorldPosition;
            var wpb = B.WorldPosition;
            var wpc = C.WorldPosition;
            var wpd = D.WorldPosition;

            var gradient1 = pa.y != pb.y ? (data.currentY - pa.y) / (pb.y - pa.y) : 1;
            var gradient2 = pc.y != pd.y ? (data.currentY - pc.y) / (pd.y - pc.y) : 1;

            int sx  = (int)Interpolate(pa.x, pb.x, gradient1);
            int ex  = (int)Interpolate(pc.x, pd.x, gradient2);
            int swx = (int)Interpolate(wpa.x, wpb.x, gradient1);
            int ewx = (int)Interpolate(wpc.x, wpd.x, gradient2);

            double z1  = Interpolate(pa.z, pb.z, gradient1);
            double z2  = Interpolate(pc.z, pd.z, gradient2);
            double wz1 = Interpolate(wpa.z, wpb.z, gradient1);
            double wz2 = Interpolate(wpc.z, wpd.z, gradient2);

            var sN = InterpolateVector(data.Na, data.Nb, gradient1);
            var eN = InterpolateVector(data.Nc, data.Nd, gradient2);

            for (var x = sx; x < ex; x++)
            {
                double gradient = (x - sx) / (double)(ex - sx);
                var    z        = Interpolate(z1, z2, gradient);
                var    position = new Vector3(x, data.currentY, z);

                var wx        = Interpolate(swx, ewx, gradient);
                var wy        = data.currentWorldY;
                var wz        = Interpolate(wz1, wz2, gradient);
                var wPosition = new Vector3(wx, wy, wz);

                var N   = InterpolateVector(sN, eN, gradient);
                var NoL = Compute_NoL(wPosition, N, lightPosition);

                byte r = 0, g = 0, b = 0;
                if (blin)
                {
                    var H = Compute_H(wPosition, viewerPosition, lightPosition);
                    H.Normalize();
                    var Nnorm = N;
                    Nnorm.Normalize();
                    var NoH = Vector3.Dot(Nnorm, H);
                    NoH = Math.Pow(NoH, alpha);
                    r   = Limit(kd * color.R * NoL + ks * color.R * NoH);
                    g   = Limit(kd * color.R * NoL + ks * color.R * NoH);
                    b   = Limit(kd * color.R * NoL + ks * color.R * NoH);
                }
                else
                {
                    var R = Compute_R(wPosition, N, lightPosition);
                    R.Normalize();
                    var V = viewerPosition - wPosition;
                    V.Normalize();
                    var RoV = OverZero(Vector3.Dot(R, V));
                    RoV = Math.Pow(RoV, alpha);
                    r   = Limit(kd * color.R * NoL + ks * color.R * RoV);
                    g   = Limit(kd * color.R * NoL + ks * color.R * RoV);
                    b   = Limit(kd * color.R * NoL + ks * color.R * RoV);
                }



                var shadedColor = Color.FromArgb(color.A, r, g, b);
                DrawPoint(position, shadedColor);
            }
        }