Unity用Shader实现矩形mesh的边框,同时边框可以近大远小

这个shader原本是用做项目中矩形物体的描边,因为项目中需要描边的物体都是矩形面片,而且比较多,所以用这个比一般的描边插件要节省性能

近大远小的原理就是,计算相机空间下物体的中心的点和摄像机的距离,然后与描边宽度做权重算法

ShortSide是矩形的短边长度
SideRatio是矩形的宽高比(width/height)

下面是shader代码:

Shader "UnlitEdge" {
    Properties{
        _Color("Main Color", Color) = (1,1,1,1)
        _OutlineColor("Outline Color", Color) = (1,1,1,1)
        _Outline("Outline Width", Range(0.001, 0.01)) = 0.005
        _ShortSide("Short Side", Float) = 1
        _SideRatio("SideRatio", Float) = 1
    }

        SubShader{
                Tags {"Queue" = "Transparent" "Queue" = "Overlay" }
                LOD 200
                ZTest Always
                Cull Off
                Cull Back
                Blend SrcAlpha OneMinusSrcAlpha

            Pass {
                CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #pragma target 2.0

                    #include "UnityCG.cginc"

                    struct appdata_t {
                        float4 vertex : POSITION;
                        float2 texcoord : TEXCOORD0;
                        UNITY_VERTEX_INPUT_INSTANCE_ID
                    };

                    struct v2f {
                        float4 vertex : SV_POSITION;
                        float2 texcoord : TEXCOORD0;
                        float4 color : COLOR;
                        UNITY_VERTEX_OUTPUT_STEREO
                    };

                    float4 _Color;
                    float4 _OutlineColor;
                    float _Outline;
                    float _ShortSide;
                    float _SideRatio;

                    v2f vert(appdata_t v)
                    {
                        v2f o;
                        UNITY_SETUP_INSTANCE_ID(v);
                        UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                        o.vertex = UnityObjectToClipPos(v.vertex);
                        o.texcoord = v.texcoord;
                        return o;
                    }

                    fixed4 frag(v2f i) : SV_Target
                    {
                        float3 center = float3(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23);
                        float dist = distance(_WorldSpaceCameraPos, center);
                        dist = clamp(dist / _ShortSide, 1, 50);
                        float widthX = dist * _Outline;
                        float widthY = widthX * _SideRatio;
                        if (i.texcoord.x < widthX || i.texcoord.y < widthY || i.texcoord.x >1 - widthX || i.texcoord.y > 1 - widthY)
                        {
                            i.color = _OutlineColor;
                        }
                        else 
                        {
                            i.color = _Color;
                        }
                        return i.color;
                    }
                ENDCG
            }
        }
}

参考的文章:

https://blog.csdn.net/MonoBehaviour/article/details/82707795

https://blog.csdn.net/alla_Candy/article/details/129751758

https://blog.csdn.net/weixin_43933605/article/details/103815167

https://zhuanlan.zhihu.com/p/535452034

posted @ 2023-08-21 17:26  zerozabuu  阅读(58)  评论(0编辑  收藏  举报