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()); }
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()); }
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); }