美文网首页unityShader
[Unity 3D] UGUI 实现超赞 Win10 日历悬停效

[Unity 3D] UGUI 实现超赞 Win10 日历悬停效

作者: 雨落随风 | 来源:发表于2024-05-26 02:18 被阅读0次

    在本文,笔者将教你如何使用 UGUI 和 Shader 实现 Window10 日历中鼠标悬停时的效果。

    预览

    实现

    1. Shader 实现

    这种动效的核心思路是将鼠标光标的位置传递到 shader 中,根据当前像素到光标的距离处理该像素的颜色值,这个动作需要拆分分为背景 + 边框两部分使用 2 个 Pass 处理。

    1.1 Background Pass

                fixed4 frag (v2f i) : SV_Target
                {
                    fixed4 col = tex2D(_MainTex, i.uv);
                    float dis = distance(_MousePos.xy, i.vertex.xy);
                    float4 addColor = _Color;
                    addColor.a = saturate(smoothstep(_ColorRadius, 0, dis) - _ColorOffset * sign(col.a-0.1));
                    addColor.a =  addColor.a * col.a * _ColorPow;
                    return addColor;
                }
    

    1.2 Border Pass

                fixed4 frag (v2f i) : SV_Target
                {
                    fixed4 col = tex2D(_BorderTex, i.uvBorder);
    
                    float dis = distance(_MousePos.xy, i.vertexBorder.xy);
                    
                    col = col + sign(col.a) * smoothstep(_ColorRadius, 0, dis) * _Color * _BorderPow;
                    return col;
                }
    

    1.3 完整 Shader 代码

    详见仓库

    2. 脚本实现

    脚本实现就相当的简单了,直接实时的将鼠标位置传递到 shader 中即可,当然点击按钮时光斑晕开的效果也着实增添了不少代码量。

    using System;
    using System.Collections;
    using UnityEngine;
    using UnityEngine.EventSystems;
    using UnityEngine.UI;
    public class UIHoverLight : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
    {
        private Material material;
        private void Start()
        {
            var image = GetComponent<Image>();
            //create a new one as we need change color offset later but should not change the others
            material = new(image.material);
            image.material = material;
        }
        private void Update() => material.SetVector("_MousePos", Input.mousePosition);
    
        Coroutine coroutine;
        void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
        {
            if (null != coroutine)
            {
                StopCoroutine(coroutine);
            }
            if (null != coroutine_hide) 
            {
                StopCoroutine(coroutine_hide);
            }
            coroutine = StartCoroutine(ChangeInnerColorStateAsync(0.3f, true));
        }
    
        // 当 _ColorOffset = 0 显示内部颜色
        private IEnumerator ChangeInnerColorStateAsync(float duration, bool show)
        {
            #region Ease
            static float inCubic(float t) => t * t * t;
            static float outCubic(float t) => inCubic(t - 1f) + 1f;
            #endregion
    
            float time = 0;
            float start = material.GetFloat("_ColorOffset");
            float end = show ? 0 : 0.98f;
            Func<float, float> ease = show ? outCubic : inCubic;
            while (time < duration)
            {
                time += Time.deltaTime;
                var p = ease(time / duration);
                material.SetFloat("_ColorOffset", Mathf.Lerp(start, end, p));
                yield return null;
            }
        }
        Coroutine coroutine_hide;
        void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
        {
            if (null != coroutine_hide)
            {
                StopCoroutine(coroutine_hide);
            }
            coroutine_hide = StartCoroutine(HideInnerColorAsync());
        }
        private IEnumerator HideInnerColorAsync()
        {
            //等待ShowInnerColorAsync结束
            if (null != coroutine)
            {
                yield return coroutine;
            }
            coroutine_hide = StartCoroutine(ChangeInnerColorStateAsync(0.1f, false));
        }
    }
    

    3. 后期特效

    为了更好的实现 UI 的辉光效果,我们需要以下 3 个核心要素:

    • 首先 Canvas 渲染模式使用:Screen Space - Camera 的渲染模式
    • 其次使用 ColorUsageAttribute 声明了 color 字段用于提供 HDR 设定。
    [SerializeField, ColorUsage(true, true)]
    private Color color = Color.white;
    
    • 最后,安装 PostProcessing 并启用 Bloom 效果就好啦~~

    结语

    本文也是本着做小抄的目的撰写,灵感甚至源码都源自于这里,欢迎在留言区交流~
    本文地址:https://github.com/Bian-Sh/UGUI-Hover-Light-Effect

    相关文章

      网友评论

        本文标题:[Unity 3D] UGUI 实现超赞 Win10 日历悬停效

        本文链接:https://www.haomeiwen.com/subject/jpwfqjtx.html