Ejemplo n.º 1
0
        //Divide primitives into triangles
        private void TriangulatePrimitives(ref DrawCall drawCall)
        {
            var primitives = new List <Primitive>();

            foreach (var item in drawCall.Primitives)
            {
                //ignore the primitive that was cliped
                if (item.Vertics.Length == 0)
                {
                    continue;
                }

                //we select a vertex to make triangulate
                var importantVertex = item.Vertics[0];

                //we can know the number of triangles is (item.Vertics.Length - 2)
                for (int i = 0; i < item.Vertics.Length - 2; i++)
                {
                    var vertics = new UnitProperty[3];

                    //new triangle
                    vertics[0] = importantVertex;
                    vertics[1] = item.Vertics[i + 1];
                    vertics[2] = item.Vertics[i + 2];

                    //normalize the ordering(counter-clockwise)
                    Utility.NormalizeOrdering(ref vertics);

                    //add it
                    primitives.Add(new Primitive(vertics));
                }
            }

            drawCall.Primitives = primitives.ToArray();
        }
Ejemplo n.º 2
0
        public void Subtract(UnitProperty unitProperty)
        {
            color               -= unitProperty.color;
            depth               -= unitProperty.depth;
            position            -= unitProperty.position;
            positionTransformed -= unitProperty.positionTransformed;

            positionAfterDivide = positionTransformed / positionTransformed.W;
        }
Ejemplo n.º 3
0
        public void Add(UnitProperty unitProperty)
        {
            color               += unitProperty.color;
            depth               += unitProperty.depth;
            position            += unitProperty.position;
            positionTransformed += unitProperty.positionTransformed;

            positionAfterDivide = positionTransformed / positionTransformed.W;
        }
Ejemplo n.º 4
0
        public PixelProperty(UnitProperty baseProperty, Vector2 location)
        {
            unitProperty = baseProperty;

            Location = location;
        }
Ejemplo n.º 5
0
 protected virtual object OnProcessUnit(ref UnitProperty unitProperty, params object[] inputData)
 {
     return(Vector4.Zero);
 }
Ejemplo n.º 6
0
 internal void StartProcessUnit(ref UnitProperty unitProperty, params object[] inputData)
 {
     ProcessUnit.Invoke(ref unitProperty, inputData);
 }
Ejemplo n.º 7
0
        private void RasterizerPrimitives(ref DrawCall drawCall)
        {
            List <PixelProperty> pixels = new List <PixelProperty>();

            var renderTarget = GraphicsPipeline.OutputMergerStage.RenderTarget;

            //for each primitives(triangles)
            //and the primitives are counter-clockwise.
            foreach (var primitive in drawCall.Primitives)
            {
                //bounding box = (left, top, right, bottom)
                Vector4 boundingBox = new Vector4(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);

                //create triangle
                Vector2[] triangle = new Vector2[3];

                int index = 0;

                //enum the vertex
                foreach (var vertex in primitive.Vertics)
                {
                    //compute the bounding box
                    boundingBox.X = Math.Min(boundingBox.X, vertex.PositionAfterDivide.X);
                    boundingBox.Y = Math.Min(boundingBox.Y, vertex.PositionAfterDivide.Y);
                    boundingBox.Z = Math.Max(boundingBox.Z, vertex.PositionAfterDivide.X);
                    boundingBox.W = Math.Max(boundingBox.W, vertex.PositionAfterDivide.Y);

                    //make triangle data and convert it to the render target
                    //the range of point in the ndc space is [-1 ,1]
                    //so the point in the screen is (point + 1) * size * 0.5f
                    triangle[index] = new Vector2(
                        (primitive.Vertics[index].PositionAfterDivide.X + 1) * renderTarget.Width * 0.5f,
                        (primitive.Vertics[index].PositionAfterDivide.Y + 1) * renderTarget.Height * 0.5f);

                    index++;
                }

                //convert the boundingBox to the render target
                boundingBox.X = (float)Math.Floor((boundingBox.X + 1) * renderTarget.Width * 0.5f);
                boundingBox.Y = (float)Math.Floor((boundingBox.Y + 1) * renderTarget.Height * 0.5f);
                boundingBox.Z = (float)Math.Ceiling((boundingBox.Z + 1) * renderTarget.Width * 0.5f);
                boundingBox.W = (float)Math.Ceiling((boundingBox.W + 1) * renderTarget.Height * 0.5f);

                //for the float
                boundingBox.X = Utility.Limit(boundingBox.X, 0, renderTarget.Width);
                boundingBox.Y = Utility.Limit(boundingBox.Y, 0, renderTarget.Height);
                boundingBox.Z = Utility.Limit(boundingBox.Z, 0, renderTarget.Width);
                boundingBox.W = Utility.Limit(boundingBox.W, 0, renderTarget.Height);

                //get the triangle's area
                //we do not need to divide 2
                float triangleArea = MathHelper.AreaFunction(triangle[0], triangle[1], triangle[2]);

                //make the UnitProperties for computing the pixel's unitProperty
                //rule: P = z * (P0 / z0 * e0 + P1 / z1 * e1 + P2 / z2 * e2)
                //e0 + e1 + e2 = 1
                var unitProperties = new UnitProperty[3];

                unitProperties[0] = primitive.Vertics[0] / primitive.Vertics[0].PositionTransformed.Z;
                unitProperties[1] = primitive.Vertics[1] / primitive.Vertics[1].PositionTransformed.Z;
                unitProperties[2] = primitive.Vertics[2] / primitive.Vertics[2].PositionTransformed.Z;

                //make the invert z to compute the pixel's invert z
                //rule: Z = 1 / (1 / z0 * e0 + 1 / z1 * e1 + 1 / z2 * e2)
                var triangleInvertZ = new float[3];

                triangleInvertZ[0] = 1.0f / primitive.Vertics[0].PositionTransformed.Z;
                triangleInvertZ[1] = 1.0f / primitive.Vertics[1].PositionTransformed.Z;
                triangleInvertZ[2] = 1.0f / primitive.Vertics[2].PositionTransformed.Z;

                //enum the pixel
                for (int x = (int)boundingBox.X; x <= boundingBox.Z; x++)
                {
                    for (int y = (int)boundingBox.Y; y <= boundingBox.W; y++)
                    {
                        //0.5f offset, because we will use the center of pixel
                        var pixel = new Vector2(x + 0.5f, y + 0.5f);

                        //compute the area(ratio) about sub-triangle
                        float subArea0 = MathHelper.AreaFunction(triangle[1], triangle[2], pixel) / triangleArea;
                        float subArea1 = MathHelper.AreaFunction(triangle[2], triangle[0], pixel) / triangleArea;
                        float subArea2 = MathHelper.AreaFunction(triangle[0], triangle[1], pixel) / triangleArea;

                        if (subArea0 < 0 || subArea1 < 0 || subArea2 < 0)
                        {
                            continue;
                        }

                        //compute the property
                        UnitProperty pixelProperty
                            = unitProperties[0] * subArea0 + unitProperties[1] * subArea1 + unitProperties[2] * subArea2;

                        float invertZ = 1.0f / (triangleInvertZ[0] * subArea0 + triangleInvertZ[1] * subArea1 + triangleInvertZ[2] * subArea2);

                        pixelProperty = pixelProperty * invertZ;

                        //accept the pixel
                        pixels.Add(new PixelProperty(pixelProperty, new Vector2(x, y)));
                    }
                }
            }

            //get the pixels
            drawCall.Pixels = pixels.ToArray();
        }
Ejemplo n.º 8
0
        //Clip the edge with a face
        private static UnitProperty ClipEdge(UnitProperty start, UnitProperty end, FrustumFace faceIndex)
        {
            float t = 0;

            //vector = end - start
            var vector = end - start;

            // result = start + (end - start) * t
            switch (faceIndex)
            {
            case FrustumFace.Left:
                // (start.x + vector.x * t) / (start.w + vector.w * t) = -1
                // t = -(start.x + start.w) / (vector.x + vector.w)
                // and (vector.x + vector.w) != 0
                // because there is most one vertex on the face(x = -w), so (vector.x + vector.w) = (end.x - start.x + end.w - start.w) != 0

                t = -(start.PositionTransformed.X + start.PositionTransformed.W) /
                    (vector.PositionTransformed.X + vector.PositionTransformed.W);

                break;

            case FrustumFace.Right:
                // (start.x + vector.x * t) / (start.w + vector.w * t) = 1
                // t = (start.w - start.x) / (vector.x - vector.w)
                // and (vector.x - vector.w) != 0
                // because there is most one vertex on the face(x = w), so (vector.x - vector.w) = (end.x - start.x - end.w + start.w) != 0

                t = (start.PositionTransformed.W - start.PositionTransformed.X) /
                    (vector.PositionTransformed.X - vector.PositionTransformed.W);

                break;

            case FrustumFace.Bottom:
                // (start.y + vector.y * t) / (start.w + vector.w * t) = -1
                // t = (start.y + start.w) / (vector.y + vector.w)
                // and (vector.y + vector.w) != 0
                // because there is most one vertex on the face(y = -w), so (vector.y + vector.w) = (end.y - start.y + end.w - start.w) != 0

                t = -(start.PositionTransformed.Y + start.PositionTransformed.W) /
                    (vector.PositionTransformed.Y + vector.PositionTransformed.W);

                break;

            case FrustumFace.Top:
                // (start.y + vector.y * t) / (start.w + vector.w * t) = 1
                // t = (start.w - start.y) / (vector.y - vector.w)
                // and (vector.y - vector.w) != 0
                // because there is most one vertex on the face(y = w), so (vector.y - vector.w) = (end.y - start.y - end.w + start.w) != 0

                t = (start.PositionTransformed.W - start.PositionTransformed.Y) /
                    (vector.PositionTransformed.Y - vector.PositionTransformed.W);

                break;

            case FrustumFace.Near:
                // (start.z + vector.z * t) / (start.w + vector.w * t) = 0
                // t = - (start.z / vector.z)
                // and vector.z != 0
                // because there is most one vertex on the face(z = 0), so vector.z = (end.z - start.z) != 0

                t = -(start.PositionTransformed.Z / vector.PositionTransformed.Z);

                break;

            case FrustumFace.Far:
                // (start.z + vector.z * t) / (start.w + vector.w * t) = 1
                // t = (start.w - start.z) / (vector.z - vector.w)
                // and (vector.z - vector.w) != 0
                // because there is most one vertex on the face(z = w), so (vector.z - vector.w) = (end.z - start.z - end.w + start.w) != 0

                t = (start.PositionTransformed.W - start.PositionTransformed.Z) /
                    (vector.PositionTransformed.Z - vector.PositionTransformed.W);

                break;

            default:
                break;
            }

            var result = start + vector * t;

            //divide for the new vertex
            result.PositionAfterDivide = result.PositionTransformed / result.PositionTransformed.W;

            return(result);
        }
Ejemplo n.º 9
0
 protected virtual void OnProcessUnit(ref UnitProperty unitProperty, object vertex, params object[] inputData)
 {
     //
 }