• Shader实例:扭曲,漩涡


    效果:

    案例:新仙剑,王者之剑。
    在切换场景的时候,就会有这样的全屏扭曲效果。

    思路:
    1.用GrabPass抓屏到一张纹理中。
    2.进行扭曲,绘制到UGUI的Image上。

    准备:
    去官网下载Unity内置Shader,当前最新版本:builtin_shaders-5.3.1f1
    http://unity3d.com/cn/get-unity/download/archive
    里面有Image用的默认Shader:Sprites-Default
    我们要在这个shader的基础上加上扭曲效果。

    GrabPass比较耗,加上我没有好看的场景,这里就用一张全屏的背景图进行扭曲了。
    代码中//–add 就是在原来基础上添加部分

    Shader "Custom/ImageSwirl"
    {
        Properties
        {
            [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
            _Color("Tint", Color) = (1,1,1,1)
            [MaterialToggle] PixelSnap("Pixel snap", Float) = 0
        }
     
        SubShader
        {
            Tags
            {
                "Queue" = "Transparent"
                "IgnoreProjector" = "True"
                "RenderType" = "Transparent"
                "PreviewType" = "Plane"
                "CanUseSpriteAtlas" = "True"
            }
     
            Cull Off
            Lighting Off
            ZWrite Off
            Blend One OneMinusSrcAlpha
     
     
            //-----add
            GrabPass
            {
                "_MyGrabTex"
            }
            //---------
     
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma multi_compile _ PIXELSNAP_ON
                #include "UnityCG.cginc"
     
                struct appdata_t
                {
                    float4 vertex   : POSITION;
                    float4 color    : COLOR;
                    float2 texcoord : TEXCOORD0;
                };
     
                struct v2f
                {
                    float4 vertex   : SV_POSITION;
                    fixed4 color : COLOR;
                    float2 texcoord  : TEXCOORD0;
                };
     
                fixed4 _Color;
     
                //------------add
                float _Radius;
                float _Angle;
                sampler2D _MyGrabTex;
                float2 swirl(float2 uv);
                float2 swirl(float2 uv)
                {
                    //先减去贴图中心点的纹理坐标,这样是方便旋转计算 
                    uv -= float2(0.5, 0.5);
     
                    //计算当前坐标与中心点的距离。 
                    float dist = length(uv);
     
                    //计算出旋转的百分比 
                    float percent = (_Radius - dist) / _Radius;
     
                    if (percent < 1.0 && percent >= 0.0)
                    {
                        //通过sin,cos来计算出旋转后的位置。 
                        float theta = percent * percent * _Angle * 8.0;
                        float s = sin(theta);
                        float c = cos(theta);
                        //uv = float2(dot(uv, float2(c, -s)), dot(uv, float2(s, c))); 
                        uv = float2(uv.x*c - uv.y*s, uv.x*s + uv.y*c);
                    }
     
                    //再加上贴图中心点的纹理坐标,这样才正确。 
                    uv += float2(0.5, 0.5);
     
                    return uv;
                }
                //---------------
     
                v2f vert(appdata_t IN)
                {
                    v2f OUT;
                    OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                    OUT.texcoord = IN.texcoord;
                    OUT.color = IN.color * _Color;
                    #ifdef PIXELSNAP_ON
                    OUT.vertex = UnityPixelSnap(OUT.vertex);
                    #endif
     
                    return OUT;
                }
     
                sampler2D _MainTex;
                sampler2D _AlphaTex;
                float _AlphaSplitEnabled;
     
                fixed4 SampleSpriteTexture(float2 uv)
                {
                    fixed4 color = tex2D(_MainTex, uv);
     
                    //----------modify
                    //fixed4 color = tex2D(_MyGrabTex, float2(uv.x,1-uv.y));
                    //-----------
     
     
            #if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
                    if (_AlphaSplitEnabled)
                        color.a = tex2D(_AlphaTex, uv).r;
            #endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED
     
                    return color;
                }
     
                fixed4 frag(v2f IN) : SV_Target
                {
                    //---add
                    IN.texcoord = swirl(IN.texcoord);
                    //--------
     
                    fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
                    c.rgb *= c.a;
                    return c;
                }
                ENDCG
            }
        }
    }

    核心:

    //uv = float2(dot(uv, float2(c, -s)), dot(uv, float2(s, c))); 
    uv = float2(uv.x*c - uv.y*s, uv.x*s + uv.y*c);

    我的另一篇文章:基础知识:Q&A 中有对旋转矩阵进行简单推导。

    C#脚本:以时间驱动来增长角度和半径

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
     
    public class Swirl : MonoBehaviour
    {
        float angle = 0;
        float radius = 0.1f;
        Material mat;
        void Start () 
        {
                mat = this.GetComponent<Image>().material;
     
                //延迟2秒开始,每隔0.2s调用一次
                InvokeRepeating("DoSwirl", 2f, 0.2f);
        }
     
        void DoSwirl()
        {
            angle += 1f;
            radius += 0.1f;
     
            mat.SetFloat("_Angle",angle);
            mat.SetFloat("_Radius",radius);
     
               //rest
               if (radius >= 0.6f)
               {
                angle = 0;
                radius = 0.1f;
               }
        }
    }
  • 相关阅读:
    解析链接部分
    按指定格式输出日期时间
    Comet:基于 HTTP 长连接的“服务器推”技术
    dialog组件
    中文字符截断的问题
    css垂直水平居中方案
    类的创建
    修改placeholder属性
    json化表单数据
    瀑布流布局
  • 原文地址:https://www.cnblogs.com/joeshifu/p/5489761.html
Copyright © 2020-2023  润新知