可以用在ui展示进度,最近的小米手机下载应用的时候桌面也是显示类似的效果。在ShaderToy找到了很漂亮的案例(2.5d water,点击转跳)。代码基本就是翻译了一下shader toy的写法,在此基础上加一些噪声之类的,顺便单独给“液面”一个颜色,当然还可以给液面的“圆周”也上一个高亮的色,这样更好看些,不过目前够用就没有做得那么仔细。
为了在unity image的使用方便,用了color.a来控制液面高度,可读性有些奇怪,但是用起来方便:)

Shader "Test/Liquid2D" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Face ("Face Texture", 2D) = "white" {} _ReflectionTex ("ReflectionTex", 2D) = "white" {} [HDR] _FaceColor ("Face Color", Color) = (1, 1, 1, 1) _Progress ("Progress", Range(0.0, 1.0)) = 0.5 _Tangent ("AngleTangent", float) = 0.66 _NoiseSpeedScale ("NoiseSpeed(XY)Scale(ZW)", Vector) = (-0.02, 0.2, 0.5, 1) _Gradient ("Gradient", Vector) = (2, 0.36, 0, 0) [HDR] _WaterColor ("WaterColor", Color) = (1.0, 1.0, 0.2, 1.0) _WaveStrength ("WaveStrength", Float) = 2.0 _WaveFrequency ("WaveFrequency", Float) = 180.0 _WaterTransparency ("WaterTransparency", Float) = 1.0 _WaterAngle ("WaterAngle", Float) = 4.0 [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 [HideInInspector] _StencilComp ("Stencil Comparison", Float) = 8 [HideInInspector] _Stencil ("Stencil ID", Float) = 0 [HideInInspector] _StencilOp ("Stencil Operation", Float) = 0 [HideInInspector] _StencilWriteMask ("Stencil Write Mask", Float) = 255 [HideInInspector] _StencilReadMask ("Stencil Read Mask", Float) = 255 } 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 One OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_instancing #pragma multi_compile_local _ PIXELSNAP_ON #pragma multi_compile _ ETC1_EXTERNAL_ALPHA sampler2D _Face; sampler2D _ReflectionTex; float4 _ReflectionTex_ST; float4 _FaceColor; float _Progress; fixed4 _WaterColor; float _WaveStrength; float _WaveFrequency; float _WaterTransparency; float _WaterAngle; float _Tangent; float4 _NoiseSpeedScale; float2 _Gradient; struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; }; v2f vert(appdata_t IN) { v2f OUT; OUT.vertex = UnityObjectToClipPos(IN.vertex); OUT.texcoord = IN.texcoord; OUT.color = IN.color; #ifdef PIXELSNAP_ON OUT.vertex = UnityPixelSnap (OUT.vertex); #endif return OUT; } float getWave(float2 uv, float wave_frequency) { float wave = sin(10.0 * uv.y + 10.0 * uv.x + wave_frequency * _Time); wave += sin(20.0 * -uv.y + 20.0 * uv.x + wave_frequency * 1.0 * _Time) * 0.5; wave += sin(15.0 * -uv.y + 15.0 * -uv.x + wave_frequency * 0.6 * _Time) * 1.3; wave += sin(3.0 * -uv.y + 3.0 * -uv.x + wave_frequency * 0.3 * _Time) * 10.0; return wave; } fixed4 drawWater(fixed4 water_color, sampler2D colorTex, float transparency, float height, float angle, float wave_strength, float wave_frequency, fixed2 uv) { float absSignHeight = abs(sign(height)); float rcpHeight = 1 * absSignHeight / (1 - absSignHeight + height);//避免除以0 // angle = angle * uv.y * rcpHeight + angle*angle*_Tangent; //3D effect // angle *= uv.y/height+angle/1.5; //3D effect wave_strength *= 0.001; float wave = getWave(uv, wave_frequency) * wave_strength; float waterLevel = height + wave;//晃动的水面的高度 float y = waterLevel + angle * (waterLevel - uv.y); fixed4 originColor = tex2D(_ReflectionTex, fixed2(uv.x + wave + _ReflectionTex_ST.z * _Time.y, y + wave + _ReflectionTex_ST.w * _Time.y)) * _FaceColor; originColor *= step(y, 1) * originColor.a;//避免取到uv.y大于1的颜色 fixed4 surfaceColor = lerp(originColor, water_color, saturate(_Gradient.y - (_Gradient.x * (1 - uv.y * rcpHeight)))); //两次噪声采样,做视差流动 fixed4 bodyColor = (tex2D(colorTex, fixed2(uv.x + wave/4, uv.y - _Time.y * _NoiseSpeedScale.x)) *_NoiseSpeedScale.z + tex2D(colorTex, fixed2(uv.x + wave/4, uv.y - _Time.y * _NoiseSpeedScale.y)) * _NoiseSpeedScale.w) * water_color ; //混合水表面和水体的颜色 fixed4 col = lerp(surfaceColor, bodyColor, transparency * (1 - uv.y/(height+wave))); //只取水面以下的颜色 return col * step(uv.y, waterLevel); } fixed4 frag (v2f i) : SV_Target { return drawWater(_WaterColor, _Face, _WaterTransparency, i.color.a, _WaterAngle, _WaveStrength, _WaveFrequency, i.texcoord); } ENDCG } } }