当前位置:   article > 正文

UnityShader基础案例(二)——UI流光,扭曲,外边框,波纹效果_unity怎么做全屏的热浪或者波纹效果

unity怎么做全屏的热浪或者波纹效果

一、UI流光

  1. Shader "Custom/Test0"
  2. {
  3. Properties
  4. {
  5. _MainTex("主纹理",2D)="white"{}
  6. //使用黑白纹理识别边框
  7. _MaskTex("黑白纹理",2D)="white"{}
  8. _FlowTex("流光贴图",2D)="white"{}
  9. _FlowColor("流光颜色",Color)=(1,1,1,1)
  10. _FlowSpeed("流光速度",Range(0.1,2))=1.0
  11. }
  12. SubShader
  13. {
  14. Pass
  15. {
  16. //加这句话的原因是使用的素材中把主图片的A通道拆开了
  17. Blend SrcAlpha OneMinusSrcAlpha
  18. CGPROGRAM
  19. #pragma vertex vert
  20. #pragma fragment frag
  21. #include "UnityCG.cginc"
  22. sampler2D _MainTex;
  23. sampler2D _MaskTex;
  24. sampler2D _FlowTex;
  25. fixed _FlowSpeed;
  26. fixed4 _FlowColor;
  27. struct a2v
  28. {
  29. float4 vertex:POSITION;
  30. float2 texcoord:TEXCOORD0;
  31. };
  32. struct v2f
  33. {
  34. float4 pos:SV_POSITION;
  35. float2 uv:TEXCOORD0;
  36. };
  37. v2f vert(a2v v)
  38. {
  39. v2f o;
  40. o.pos = UnityObjectToClipPos(v.vertex);
  41. o.uv.xy = v.texcoord;
  42. return o;
  43. }
  44. fixed4 frag(v2f i):SV_Target
  45. {
  46. fixed4 texResult_Main = tex2D(_MainTex, i.uv.xy);
  47. fixed4 texResult_Mask = tex2D(_MaskTex, i.uv.xy);
  48. //流光速度计算
  49. i.uv.x += _Time.y * _FlowSpeed;
  50. //用于做流光范围判定
  51. fixed alpha = tex2D(_FlowTex, i.uv.xy).a;
  52. //图片的黑色区域和非流光的位置全是0,代表这些位置不需要流光
  53. fixed3 color = alpha * texResult_Mask * _FlowColor;
  54. //0就是显示原来图片,非0就显示流光混合颜色
  55. fixed3 finalColor = texResult_Main + color;
  56. return fixed4(finalColor, texResult_Main.a);
  57. }
  58. ENDCG
  59. }
  60. }
  61. }

结果:

        41c55e7101ce4f4c865e6246194c86e9.png

         实现需要三张图片,一个便是要显示的主纹理,一个是主纹理的透明通道纹理(用于识别边框),一个是流光纹理。

        还有一种UI流光是在外面一直转圈的。

二、UI扭曲

        不只是局限于UI,场景中的传送门也可以这样做,加个广告牌技术,保证时刻面对玩家,这里就不加了。

        扭曲的原理也很简单,采样点旋转一个角度即可,不过为了体现扭曲效果,我们让越靠近中心的点旋转越小,越远离的点旋转越大,不然全旋转成一个角度那叫旋转不叫扭曲。旋转要构建旋转矩阵。   

  1. Shader "Custom/Test0"
  2. {
  3. Properties
  4. {
  5. _MainTex("渲染纹理",2D)="white"{}
  6. _Strength("扭曲强度",float)=0.5
  7. }
  8. SubShader
  9. {
  10. Pass
  11. {
  12. CGPROGRAM
  13. #pragma vertex vert
  14. #pragma fragment frag
  15. #include "UnityCG.cginc"
  16. sampler2D _MainTex;
  17. float _Strength;
  18. struct a2v
  19. {
  20. float4 vertex:POSITION;
  21. float2 texcoord:TEXCOORD0;
  22. };
  23. struct v2f
  24. {
  25. float4 pos:SV_POSITION;
  26. float2 uv:TEXCOORD0;
  27. };
  28. v2f vert(a2v v)
  29. {
  30. v2f o;
  31. o.pos = UnityObjectToClipPos(v.vertex);
  32. o.uv = v.texcoord;
  33. return o;
  34. }
  35. fixed4 frag(v2f i):SV_Target
  36. {
  37. fixed2 temp = i.uv - fixed2(0.5, 0.5);
  38. float length = sqrt(dot(temp, temp));
  39. //计算弧度
  40. float theta = length * _Strength;
  41. float3x3 materix =
  42. {
  43. cos(theta), -sin(theta), 0,
  44. sin(theta), cos(theta), 0,
  45. 0, 0, 1
  46. };
  47. fixed2 uv = fixed2(0.5, 0.5) +mul(materix,temp);
  48. fixed4 color=tex2D(_MainTex,uv);
  49. return color;
  50. }
  51. ENDCG
  52. }
  53. }
  54. }

               这里要说一下图片本身对扭曲的影响,尽量不要选那些可以填满整个图片的纹理,因为四个角的纹理坐标有的时候一旋转会超出去,这时候就要看怎么截取的。

