• Shader实现新手指引挖空圆形和矩形


    Shader "UI/ImageWithHole"
    {
        Properties
        {
            [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
            _TintColor ("Tint", Color) = (1,1,1,1)
    
            _StencilComp ("Stencil Comparison", Float) = 8
            _Stencil ("Stencil ID", Float) = 0
            _StencilOp ("Stencil Operation", Float) = 0
            _StencilWriteMask ("Stencil Write Mask", Float) = 255
            _StencilReadMask ("Stencil Read Mask", Float) = 255
    
            [KeywordEnum(ROUND, RECTANGLE, NULL)] _MaskMode("Mask mode", Float) = 0
            _Center("Center", vector) = (0, 0, 0, 0)
            _Radius("Radius", Range(0,1000)) = 100 // 圆半径
            _RectangleSize("Rectangle Size", vector) = (0, 0, 0, 0) // 矩形边长
            _TransitionRange("Transition Range", Range(0, 100)) = 10
        }
    
        SubShader
        {
            Tags
            {
                "Queue"="Transparent"
                "IgnoreProjector"="True"
                "RenderType"="Transparent"
                "PreviewType"="Plane"
                "CanUseSpriteAtlas"="True"
            }
    
            Stencil
            {
                Ref [_Stencil]
                Comp [_StencilComp]
                Pass [_StencilOp]
                ReadMask [_StencilReadMask]
                WriteMask [_StencilWriteMask]
            }
    
            Cull Off
            Lighting Off
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            ColorMask RGBA
    
            Pass
            {
                Name "Default"
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 2.0
    
                #include "UnityCG.cginc"
                #include "UnityUI.cginc"
    
                #pragma multi_compile __ UNITY_UI_CLIP_RECT
                #pragma multi_compile __ UNITY_UI_ALPHACLIP
                #pragma multi_compile _MASKMODE_ROUND _MASKMODE_RECTANGLE _MASKMODE_NULL
    
                struct appdata_t
                {
                    float4 vertex   : POSITION;
                    float4 color    : COLOR;
                    float2 texcoord : TEXCOORD0;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };
    
                struct v2f
                {
                    float4 vertex   : SV_POSITION;
                    fixed4 color    : COLOR;
                    float2 texcoord  : TEXCOORD0;
                    float4 worldPosition : TEXCOORD1;
                    UNITY_VERTEX_OUTPUT_STEREO
                };
    
                fixed4 _TintColor;
                fixed4 _TextureSampleAdd;
                float4 _ClipRect;
                float2 _Center;
                half _Radius;
                float2 _RectangleSize;
                half _TransitionRange;
    
                v2f vert(appdata_t v)
                {
                    v2f OUT;
                    UNITY_SETUP_INSTANCE_ID(v);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                    OUT.worldPosition = v.vertex;
                    OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
    
                    OUT.texcoord = v.texcoord;
    
                    OUT.color = v.color * _TintColor;
                    return OUT;
                }
    
                sampler2D _MainTex;
    
                fixed4 frag(v2f i) : SV_Target
                {
                    half4 color = (tex2D(_MainTex, i.texcoord) + _TextureSampleAdd) * i.color;
    
                    #ifdef UNITY_UI_CLIP_RECT
                    color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                    #endif
    
                    #ifdef UNITY_UI_ALPHACLIP
                    clip (color.a - 0.001);
                    #endif
    
                    #ifdef _MASKMODE_ROUND
                        // 计算片元世界坐标和目标中心位置的距离
                        half dis = distance(i.worldPosition.xy, _Center.xy);
                        // 过滤掉距离小于(半径-过渡范围)的片元
                        clip(dis - (_Radius - _TransitionRange));
                        // 是否在圆里面
                        int inside = step(dis, _Radius);
                        // 计算过渡范围内的alpha值
                        color.a *= (1 - inside) + inside * (dis - (_Radius - _TransitionRange)) / _TransitionRange;
                    #elif _MASKMODE_RECTANGLE
                        // 计算片元世界坐标和目标中心位置的距离
                        half disX = distance(i.worldPosition.x, _Center.x);
                        half disY = distance(i.worldPosition.y, _Center.y);
                        // x决定像素点应该去掉返回1,不去掉返回0
                        int clipX = step(disX, _RectangleSize.x-_TransitionRange);
                        int clipY = step(disY, _RectangleSize.y-_TransitionRange);
                        clip(disX - (_RectangleSize.x -_TransitionRange) * clipY);
                        clip(disY - (_RectangleSize.y -_TransitionRange) * clipX);
    
                        // x在范围内返回1,不在范围内返回0
                        int insideX = step(disX, _RectangleSize.x);
                        int insideY = step(disY, _RectangleSize.y);
                        half alphaX= (1 - insideX) + insideX * (disX - (_RectangleSize.x - _TransitionRange)) / _TransitionRange;
                        half alphaY= (1 - insideY) + insideY * (disY - (_RectangleSize.y - _TransitionRange)) / _TransitionRange;
                        color.a *= max(alphaX, alphaY);
                    #endif
                    return color;
                }
            ENDCG
            }
        }
    }
  • 相关阅读:
    1077. 互评成绩计算 (20)
    1076. Wifi密码 (15)
    c语言之利用指针复制字符串的几种形式
    c语言之利用函数实现字符串的复制
    c语言之字符串中字符的存取方法
    E0144"const char *" 类型的值不能用于初始化 "char *" 类型的实体的三种解决方法
    c语言之使用指针*和地址&在二维数组中表示的含义
    c语言之指向二维数组元素的指针变量
    c语言之在函数内部改变数组的值从而影响外部数组的四种方式
    c语言之使用指针将数组进行反转
  • 原文地址:https://www.cnblogs.com/DonYao/p/11766527.html
Copyright © 2020-2023  润新知