# 【多边形描边】

根据若干个坐标点,生成多边形描边。

全屏显示

PolygonEdgeShader.shader

Shader "Unlit/PolygonEdgeShader"
{
    Properties
    {
        _Point1 ("Point1", Vector) =  (0.5,0.319336,0,0)
        _Point2 ("Point2", Vector) =  (0.691406,0.457031,0,0)
        _Point3 ("Point3", Vector) =  (0.618164,0.679688,0,0)
        _Point4 ("Point4", Vector) =  (0.380859,0.679688,0,0)
        _Point5 ("Point5", Vector) =  (0.308594,0.457031,0,0)
        _Edge("Edge", Range(0,0.1)) = 0.0042
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            uniform float4 _Point1;
            uniform float4 _Point2;
            uniform float4 _Point3;
            uniform float4 _Point4;
            uniform float4 _Point5;
            uniform float _Edge;
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            // p0 点的位置
            // startPoint 线段开始点坐标
            // endPoint 线段结束点坐标
            float getDistance(float2 p0, float2 startPoint, float2 endPoint)
            {
                float2 lineDir = normalize(endPoint - startPoint); //线段的方向向量 
                float2 p0ToStart = p0 - startPoint; // p0到起始点的向量
                // 计算垂直于线段方向向量的向量
                float2 perpendicularVector = float2(-lineDir.y, lineDir.x);
                // 计算距离
                float distance = abs(dot(p0ToStart, perpendicularVector));
                return distance;
            }

            // 检查UV点是否位于多边形描边部分,是返回1,否返回0
            float checkIsPolygonEdge(float2 st)
            {
                float2 p1 = _Point1.xy;
                float2 p2 = _Point2.xy;
                float2 p3 = _Point3.xy;
                float2 p4 = _Point4.xy;
                float2 p5 = _Point5.xy;
                float edge = _Edge;
                float d1 = getDistance(st, p1,p2);
                float d2 = getDistance(st, p2,p3);
                float d3 = getDistance(st, p3,p4);
                float d4 = getDistance(st, p4,p5);
                float d5 = getDistance(st, p5,p1);

                if(d1 < edge){
                    float d1len = distance(p1,p2);
                    float max1len = max(distance(p1,st),distance(p2,st));
                    if(max1len < d1len)
                    {
                        return 1;
                    }
                }

                if(d2 < edge){
                    float d2len = distance(p2,p3);
                    float max2len = max(distance(p2,st),distance(p3,st));
                    if(max2len < d2len)
                    {
                        return 1;
                    }
                }

                if(d3 < edge){
                    float d3len = distance(p3,p4);
                    float max3len = max(distance(p3,st),distance(p4,st));
                    if(max3len < d3len)
                    {
                        return 1;
                    }
                }

                if(d4 < edge){
                    float d4len = distance(p4,p5);
                    float max4len = max(distance(p4,st),distance(p5,st));
                    if(max4len < d4len)
                    {
                        return 1;
                    }
                }

                if(d5 < edge){
                    float d5len = distance(p5,p1);
                    float max5len = max(distance(p5,st),distance(p1,st));
                    if(max5len < d5len)
                    {
                        return 1;
                    }
                }

                return 0;
            }

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float result = checkIsPolygonEdge(i.uv);
                return result;
            }
            ENDCG
        }
    }
}