2018年6月27日星期三

海岛奇兵的海水的实现

为了做一个手机版的海水,现有的插件在电脑上不错,但手机上都不行,于是就打算自己实现一个海岛奇兵的海水。
   用高通工具扒了它的代码:
#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
}

代码本身很简单,自己可以改成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就好了。这样就很简单了吧。

1 条评论: