Example #1
0
    public void Generate()
    {
        float lightSize = 1000;

        float dirX = Mathf.Cos(edgeRotation) * edgeSize;
        float dirY = Mathf.Sin(edgeRotation) * edgeSize;

        leftEdgeLocal  = new Vector2(dirX, dirY);
        rightEdgeLocal = new Vector2(-dirX, -dirY);

        leftEdge  = leftEdgeLocal + edgePosition;
        rightEdge = rightEdgeLocal + edgePosition;

        // left outer
        leftOuterCore = Mathf.Atan2(leftEdge.y, leftEdge.x) + Mathf.PI / 2;;
        leftCoreOut.x = Mathf.Cos(leftOuterCore) * coreSize;
        leftCoreOut.y = Mathf.Sin(leftOuterCore) * coreSize;
        leftCoreOut.x = 0;
        leftCoreOut.y = 0;

        leftOuterToEdge      = Mathf.Atan2(leftEdge.y - leftCoreOut.y, leftEdge.x - leftCoreOut.x);
        leftCoreOutToEdge    = leftCoreOut; // middle
        leftCoreOutToEdge.x += Mathf.Cos(leftOuterToEdge) * lightSize;
        leftCoreOutToEdge.y += Mathf.Sin(leftOuterToEdge) * lightSize;

        leftInnerCore = Mathf.Atan2(leftEdge.y, leftEdge.x) - Mathf.PI / 2;;
        leftCoreIn.x  = Mathf.Cos(leftInnerCore) * coreSize;
        leftCoreIn.y  = Mathf.Sin(leftInnerCore) * coreSize;

        leftInnerToEdge     = Mathf.Atan2(leftEdge.y - leftCoreIn.y, leftEdge.x - leftCoreIn.x);
        leftCoreInToEdge    = leftCoreIn; // middle
        leftCoreInToEdge.x += Mathf.Cos(leftInnerToEdge) * lightSize;
        leftCoreInToEdge.y += Mathf.Sin(leftInnerToEdge) * lightSize;

        // right outer
        rightOuterCore = Mathf.Atan2(rightEdge.y, rightEdge.x) + Mathf.PI / 2;;
        rightCoreOut.x = Mathf.Cos(rightOuterCore) * coreSize;
        rightCoreOut.y = Mathf.Sin(rightOuterCore) * coreSize;

        rightOuterToEdge      = Mathf.Atan2(rightEdge.y - rightCoreOut.y, rightEdge.x - rightCoreOut.x);
        rightCoreOutToEdge    = rightCoreOut; // middle
        rightCoreOutToEdge.x += Mathf.Cos(rightOuterToEdge) * lightSize;
        rightCoreOutToEdge.y += Mathf.Sin(rightOuterToEdge) * lightSize;

        rightInnerCore = Mathf.Atan2(rightEdge.y, rightEdge.x) - Mathf.PI / 2;;
        rightCoreIn.x  = Mathf.Cos(rightInnerCore) * coreSize;
        rightCoreIn.y  = Mathf.Sin(rightInnerCore) * coreSize;
        rightCoreIn.x  = 0;
        rightCoreIn.y  = 0;


        rightInnerToEdge     = Mathf.Atan2(rightEdge.y - rightCoreIn.y, rightEdge.x - rightCoreIn.x);
        rightCoreInToEdge    = rightCoreIn; // middle
        rightCoreInToEdge.x += Mathf.Cos(rightInnerToEdge) * lightSize;
        rightCoreInToEdge.y += Mathf.Sin(rightInnerToEdge) * lightSize;



        edgeMiddle = (leftEdge + rightEdge) / 2;

        Vector2 closestPoint = Math2D.ClosestPointOnLine(Vector2.zero, leftCoreOutToEdge, rightCoreInToEdge);
        float   rotM         = (float)System.Math.Atan2(closestPoint.y, closestPoint.x);

        projectedMiddle.x = (leftEdge.x + rightEdge.x) / 2 + Mathf.Cos(rotM) * lightSize;
        projectedMiddle.y = (leftEdge.y + rightEdge.y) / 2 + Mathf.Sin(rotM) * lightSize;
    }
