Example #1
0
        public void DrawTriangle(ref Vertex v0, ref Vertex v1, ref Vertex v2, Color4 color)
        {
            // Sorting the points in order to always have this order on screen p1, p2 & p3
            // with p1 always up (thus having the Y the lowest possible to be near the top screen)
            // then p2 between p1 & p3
            if (v0.Coordinates.Y > v1.Coordinates.Y)
                MathExtensions.Swap(ref v0, ref v1);
            if (v1.Coordinates.Y > v2.Coordinates.Y)
                MathExtensions.Swap(ref v1, ref v2);
            if (v0.Coordinates.Y > v1.Coordinates.Y)
                MathExtensions.Swap(ref v0, ref v1);

            Vector3 p0 = v0.Coordinates;
            Vector3 p1 = v1.Coordinates;
            Vector3 p2 = v2.Coordinates;

            // computing the cos of the angle between the light vector and the normal vector
            // it will return a value between 0 and 1 that will be used as the intensity of the color
            var nl0 = MathExtensions.ComputeNDotL(ref v0.WorldCoordinates, ref v0.Normal, ref LightPosition);
            var nl1 = MathExtensions.ComputeNDotL(ref v1.WorldCoordinates, ref v1.Normal, ref LightPosition);
            var nl2 = MathExtensions.ComputeNDotL(ref v2.WorldCoordinates, ref v2.Normal, ref LightPosition);

            // computing lines' directions
            // http://en.wikipedia.org/wiki/Slope
            // Computing slopes
            var d1 = (p1.Y - p0.Y > 0) ? (p1.X - p0.X) / (p1.Y - p0.Y) : 0;
            var d2 = (p2.Y - p0.Y > 0) ? (p2.X - p0.X) / (p2.Y - p0.Y) : 0;

            var data = new ScanlineData();
            // First case where triangles are like that:
            // P1
            // -
            // --
            // - -
            // -  -
            // -   - P2
            // -  -
            // - -
            // -
            // P3
            if (d1 > d2)
            {
                for (var y = (int)p0.Y; y <= (int)p2.Y; y++)
                {
                    data.Y = y;

                    if (y < p1.Y)
                    {
                        data.NDotL0 = nl0;
                        data.NDotL1 = nl2;
                        data.NDotL2 = nl0;
                        data.NDotL3 = nl1;
                        ProcessScanline(ref data, ref v0, ref v2, ref v0, ref v1, ref color);
                    }
                    else
                    {
                        data.NDotL0 = nl0;
                        data.NDotL1 = nl2;
                        data.NDotL2 = nl1;
                        data.NDotL3 = nl2;
                        ProcessScanline(ref data, ref v0, ref v2, ref v1, ref v2, ref color);
                    }
                }
            }
            // First case where triangles are like that:
            //       P1
            //        -
            //       --
            //      - -
            //     -  -
            // P2 -   -
            //     -  -
            //      - -
            //        -
            //       P3
            else
            {
                for (var y = (int)p0.Y; y <= (int)p2.Y; y++)
                {
                    data.Y = y;

                    if (y < p1.Y)
                    {
                        data.NDotL0 = nl0;
                        data.NDotL1 = nl1;
                        data.NDotL2 = nl0;
                        data.NDotL3 = nl2;
                        ProcessScanline(ref data, ref v0, ref v1, ref v0, ref v2, ref color);
                    }
                    else
                    {
                        data.NDotL0 = nl1;
                        data.NDotL1 = nl2;
                        data.NDotL2 = nl0;
                        data.NDotL3 = nl2;
                        ProcessScanline(ref data, ref v1, ref v2, ref v0, ref v2, ref color);
                    }
                }
            }
        }
Example #2
0
        void ProcessScanline(ref ScanlineData d, ref Vertex v0, ref Vertex v1, ref Vertex v2, ref Vertex v3, ref Color4 color)
        {
            var p0 = v0.Coordinates;
            var p1 = v1.Coordinates;
            var p2 = v2.Coordinates;
            var p3 = v3.Coordinates;

            // Thanks to current Y, we can compute the gradient to compute others values like
            // the starting X (sx) and ending X (ex) to draw between
            // if pa.Y == pb.Y or pc.Y == pd.Y, gradient is forced to 1
            var gradient1 = p0.Y != p1.Y ? (d.Y - p0.Y) / (p1.Y - p0.Y) : 1;
            var gradient2 = p2.Y != p3.Y ? (d.Y - p2.Y) / (p3.Y - p2.Y) : 1;

            var sx = (int)gradient1.Interpolate(p0.X, p1.X);
            var ex = (int)gradient2.Interpolate(p2.X, p3.X);

            // starting Z & ending Z
            var z1 = gradient1.Interpolate(p0.Z, p1.Z);
            var z2 = gradient2.Interpolate(p2.Z, p3.Z);

            var snl = gradient1.Interpolate(d.NDotL0, d.NDotL1);
            var enl = gradient2.Interpolate(d.NDotL2, d.NDotL3);

            Color c = new Color();
            Color4 c4;
            Vector3 pt;
            // drawing a line from left (sx) to right (ex)
            for (var x = sx; x < ex; x++)
            {
                var gradient = (x - sx) / (float)(ex - sx);
                var z = gradient.Interpolate(z1, z2);
                var ndotl = gradient.Interpolate(snl, enl);
                Color4.Scale(ref color, ndotl, out c4);
                c.FromColor4(ref c4);
                pt.X = x;
                pt.Y = d.Y;
                pt.Z = z;
                DrawPoint(ref pt, ref c);
            }
        }