原创作品

Unity Shader——水桶里的圆形波纹水面

唐福幸 发表于   2021-10-15 10:46:08
3515
3
8

在开始之前,先看一下最终的动态效果。

soogif(1).gif

水桶里的圆形波纹水面

实现思路

1.水面是使用的Unity内置的plane模型,通过内置的Time变量更改它的纹理坐标,从而产生动态的波纹

2.计算纹理坐标到中心点的距离,通过clip函数将除了圆形之外的部分裁切掉,就会剩下圆形的水面了

资源准备

一张水面的贴图

water texture


如果想要更好的效果,可以自行准备一个水桶或者杯子的模型,用来更好的衬托我们的水面。


定义变量

Shader "My Shader/Wave Water"{
Properties
{
_MainTex("Base (RGB)", 2D) = "white" {}
_MainColor("Main Coloe (RGBA)", Color) = (1,1,1,1)
_WaveHeight("Wave Height",Range(0,0.1)) = 0.01
_WaveFrequency("Wave Frequency",Range(1,100)) = 50
_WaveSpeed("Wave Speed",Range(0,10)) = 1
}


1.定义水面波纹的贴图


2.定义一个颜色变量,其中RGB用于控制水面波纹的颜色,A用于控制材质的透明度


3.定义波纹的波动高度


4.定义波纹出现的频率


5.定义波纹的波动速度

编译指令

SubShader{
Tags{"Queue"="Transparent"}

Pass
{
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha

CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"

因为我们想要水面透明显示,所以把它的渲染序列放在Transparent里,关闭深度写入,开启混合模式。这属于透明shader的标准设置。

定义顶点着色器和片段着色器,然后把Unity的内置文件包含进来。

再次声明变量

struct v2f{
float4 vertex:SV_POSITION;
float2 uv:TEXCOORD0;};sampler2D _MainTex;float4 _MainTex_ST;fixed4 _MainColor;float _WaveHeight;float _WaveFrequency;float _WaveSpeed;


1.定义v2f结构体,里边包含顶点坐标和纹理坐标


2.将上述所有的变量在CG里重新定义一遍,多出来的_MainTex_ST变量是水面贴图的Tiling和Offset,用于计算纹理坐标

定义顶点着色器

v2f vert (appdata_base v) {
v2f o;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
o.vertex = UnityObjectToClipPos(v.vertex);

return o;}

在顶点着色器里我们进行了以下操作:

1.使用UnityCG.cginc里包含的appdata_base结构体作为顶点着色器的输入结构体


2.在顶点着色器里,使用宏TRANSFORM_TEX计算_MainTex的纹理坐标


3.将顶点坐标变换到裁切空间


4.最后输出到v2f结构体

定义片段着色器

                    fixed4 frag(v2f IN) : SV_Target
{
float2 uvCoord = _MainTex_ST.xy*0.5;

fixed2 uvDir = normalize(IN.uv-uvCoord);
fixed uvDis = distance(IN.uv,uvCoord);

clip(uvCoord-uvDis);

fixed2 uv = IN.uv+sin(uvDis*_WaveFrequency - _Time.y*_WaveSpeed)*_WaveHeight*uvDir;

fixed4 color;
color.rgb = tex2D(_MainTex, uv)*_MainColor;
color.a = _MainColor.a;
return color;
}
ENDCG
}
}
FallBack "Transparent"}

片段着色器是本shader里最重要的部分,在这里我们进行了以下操作:

1.将v2f结构体输入到片段着色器


2._MainTex_ST是一个四维向量,其中xy是UV的Tiling,乘以0.5表示纹理坐标的中间点,保存到新定义的变量uvCoord里


3.定义变量uvDir,等于纹理坐标到中心点的方向。是从中心点朝向四周放射的形状


4.定义变量uvDis,等于纹理坐标到中心点的距离。且从中心点向四周线性递增,到达边界的距离为uvCoord,到达四个顶点的距离大于uvCoord


5.使用uvCoord减去uvDis,得出一个以中心点为原点,uvCoord为半径的圆,而圆之外的数值小于零。使用clip函数把结果小于0的像素全部裁切,最后只剩下圆形


6.uvDis乘以_WaveFrequency变量,用于控制sin函数的频率,时间变量乘以_WaveSpeed是为了控制sin函数的速度,两个之所以相减,是为了让波纹是从中心向四周扩散的。如果用加,会出现波纹从四周向中心汇集的效果。乘以_WaveHeight变量用于控制sin函数的振幅,再乘以方向变量uvDir变为二维向量。结果加在最开始的纹理坐标IN.uv上


7.使用新的纹理坐标uv变量对水面贴图进行采样,然后乘以颜色变量作为颜色输出,颜色的A通道作为透明度。最后返回color


材质面板


最后的材质面板以及变量的参数如下:



没有标签
确定
评论(3)
Albert
你们Ta没有自己的网站吗
回复
907天前
小菜鸡太美
回复
Albert
哈哈哈哈哈
回复
634天前
GouDDDD
你们Ta没有自己的网站吗
回复
918天前
杳钟
你们Ta没有自己的网站吗
回复
918天前
没有更多啦~
  • 咨询
    客服
  • 扫码加入QQ群 或搜索QQ群号: 797421367
  • 扫码关注公众号 或微信搜索: cokey游戏特效