Example #2
0
        public static void Draw(List <Polygon2> polygons, float distance, float translucency)
        {
            if (polygons == null)
            {
                return;
            }

            Light2D light    = ShadowEngine.light;
            Vector2 position = ShadowEngine.lightOffset + ShadowEngine.objectOffset;

            float shadowDistance = ShadowEngine.lightSize;

            float outerAngle = light.outerAngle;
            bool  drawInside = (ShadowEngine.lightDrawAbove == false);
            bool  culling    = true;

            UVRect penumbraRect = ShadowEngine.Penumbra.uvRect;
            UVRect fillRect     = ShadowEngine.FillBlack.uvRect;

            float angleA, angleB;
            float rotA, rotB, rotM;

            Vector2 middle = Vector2.zero;

            int PolygonCount = polygons.Count;

            Vector2 draw = ShadowEngine.drawOffset;

            if (translucency > 0)
            {
                GL.Color(new Color(0, 0, 0, 1 - translucency));

                fillRect   = ShadowEngine.FillWhite.uvRect;
                outerAngle = 0;
            }

            if (distance > 0)
            {
                shadowDistance = distance;
                outerAngle     = 0;
                culling        = false;
            }

            for (int i = 0; i < PolygonCount; i++)
            {
                Vector2[] pointsList  = polygons[i].points;
                int       pointsCount = pointsList.Length;

                for (int x = 0; x < pointsCount; x++)
                {
                    int next = (x + 1) % pointsCount;

                    pair.A = pointsList[x];
                    pair.B = pointsList[next];

                    edgeALocal.x = pair.A.x;
                    edgeALocal.y = pair.A.y;

                    edgeBLocal.x = pair.B.x;
                    edgeBLocal.y = pair.B.y;

                    edgeAWorld.x = edgeALocal.x + position.x;
                    edgeAWorld.y = edgeALocal.y + position.y;

                    edgeBWorld.x = edgeBLocal.x + position.x;
                    edgeBWorld.y = edgeBLocal.y + position.y;

                    closestPoint = Math2D.ClosestPointOnLine(middle, edgeAWorld, edgeBWorld);
                    if (Vector2.Distance(middle, closestPoint) > light.size)
                    {
                        continue;
                    }

                    float lightDirection = (float)Math.Atan2((edgeAWorld.y + edgeBWorld.y) / 2, (edgeAWorld.x + edgeBWorld.x) / 2) * Mathf.Rad2Deg;
                    float EdgeDirection  = (float)Math.Atan2(edgeALocal.y - edgeBLocal.y, edgeALocal.x - edgeBLocal.x) * Mathf.Rad2Deg - 180;

                    lightDirection -= EdgeDirection;
                    lightDirection  = (lightDirection + 720) % 360;

                    if (culling && drawInside == false)
                    {
                        if (lightDirection < 180)
                        {
                            continue;
                        }
                    }

                    angleA = (float)System.Math.Atan2(edgeAWorld.y, edgeAWorld.x);
                    angleB = (float)System.Math.Atan2(edgeBWorld.y, edgeBWorld.x);

                    projectedRight.x = edgeAWorld.x + Mathf.Cos(angleA) * shadowDistance;
                    projectedRight.y = edgeAWorld.y + Mathf.Sin(angleA) * shadowDistance;

                    projectedLeft.x = edgeBWorld.x + Mathf.Cos(angleB) * shadowDistance;
                    projectedLeft.y = edgeBWorld.y + Mathf.Sin(angleB) * shadowDistance;

                    if (outerAngle > 0)
                    {
                        rotA = angleA - Mathf.Deg2Rad * light.outerAngle;
                        rotB = angleB + Mathf.Deg2Rad * light.outerAngle;

                        outerRight.x = edgeAWorld.x + Mathf.Cos(rotA) * shadowDistance;
                        outerRight.y = edgeAWorld.y + Mathf.Sin(rotA) * shadowDistance;

                        outerLeft.x = edgeBWorld.x + Mathf.Cos(rotB) * shadowDistance;
                        outerLeft.y = edgeBWorld.y + Mathf.Sin(rotB) * shadowDistance;

                        // Right Penumbra
                        GL.TexCoord3(penumbraRect.x0, penumbraRect.y0, 0);
                        GL.Vertex3(draw.x + edgeAWorld.x, draw.y + edgeAWorld.y, 0);

                        GL.TexCoord3(penumbraRect.x1, penumbraRect.y0, 0);
                        GL.Vertex3(draw.x + outerRight.x, draw.y + outerRight.y, 0);

                        GL.TexCoord3(penumbraRect.x0, penumbraRect.y1, 0);
                        GL.Vertex3(draw.x + projectedRight.x, draw.y + projectedRight.y, 0);

                        // Left Penumbra
                        GL.TexCoord3(penumbraRect.x0, penumbraRect.y0, 0);
                        GL.Vertex3(draw.x + edgeBWorld.x, draw.y + edgeBWorld.y, 0);

                        GL.TexCoord3(penumbraRect.x1, penumbraRect.y0, 0);
                        GL.Vertex3(draw.x + outerLeft.x, draw.y + outerLeft.y, 0);

                        GL.TexCoord3(penumbraRect.x0, penumbraRect.y1, 0);
                        GL.Vertex3(draw.x + projectedLeft.x, draw.y + projectedLeft.y, 0);
                    }

                    // Right Fin
                    GL.TexCoord3(fillRect.x0, fillRect.y0, 0);
                    GL.Vertex3(draw.x + projectedLeft.x, draw.y + projectedLeft.y, 0);
                    GL.Vertex3(draw.x + projectedRight.x, draw.y + projectedRight.y, 0);
                    GL.Vertex3(draw.x + edgeAWorld.x, draw.y + edgeAWorld.y, 0);

                    // Left Fin
                    GL.TexCoord3(fillRect.x0, fillRect.y0, 0);
                    GL.Vertex3(draw.x + edgeAWorld.x, draw.y + edgeAWorld.y, 0);
                    GL.Vertex3(draw.x + edgeBWorld.x, draw.y + edgeBWorld.y, 0);
                    GL.Vertex3(draw.x + projectedLeft.x, draw.y + projectedLeft.y, 0);

                    closestPoint = Math2D.ClosestPointOnLine(middle, projectedLeft, projectedRight);
                    rotM         = (float)System.Math.Atan2(closestPoint.y, closestPoint.x);

                    // Detailed Shadow
                    projectedMiddle.x = (edgeAWorld.x + edgeBWorld.x) / 2 + Mathf.Cos(rotM) * shadowDistance;
                    projectedMiddle.y = (edgeAWorld.y + edgeBWorld.y) / 2 + Mathf.Sin(rotM) * shadowDistance;

                    // Middle Fin
                    GL.TexCoord3(fillRect.x0, fillRect.y0, 0);
                    GL.Vertex3(draw.x + projectedLeft.x, draw.y + projectedLeft.y, 0);
                    GL.Vertex3(draw.x + projectedRight.x, draw.y + projectedRight.y, 0);
                    GL.Vertex3(draw.x + projectedMiddle.x, draw.y + projectedMiddle.y, 0);
                }
            }

            if (translucency > 0)
            {
                GL.Color(Color.white);
            }
        }