三、外边框效果

        这个不同于3D物体的描边,扩充模型什么的,我们相当于是对纹理进行的描边,这里就有一个可以利用的地方,那就是透明度。                

  1. Shader "Custom/Test2"
  2. {
  3. Properties
  4. {
  5. _MainTex("渲染纹理",2D)="white"{}
  6. _EdgeColor("边缘颜色",Color)=(1,1,1,1)
  7. _EdgeArea("边缘范围",float)=1
  8. }
  9. SubShader
  10. {
  11. Pass
  12. {
  13. Blend SrcAlpha OneMinusSrcAlpha
  14. CGPROGRAM
  15. #pragma vertex vert
  16. #pragma fragment frag
  17. #include "UnityCG.cginc"
  18. sampler2D _MainTex;
  19. float4 _MainTex_TexelSize;
  20. fixed4 _EdgeColor;
  21. fixed _EdgeArea;
  22. struct a2v
  23. {
  24. float4 vertex:POSITION;
  25. float2 texcoord:TEXCOORD0;
  26. };
  27. struct v2f
  28. {
  29. float4 pos:SV_POSITION;
  30. float2 uv:TEXCOORD0;
  31. };
  32. v2f vert(a2v v)
  33. {
  34. v2f o;
  35. o.pos = UnityObjectToClipPos(v.vertex);
  36. o.uv = v.texcoord;
  37. return o;
  38. }
  39. fixed4 frag(v2f i):SV_Target
  40. {
  41. fixed4 texResult=tex2D(_MainTex,i.uv);
  42. //通过采样周围点的Alpha,判断边缘
  43. float2 uv_up = i.uv + _MainTex_TexelSize.xy * float2(0,1) * _EdgeArea;
  44. float2 uv_down = i.uv + _MainTex_TexelSize.xy * float2(0,-1) * _EdgeArea;
  45. float2 uv_left = i.uv + _MainTex_TexelSize.xy * float2(-1,0) * _EdgeArea;
  46. float2 uv_right = i.uv + _MainTex_TexelSize.xy * float2(1,0) * _EdgeArea;
  47. //周围的Alpha
  48. fixed aroundAlpha=tex2D(_MainTex,uv_up).a*tex2D(_MainTex,uv_down).a*
  49. tex2D(_MainTex,uv_left).a*tex2D(_MainTex,uv_right).a;
  50. //判定颜色
  51. fixed3 color=lerp(_EdgeColor,texResult,aroundAlpha);
  52. return fixed4(color,texResult.a);
  53. }
  54. ENDCG
  55. }
  56. }
  57. }

       

        这个是参考网上的写法,但这个写法本身好像会对图片有一定的要求,主要是最后混合时用的参数,个人感觉怪怪的。

        下面这个是作者的写法,仅供参考 。       

  1. Shader "Custom/Test0"
  2. {
  3. Properties
  4. {
  5. _MainTex("渲染纹理",2D)="white"{}
  6. _EdgeColor("边缘颜色",Color)=(1,1,1,1)
  7. _EdgeArea("边缘范围",float)=1
  8. }
  9. SubShader
  10. {
  11. Pass
  12. {
  13. Blend SrcAlpha OneMinusSrcAlpha
  14. CGPROGRAM
  15. #pragma vertex vert
  16. #pragma fragment frag
  17. #include "UnityCG.cginc"
  18. sampler2D _MainTex;
  19. float4 _MainTex_TexelSize;
  20. fixed4 _EdgeColor;
  21. fixed _EdgeArea;
  22. struct a2v
  23. {
  24. float4 vertex:POSITION;
  25. float2 texcoord:TEXCOORD0;
  26. };
  27. struct v2f
  28. {
  29. float4 pos:SV_POSITION;
  30. float2 uv:TEXCOORD0;
  31. };
  32. v2f vert(a2v v)
  33. {
  34. v2f o;
  35. o.pos = UnityObjectToClipPos(v.vertex);
  36. o.uv = v.texcoord;
  37. return o;
  38. }
  39. fixed4 frag(v2f i):SV_Target
  40. {
  41. fixed4 texResult=tex2D(_MainTex,i.uv);
  42. //通过采样周围点的Alpha,判断边缘
  43. float2 uv_up = i.uv + _MainTex_TexelSize.xy * float2(0,1) * _EdgeArea;
  44. float2 uv_down = i.uv + _MainTex_TexelSize.xy * float2(0,-1) * _EdgeArea;
  45. float2 uv_left = i.uv + _MainTex_TexelSize.xy * float2(-1,0) * _EdgeArea;
  46. float2 uv_right = i.uv + _MainTex_TexelSize.xy * float2(1,0) * _EdgeArea;
  47. //周围的Alpha
  48. fixed aroundAlpha=tex2D(_MainTex,uv_up).a+tex2D(_MainTex,uv_down).a+
  49. tex2D(_MainTex,uv_left).a+tex2D(_MainTex,uv_right).a;
  50. aroundAlpha=saturate(aroundAlpha);
  51. //判定颜色
  52. fixed3 color=lerp(_EdgeColor,texResult,aroundAlpha*texResult.a);
  53. return fixed4(color,aroundAlpha);
  54. }
  55. ENDCG
  56. }
  57. }
  58. }

       

        左边为作者的效果。

