예제 #1
0
 private void SortVectorByY(ref ScanLineData a, ref ScanLineData b)
 {
     if (a.Pos.y > b.Pos.y)
     {
         var temp = a;
         a = b;
         b = temp;
     }
 }
예제 #2
0
 private float CalculateSlope(ScanLineData a, ScanLineData b)
 {
     if (b.Pos.y > a.Pos.y)
     {
         return((b.Pos.x - a.Pos.x) / (b.Pos.y - a.Pos.y));
     }
     else
     {
         return(0);
     }
 }
예제 #3
0
        private void ProcessScanLine(int y, ScanLineData a, ScanLineData b, ScanLineData c, ScanLineData d)
        {
            var gradient1 = (int)a.Pos.y != (int)b.Pos.y ? (y - a.Pos.y) / (b.Pos.y - a.Pos.y) : 1;
            var gradient2 = (int)c.Pos.y != (int)d.Pos.y ? (y - c.Pos.y) / (d.Pos.y - c.Pos.y) : 1;

            var sx = (int)Interpolate(a.Pos.x, b.Pos.x, gradient1);
            var ex = (int)Interpolate(c.Pos.x, d.Pos.x, gradient2);

            var z1 = Interpolate(a.Pos.z, b.Pos.z, gradient1);
            var z2 = Interpolate(c.Pos.z, d.Pos.z, gradient2);

            var snl = Interpolate(a.NDotL, b.NDotL, gradient1);
            var enl = Interpolate(c.NDotL, d.NDotL, gradient2);

            var su = Interpolate(a.Texcoord.x, b.Texcoord.x, gradient1);
            var eu = Interpolate(c.Texcoord.x, d.Texcoord.x, gradient2);
            var sv = Interpolate(a.Texcoord.y, b.Texcoord.y, gradient1);
            var ev = Interpolate(c.Texcoord.y, d.Texcoord.y, gradient2);

            for (int x = sx; x < ex; x++)
            {
                var gradient3 = (float)(x - sx) / (ex - sx);
                var z         = Interpolate(z1, z2, gradient3);

                var index = y * m_screenWidth + x;
                if (index >= 0 && index < m_depthBuffer.Length)
                {
                    if (m_depthBuffer[index] > z)
                    {
                        m_depthBuffer[index] = z;
                        var ndotl = Interpolate(snl, enl, gradient3);
                        var color = m_light.LightColor * ndotl;
                        if (m_texture != null)
                        {
                            var u = Interpolate(su, eu, gradient3);
                            var v = Interpolate(sv, ev, gradient3);
                            color *= Map(u, v);
                        }
                        color.a = 1;
                        DrawPoint(x, y, color);
                    }
                }
            }
        }
예제 #4
0
        private void RenderBuffer(MeshData mesh)
        {
            var world      = mesh.GetLocalToWorld();
            var view       = m_camera.GetViewMatrix4X4(mesh.Position, Vector3.up);
            var projection = m_camera.GetProjectionMatrix4X4();
            var matrix     = projection * view;

            m_worldPoints.Clear();
            m_screePoints.Clear();
            m_worldNormals.Clear();
            for (int i = 0, m = mesh.Triangle.GetLength(0); i < m; i++)
            {
                var i0 = mesh.Triangle[i, 0];
                var i1 = mesh.Triangle[i, 1];
                var i2 = mesh.Triangle[i, 2];

                var wP0 = GetWorldPoint(world, mesh.Vertex[i0].Pos, i0);
                var wP1 = GetWorldPoint(world, mesh.Vertex[i1].Pos, i1);
                var wP2 = GetWorldPoint(world, mesh.Vertex[i2].Pos, i2);

                if (Mode == ShadingMode.Shaded)
                {
                    if (!BackFaceCull(wP0, wP1, wP2))
                    {
                        var sP0 = GetScreenPoint(matrix, wP0, i0);
                        var sP1 = GetScreenPoint(matrix, wP1, i1);
                        var sP2 = GetScreenPoint(matrix, wP2, i2);

                        var wN0 = GetWorldNormal(world, mesh.Vertex[i0].Normal, i0);
                        var wN1 = GetWorldNormal(world, mesh.Vertex[i1].Normal, i1);
                        var wN2 = GetWorldNormal(world, mesh.Vertex[i2].Normal, i2);

                        var ndotl0 = ComputeNDotL(wP0, wN0);
                        var ndotl1 = ComputeNDotL(wP1, wN1);
                        var ndotl2 = ComputeNDotL(wP2, wN2);

                        var v0 = new ScanLineData {
                            Pos = sP0, NDotL = ndotl0, Texcoord = mesh.Vertex[i0].Texcoord
                        };
                        var v1 = new ScanLineData {
                            Pos = sP1, NDotL = ndotl1, Texcoord = mesh.Vertex[i1].Texcoord
                        };
                        var v2 = new ScanLineData {
                            Pos = sP2, NDotL = ndotl2, Texcoord = mesh.Vertex[i2].Texcoord
                        };

                        DrawTriangle(v0, v1, v2);
                    }
                }
                else
                {
                    var sP0 = GetScreenPoint(matrix, wP0, i0);
                    var sP1 = GetScreenPoint(matrix, wP1, i1);
                    var sP2 = GetScreenPoint(matrix, wP2, i2);

                    DrawLine((int)sP0.x, (int)sP0.y, (int)sP1.x, (int)sP1.y);
                    DrawLine((int)sP1.x, (int)sP1.y, (int)sP2.x, (int)sP2.y);
                    DrawLine((int)sP2.x, (int)sP2.y, (int)sP0.x, (int)sP0.y);
                }
            }

            mesh.Rotation += new Vector3(0, 1, 0);
        }
예제 #5
0
        private void DrawTriangle(ScanLineData point0, ScanLineData point1, ScanLineData point2)
        {
            SortVectorByY(ref point0, ref point1);
            SortVectorByY(ref point1, ref point2);
            SortVectorByY(ref point0, ref point1);

            if ((int)point0.Pos.y == (int)point1.Pos.y)
            {
                if (point0.Pos.x > point1.Pos.x)
                {
                    for (int i = (int)point0.Pos.y, max = (int)point2.Pos.y; i <= max; i++)
                    {
                        ProcessScanLine(i, point1, point2, point0, point2);
                    }
                }
                else
                {
                    for (int i = (int)point0.Pos.y, max = (int)point2.Pos.y; i <= max; i++)
                    {
                        ProcessScanLine(i, point0, point2, point1, point2);
                    }
                }
            }
            else if ((int)point2.Pos.y == (int)point1.Pos.y)
            {
                if (point2.Pos.x > point1.Pos.x)
                {
                    for (int i = (int)point0.Pos.y, max = (int)point2.Pos.y; i <= max; i++)
                    {
                        ProcessScanLine(i, point0, point1, point0, point2);
                    }
                }
                else
                {
                    for (int i = (int)point0.Pos.y, max = (int)point2.Pos.y; i <= max; i++)
                    {
                        ProcessScanLine(i, point0, point2, point0, point1);
                    }
                }
            }
            else
            {
                var dP0P1 = CalculateSlope(point0, point1);
                var dP0P2 = CalculateSlope(point0, point2);

                if (dP0P1 > dP0P2)
                {
                    for (int i = (int)point0.Pos.y, max = (int)point2.Pos.y; i <= max; i++)
                    {
                        if (i < point1.Pos.y)
                        {
                            ProcessScanLine(i, point0, point2, point0, point1);
                        }
                        else
                        {
                            ProcessScanLine(i, point0, point2, point1, point2);
                        }
                    }
                }
                else
                {
                    for (int i = (int)point0.Pos.y, max = (int)point2.Pos.y; i <= max; i++)
                    {
                        if (i < point1.Pos.y)
                        {
                            ProcessScanLine(i, point0, point1, point0, point2);
                        }
                        else
                        {
                            ProcessScanLine(i, point1, point2, point0, point2);
                        }
                    }
                }
            }
        }