前一端时间写了一些有关下雨效果的Shader的,感觉实现的效果很不错,所以把它们分享一下,主要参考表面积水效果 RainSurface和Rainy Surface Shader Part 1: Ripples。下面是视频:
一些下雨的效果(Unity Shader)
Shader "Custom/WeatherFloor"
{
Properties
{
_RainColor ("Water Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Normal("Normal",2D)="bump"{}
[NoScaleOffset]_RippleTex("Ripple Tex", 2D) = "white" {}
[NoScaleOffset]_MaskTex("Mask Tex", 2D) = "white" {}
_RippleScale("Ripple Scale",Range(1,10)) =1
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_Ripple ("Ripple Strength", Range(0,1)) = 0.0
_WaterRange("Water Range", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Normal;
sampler2D _RippleTex;
//R通道代表了涟漪生成的范围,并且带有淡出的效果,
//GB两个通道是高度,差不多就是法线图的效果,
//A通道用来存储时间差,从白到黑不同的颜色值代表了不同的时间。
sampler2D _MaskTex;
struct Input
{
half2 uv_MainTex;
half2 uv_Normal;
half2 uv_FlowMap;
};
half _Glossiness;
half _Metallic;
fixed4 _RainColor;
half _RippleScale;
half _Ripple;
half _WaterRange;
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_INSTANCING_BUFFER_END(Props)
half3 ComputeRipple(half2 uv,half t)
{
//波纹贴图采样,并把采样的高度值扩展到-1到1
half4 ripple=tex2D(_RippleTex,uv);
ripple.gb=ripple.gb*2-1;
//获取波纹的时间,从A通道获取不同的波纹时间,
//frac返回输入值的小数部分。
half dropFrac=frac(ripple.a+t);
//把时间限制在R通道内,(dropFrac-1+ripple.r<0时,计算final时0*UNITY_PI)
half timeFrac=dropFrac-1+ripple.r;
//做淡出处理
half dropFactor=1- saturate(dropFrac);
//计算最终的高度,用一个sin计算出随时间的振幅,修改一下值就知道什么效果了
half final=dropFactor*sin(clamp(timeFrac*9,0,4)*UNITY_PI);
return half3(ripple.gb*final,1);
}
void surf (Input IN, inout SurfaceOutputStandard o)
{
half3 ripple=ComputeRipple(IN.uv_MainTex*_RippleScale,_Time.y)*_Ripple;
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
half3 normal=UnpackNormal(tex2D(_Normal,IN.uv_MainTex));
fixed mask=tex2D(_MaskTex,IN.uv_Normal).r;
half rainMask=pow(saturate(lerp(-0.6,3,_WaterRange)-(1-mask)*2),8);
fixed3 waterColor=_RainColor.rgb*c.rgb;
o.Albedo = lerp(c.rgb,waterColor,rainMask);
o.Normal=normalize(lerp(normal,half3(0,0,1),rainMask)+ripple*rainMask);
o.Metallic = lerp(_Metallic,0.5,rainMask);
o.Smoothness = lerp(_Glossiness,1,rainMask);
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
ComputeRipple计算出的波形大致会是这个样子:
一个周期里只会出现两次波峰,刚好符合效果的两圈涟漪。这里有需要一张涟漪图:
CSDN不能上传tga格式的,并且会打水印,可以在网盘里拿,链接:https://pan.baidu.com/s/1XyH0yyS5u-a9DgEo4E9rNQ 提取码:4fj6。
水洼的原理是改变改变水洼处的法线、金属度、粗糙度的信息,并没有太多复杂的地方,可以用一张噪声图来控制水洼的位置,我现在是直接用一张噪声图来做。
接下来是水流效果:
以下是Shader代码:
Shader "Custom/Flow"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
[NoScaleOffset]_NormalTex("Normal Map",2D )="bump"{}
_RainColor("Water Color", Color) = (1,1,1,1)
_FlowMap("FlowMap",2D)="white"{}
[NoScaleOffset]_FlowNormal("Flow Normal Map",2D )="bump"{}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_FlowRange("Flow Water Range",Range(0,1))=0.5
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Cull Back
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
sampler2D _NormalTex;
sampler2D _FlowMap;
sampler2D _FlowNormal;
struct Input
{
float2 uv_MainTex;
half2 uv_FlowMap;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
fixed _FlowRange;
fixed4 _RainColor;
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
half2 flowUV=IN.uv_FlowMap;
fixed flowG=tex2D(_FlowMap,flowUV).g;
flowUV=flowUV+half2(0,_Time.y*0.4);
fixed flowB=tex2D(_FlowMap,flowUV).b;
fixed flowMask=saturate(_FlowRange-flowB);
half3 flowNormal=UnpackNormal(tex2D(_FlowNormal,IN.uv_FlowMap));
//flowNormal.xy=-flowNormal.xy;
half3 normal=UnpackNormal(tex2D(_NormalTex,IN.uv_MainTex));
//flowNormal=normalize(normal+lerp(half3(0,0,1),flowNormal,flowMask));
flowNormal=normalize(lerp(normal,flowNormal,flowMask));
o.Albedo = c.rgb+_RainColor.rgb*flowG*flowMask;
o.Normal=flowNormal;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
这里也需要两张特制的贴图,链接:https://pan.baidu.com/s/14XhpRExfjQ7bo0kdBjivLg,提取码:ktfj。
具体的思路是用一张流动的遮罩对法线进行叠加,造成雨水流动的假象,方法很简单但实现的效果很好。
好了今天的就摸到这了,溜了溜了。