Unity3D开发之Shader实现扭曲效果

发表于2016-04-01
评论1 9.3k浏览
一、前言
  最近的项目打算弄一个漩涡扭曲的效果,然后在网上搜了一下相关的Shader,发现好像没有可用的Unity3D的现成Shader,所以就打算自己稍微弄弄分享给大家。

二、效果以及实现
  先贴上几个效果图:


  下面是shader面板的控制参数图:


  下面是主要扭曲计算的主要代码,已经附加了必要的注释:


  这个就是简单的扭曲漩涡效果实现了,下面我把完整的代码文件也上传给大家吧,主要只是为了分享而已了,希望能帮到有需要的人。
  额,平台的下载功能好像还没支持,我直接把代码贴上来吧:
Shader "Custom/SwirlShader" {
    Properties {
        _MainTex ("贴图", 2D) = "white" {}
        _Cutout("透明剔除值",Float) = 0.5
        _SwirlArea("区域", Vector) = (100,100,0,0)
        _SwirlCenterXPercent("扭曲中心X偏移比例", Range(0,1)) = 0.5
        _SwirlCenterYPercent("扭曲中心Y偏移比例", Range(0,1)) = 0.5
        _Radius("扭曲半径", Float) = 5
        _SwirlValue("扭曲程度", Float) = 1
    }
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            sampler2D _MainTex;
            fixed4 _SwirlArea;
            fixed _SwirlCenterXPercent;
            fixed _SwirlCenterYPercent;
            fixed _Radius;
            fixed _SwirlValue;
            fixed _Cutout;
            struct vin_vct 
            {
                fixed4 vertex : POSITION;
                fixed4 color : COLOR;
                fixed2 texcoord : TEXCOORD0;
            };
            struct v2f_vct
            {
                fixed4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                fixed2 texcoord : TEXCOORD0;
            };
            v2f_vct vert(vin_vct v)
            {
                v2f_vct o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.color = v.color;
                o.texcoord = v.texcoord;
                return o;
            }
            fixed4 frag(v2f_vct i) : SV_Target 
            {
                //得到想要扭曲的区域大小
                fixed2 swirlArea = fixed2(_SwirlArea.x, _SwirlArea.y);
                //计算扭曲区域的中心点位置
                fixed2 center = fixed2(_SwirlArea.x * _SwirlCenterXPercent, _SwirlArea.y * _SwirlCenterYPercent);
                //计算得到要扭曲的片段距离中心点的距离
                fixed2 targetPlace = i.texcoord * swirlArea;
                targetPlace -= center;
                fixed dis = length(targetPlace);
                //当距离比需要扭曲的半径小的时候,计算扭曲
                if(dis < _Radius)
                {
                    //计算扭曲的程度,慢慢向边缘减弱扭曲,当它恒为1的时候,是一个正圆
                    fixed percent = (_Radius - dis) / _Radius;
                    //根据扭曲程度计算因子,还可以改写为_Time的值让它一直转
                    fixed delta = percent * _SwirlValue;
                    //得到在轴上的值
                    fixed s = sin(delta);
                    fixed c = cos(delta);
                    targetPlace = fixed2(dot(targetPlace, fixed2(c, -s)), dot(targetPlace, fixed2(s, c)));
                }
                //把计算的值偏移回中心点
                targetPlace += center;
                fixed4 c = tex2D(_MainTex, targetPlace/swirlArea) * i.color;
                clip(c.a - _Cutout);
                return c;
            }
           ENDCG
        }
    }
    FallBack "Diffuse"
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: