您需要 登录 才可以下载或查看,没有账号?注册
x
第一篇文章想分享一下使用Unity来制作海岛奇兵海洋效果, 最终的实现效果如下
制作这种效果,需要如下几步1, 首先要准备一个Mesh, 我使用的是10 x 10 的Mesh, 一共100个格子,这样的Mesh顶点相对比较多,最后shader计算的时候效果比较好。
2, 然后来看看shader的具体实现 首先看一下需要传入的属性,需要传入3张贴图,一张_SeaNormal 法线图,一张亮色的海洋图_LightSea , 一张暗色的海洋图_DarkSea ,u_time 是时间变化参数,u_uvFactor 是uv缩放参数
1
2
3
4
5
6
7
| Properties
{
_SeaNormal ("SeaNormal", 2D) = "white" {}
_LightSea ("LightSea", 2D) = "white" {}
_DarkSea ("DarkSea", 2D) = "white" {}
u_time ("u_time", float) = 83.36153
u_uvFactor ("u_uvFactor", float) = 0.7735959
}
|
接下来看下vertshader的具体实现
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| struct appdata
{
float4 vertex : POSITION0;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : POSITION0;
float2 uv : TEXCOORD0;
float2 normaluv : TEXCOORD1;
float v_result : TEXCOORD2;
float v_reflectionPower : TEXCOORD3;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
float ystretch = 0.2;
o.v_reflectionPower = clamp((1.0 - length(float2(v.vertex.x * 0.7 + (v.uv.x - 0.5) * 1.5, v.vertex.z * ystretch) - float2(0.0, ystretch))) * 3.0, 1.5, 4.0);
float x = v.uv.x;
float y = v.uv.y * u_uvFactor;
float mov1 = y / 0.04 * 5.0 + u_time;
float mov2 = x / 0.02 * 5.0;
float c1 = abs((sin(mov1 + u_time) + mov2) * 0.5 - mov1 - mov2 + u_time);
float c4 = 0.5 * sin(sqrt(x * x + y * y) * 150.0 - u_time) + 0.5;
c1 = 0.5 * sin(c1) + 0.5;
o.v_result = c4;
o.normaluv = v.uv * 25.0;
o.normaluv.x -= 0.01 * u_time * 0.5;
o.normaluv.y += 0.02 * u_time * 0.5;
o.normaluv = float2(o.normaluv.x + c1 * 0.01, (o.normaluv.y + c1 * 0.01) * u_uvFactor) * 1.5;
return o;
}
|
vertexshader传入到pixelshader的参与有5个 a, vertex参数不传入pixelshader, 直接由引擎计算出屏幕空间的位置 b, uv就是模型的uv, 直接传入pixelshader c, normaluv是计算出来的法线uv, 来采样法线图, 法线uv是动态的,来模拟海洋的海浪变化 d, v_reflectionPower是计算的高光强度 e, v_result参数也是用来影响法线uv的变化的
然后看下pixelshader [AppleScript] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
| float4 custommix(float4 x, float4 y, float a)
{
return (x * (1 - a) + y * a);
}
fixed4 frag (v2f i) : SV_Target
{
float4 normalMapValue = tex2D(_SeaNormal, i.normaluv);
float4 lightseacol = tex2D(_LightSea, i.uv);
float4 darkseacol = tex2D(_DarkSea, i.uv);
float4 fragcol = custommix(lightseacol, darkseacol, (normalMapValue.x * i.v_result) + (normalMapValue.y * (1.0 - i.v_result)));
float4 fragspeccol = min(0.4, exp2(log2(((normalMapValue.z * i.v_result) + (normalMapValue.w * (1.0 - i.v_result))) * i.v_reflectionPower) * 5.0));
fragcol += fragspeccol;
return fragcol;
}
|
通过vertexshader传入的参数,采样出亮色海洋贴图,暗色海洋贴图颜色以及动态的法线图 通过函数计算得到diffuse颜色fragcol, 然后根据vertexshader传入的v_reflectionPower高光参数,计算出高光值fragspeccol, 然后计算出最终的颜色fragcol并输出 ,Adreno Profiler是用来分析 手机游戏的渲染比较好用的工具,原则上可以用来分析任意发布在手机上游戏的渲染实现 截图效果如下
知乎@谢刘斌
|