Example #1
0
        public Color[] Render()
        {
            this.Scene.ToList().ForEach(group =>
                                        group.ToList().ForEach(renderable =>
            {
                //for now only one shader.
                var material = renderable.material;

                //render
                var triIndex = 0;
                foreach (var triFace in renderable.RenderableObject.Triangles)
                {
                    //transform verts to screenspace
                    var screenCoords   = new List <Vector3>();
                    var localVertIndex = 0;
                    foreach (var meshVertInde in triFace.vertIndexList)
                    {
                        screenCoords.Add(material.Shader.VertexToFragment(renderable.RenderableObject, triIndex, localVertIndex));
                        localVertIndex++;
                    }

                    TriangleExtensions.drawTriangle(triIndex, screenCoords.ToArray(), material, depthBuffer, imageBuffer, Width);
                    triIndex = triIndex + 1;
                }
            })
                                        );

            return(imageBuffer.ToArray());
        }
Example #2
0
        public Color[] Render()
        {
            //cleanup from previous renders
            ImageBuffer = Enumerable.Repeat(fillColor, Width * Height).ToArray();
            DepthBuffer = Enumerable.Repeat(10000.0, Width * Height).ToArray();

            this.Scene.ToList().ForEach(group =>
                                        group.ToList().ForEach(renderable =>
            {
                //for now only one shader.
                var material = renderable.material;

                //render
                var triIndex = 0;
                foreach (var triFace in renderable.RenderableObject.Triangles)
                {
                    // Console.WriteLine($"{triIndex} out of {renderable.RenderableObject.Triangles.Count}");
                    //transform verts to screenspace
                    var screenCoords   = new List <Vector3>();
                    var localVertIndex = 0;
                    foreach (var meshVertInde in triFace.vertIndexList)
                    {
                        var vect = material.Shader.VertexToFragment(renderable.RenderableObject, triIndex, localVertIndex);

                        //if outside clip bounds, we will mark the vert NAN.

                        /* if (scaledX < 0 || scaledX > Width || scaledY < 0 || scaledY > Height)
                         * {
                         *   screenCoords.Add(new Vector3(float.NaN, float.NaN, float.NaN));
                         * }
                         * else
                         */
                        {
                            screenCoords.Add(new Vector3(vect.X, vect.Y, vect.Z));
                        }

                        localVertIndex++;
                    }
                    //draw if not nan.
                    //todo - logic is a bit backward.
                    //  if (screenCoords.All(x => !float.IsNaN(x.X)))
                    {
                        TriangleExtensions.drawTriangle(triIndex, screenCoords.ToArray(), material, DepthBuffer, ImageBuffer, Width);
                    }
                    triIndex = triIndex + 1;
                }
            })
                                        );

            return(ImageBuffer.ToArray());
        }
Example #3
0
        public Color[] Render()
        {
            if (VertexData == null)
            {
                throw new Exception($"{nameof(VertexData)} must be set before calling render");
            }

            //cache conversion of all verts to 2d -
            var Verts2d = VertexData.Select(x => x.ToVector2()).ToArray();

            //fill depth buffer

            this.Scene.ToList().ForEach(trigroup =>
            {
                trigroup.ToList().ForEach(tri =>
                {
                    Console.WriteLine(tri);
                    //all position data will be unchanged and unscaled.
                    //TODO except maybe invert the y?
                    var A = VertexData[tri.vertIndexList[0] - 1];
                    var B = VertexData[tri.vertIndexList[1] - 1];
                    var C = VertexData[tri.vertIndexList[2] - 1];

                    var verts = new List <Vector3>()
                    {
                        A, B, C
                    };
                    //calculate bounding box and iterate all pixels within.
                    var minx = verts.Select(x => x.X).Min();
                    var miny = verts.Select(x => x.Y).Min();
                    var maxx = verts.Select(x => x.X).Max();
                    var maxy = verts.Select(x => x.Y).Max();

                    Console.WriteLine($"{minx},{miny}    {maxx},{maxy}");

                    Enumerable.Range((int)minx, (int)(maxx - minx) + 2).ToList().ForEach(x =>
                    {
                        Enumerable.Range((int)miny, (int)(maxy - miny) + 2).ToList().ForEach(y =>
                        {
                            var IsInsideTriangle = TriangleExtensions.pixelIsInsideTriangle(x, y, tri, VertexData);

                            var bary = TriangleExtensions.BaryCoordinates2(x, y, tri, Verts2d);
                            //compute the depth of current pixel.
                            var z = bary.X * A.Z + bary.Y * B.Z + bary.Z * C.Z;


                            var AB    = Vector3.Subtract(A, B);
                            var AC    = Vector3.Subtract(A, C);
                            var ABXAC = Vector3.Normalize(Vector3.Cross(AB, AC));


                            if (IsInsideTriangle)
                            {
                                var flatIndex = Width * (int)y + (int)x;
                                //don't draw unless we are within bounds
                                //don't draw if something is already in the depth buffer for this pixel.
                                if (flatIndex <= imageBuffer.Length && flatIndex > -1 /*&& z < depthBuffer[flatIndex]*/)
                                {
                                    //only draw if nothing else is closer in the depth buffer
                                    if (z < depthBuffer[flatIndex])
                                    {
                                        //adjust color here.
                                        var normalDotLightVector = Vector3.Dot(ABXAC, new Vector3(1.0f, 0f, 0f));
                                        //if (normalDotLightVector < 0)
                                        //{
                                        //    return;
                                        //}
                                        var diffuseCoef = (float)(Math.Max(normalDotLightVector, 0.3));
                                        //don't draw pixels which are facing directly away from camera.


                                        imageBuffer[flatIndex] = Color.FromArgb((int)(diffuseCoef * 255), (int)(diffuseCoef * 255), (int)(diffuseCoef * 255));
                                        depthBuffer[flatIndex] = z;
                                    }
                                }
                            }
                        });
                    });
                });
            });

            return(imageBuffer);
        }