四、波纹采样

        通过正弦或者余弦函数对采样做偏移来营造出波纹感觉。        

  1. Shader "Custom/Test0"
  2. {
  3. Properties
  4. {
  5. _MainTex("主颜色",2D)="white"{}
  6. _A("波幅",Range(0.01,10))=0.2
  7. _W("波频",Range(3,50))=0.5
  8. _Area("波纹区域",Range(0,1))=0.2
  9. _Atten("波幅衰减速度",Range(0,10))=1
  10. }
  11. SubShader
  12. {
  13. Pass
  14. {
  15. Blend SrcAlpha OneMinusSrcAlpha
  16. CGPROGRAM
  17. #pragma vertex vert
  18. #pragma fragment frag
  19. #include "UnityCG.cginc"
  20. sampler2D _MainTex;
  21. float2 _MainTex_TexelSize;
  22. float _A;
  23. float _W;
  24. float _Area;
  25. float _Atten;
  26. struct a2v
  27. {
  28. float4 vertex:POSITION;
  29. float2 texcoord:TEXCOORD0;
  30. };
  31. struct v2f
  32. {
  33. float4 pos:SV_POSITION;
  34. float2 uv:TEXCOORD0;
  35. };
  36. v2f vert(a2v v)
  37. {
  38. v2f o;
  39. o.pos = UnityObjectToClipPos(v.vertex);
  40. o.uv = v.texcoord;
  41. return o;
  42. }
  43. fixed4 frag(v2f i):SV_Target
  44. {
  45. float2 center = float2(0.5, 0.5);
  46. //我们利用采样点距离中心点的距离作为t变量,这里就不加时间变化了,如果需要和距离混在一起加就行
  47. float w=sqrt(dot(i.uv - center, i.uv - center));
  48. //length用于检测区域
  49. float length = saturate(_Area-w);
  50. //做出离的越远振幅越小
  51. float a = _A / (_A + w*_Atten)*_A;
  52. float2 uv = i.uv;
  53. uv.y += a * cos(_W * w * UNITY_PI)*length; //*length;
  54. fixed4 texColor = tex2D(_MainTex, uv);
  55. return texColor;
  56. }
  57. ENDCG
  58. }
  59. }
  60. }

       

 这个图片的效果不算特别好,找那种有水的会更好。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/107893
推荐阅读
相关标签
  

闽ICP备14008679号