zoukankan      html  css  js  c++  java
  • 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
            }
        }
    }
  • 相关阅读:
    通过HttpListener实现简单的Http服务
    WCF心跳判断服务端及客户端是否掉线并实现重连接
    NHibernate初学六之关联多对多关系
    NHibernate初学五之关联一对多关系
    EXTJS 4.2 资料 跨域的问题
    EXTJS 4.2 资料 控件之Grid 那些事
    EXTJS 3.0 资料 控件之 GridPanel属性与方法大全
    EXTJS 3.0 资料 控件之 Toolbar 两行的用法
    EXTJS 3.0 资料 控件之 combo 用法
    EXTJS 4.2 资料 控件之 Store 用法
  • 原文地址:https://www.cnblogs.com/DonYao/p/11766527.html
Copyright © 2011-2022 走看看