为了做一个手机版的海水,现有的插件在电脑上不错,但手机上都不行,于是就打算自己实现一个海岛奇兵的海水。
用高通工具扒了它的代码:
#define MEDIUM
#ifdef GL_ES
#else
#define highp
#define mediump
#define lowp
#endif
uniform mat4 u_mvp;
attribute vec4 a_pos;
attribute vec2 a_uv0;
varying highp vec2 v_texcoord0;
varying lowp float v_result;
varying highp vec2 v_normalCoord;
varying lowp vec3 v_waterLightSea;
varying lowp vec3 v_waterDarkSea;
varying lowp vec3 v_waterLightShore;
varying lowp vec3 v_waterDarkShore;
uniform highp float u_time;
uniform mediump float u_uvFactor;
varying float v_reflectionPower;
void main()
{
gl_Position = u_mvp * a_pos;
v_texcoord0 = a_uv0;
float ystretch = 0.2;//0.4;
v_reflectionPower = clamp((1.0 - length(vec2(a_pos.x * 0.7 + (a_uv0.x - 0.5) * 1.5, a_pos.y * ystretch) - vec2(0.0, ystretch))) * 3.0, 1.5, 4.0);
float x = v_texcoord0.x;
float y = v_texcoord0.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;
v_result = c4;
v_normalCoord = v_texcoord0 * 25.0;
v_normalCoord.x -= 0.01 * u_time * 0.5;
v_normalCoord.y += 0.02 * u_time * 0.5;
v_normalCoord = vec2(v_normalCoord.x + c1 * 0.01, (v_normalCoord.y + c1 * 0.01) * u_uvFactor) * 1.5;
}
void main()
{
#ifdef SIMPLE
lowp vec4 normalMapValue = texture2D(normal, v_normalCoord);
gl_FragColor = mix(texture2D(texture0, v_texcoord0), texture2D(texture1, v_texcoord0), (normalMapValue.x * v_result) + (normalMapValue.y * (1.0 - v_result)));
#else
lowp vec4 normalMapValue = texture2D(normal, v_normalCoord);
gl_FragColor = mix(texture2D(texture0, v_texcoord0), texture2D(texture1, v_texcoord0), (normalMapValue.x * v_result) + (normalMapValue.y * (1.0 - v_result)))
+ min(0.4, exp2(log2(((normalMapValue.z * v_result) + (normalMapValue.w * (1.0 - v_result))) * v_reflectionPower) * 5.0));
#endif
}
#ifdef GL_ES
#else
#define highp
#define mediump
#define lowp
#endif
uniform mat4 u_mvp;
attribute vec4 a_pos;
attribute vec2 a_uv0;
varying highp vec2 v_texcoord0;
varying lowp float v_result;
varying highp vec2 v_normalCoord;
varying lowp vec3 v_waterLightSea;
varying lowp vec3 v_waterDarkSea;
varying lowp vec3 v_waterLightShore;
varying lowp vec3 v_waterDarkShore;
uniform highp float u_time;
uniform mediump float u_uvFactor;
varying float v_reflectionPower;
void main()
{
gl_Position = u_mvp * a_pos;
v_texcoord0 = a_uv0;
float ystretch = 0.2;//0.4;
v_reflectionPower = clamp((1.0 - length(vec2(a_pos.x * 0.7 + (a_uv0.x - 0.5) * 1.5, a_pos.y * ystretch) - vec2(0.0, ystretch))) * 3.0, 1.5, 4.0);
float x = v_texcoord0.x;
float y = v_texcoord0.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;
v_result = c4;
v_normalCoord = v_texcoord0 * 25.0;
v_normalCoord.x -= 0.01 * u_time * 0.5;
v_normalCoord.y += 0.02 * u_time * 0.5;
v_normalCoord = vec2(v_normalCoord.x + c1 * 0.01, (v_normalCoord.y + c1 * 0.01) * u_uvFactor) * 1.5;
}
void main()
{
#ifdef SIMPLE
lowp vec4 normalMapValue = texture2D(normal, v_normalCoord);
gl_FragColor = mix(texture2D(texture0, v_texcoord0), texture2D(texture1, v_texcoord0), (normalMapValue.x * v_result) + (normalMapValue.y * (1.0 - v_result)));
#else
lowp vec4 normalMapValue = texture2D(normal, v_normalCoord);
gl_FragColor = mix(texture2D(texture0, v_texcoord0), texture2D(texture1, v_texcoord0), (normalMapValue.x * v_result) + (normalMapValue.y * (1.0 - v_result)))
+ min(0.4, exp2(log2(((normalMapValue.z * v_result) + (normalMapValue.w * (1.0 - v_result))) * v_reflectionPower) * 5.0));
#endif
}
代码本身很简单,自己可以改成u3d版本。本来我以为改完就好了,没想到还有很多问题。
o.args.y = clamp((1.0 - length(float2(a_pos.x * 0.7 + (a_uv0.x - 0.5) * 1.5, a_pos.z * ystretch) - float2(0, ystretch))) * 3.0, 1.5, 4.0);
这个公式非常重要,要注意海岛奇兵的坐标系和unity不一样,海盗奇兵的y相当于unity的z,要注意自己替换。
另外注意法线图片,在海岛奇兵中就是普通贴图,前往不要让unity fix成normalmap类型,就会挂掉。
然后效果如下:
但是这样还不够,海岛奇兵里面的这个玩意是能够跟着视角走的,经过我不但测试,我发现玄机在这里:
a_pos.x * 0.7 + (a_uv0.x - 0.5) * 1.5
要注意,如果你要偏移,那么a_pos.x就要增加世界坐标值里面的数值。
比如你海面有100米,你要右移20米,那么就要(p_pos.x +20) * 0.7
另外uv是【-1,1】 所以只需要增加百分之20,也就是 a_uv0.x + 0.2就好了。这样就很简单了吧。
good
回复删除