ShadowGun 用动画实现水面效果


CCEffect %{
  techniques:
  - name: opaque
    passes:
    - vert: unlit-vs:vert
      frag: unlit-fs:frag
      properties: &props
        color:        { value: [1, 1, 1, 1], inspector: { type: color } }
        numTexTiles: { value: [1, 1, 0, 0] }
        overColor:    { value: [1,1,1,1] }
        replaySpeed:   { value: 4 }
        mainTexture:  { value: grey         }
  - name: transparent
    passes:
    - vert: unlit-vs:vert
      frag: unlit-fs:frag
      blendState:
        targets:
        - blend: true
          blendSrc: src_alpha
          blendDst: one_minus_src_alpha
          blendSrcAlpha: src_alpha
          blendDstAlpha: one_minus_src_alpha
      properties: *props
}%

CCProgram unlit-vs %{
  precision mediump float;
  #include <cc-global>
  #include <cc-local-batch>
  #include <input>

  #if USE_VERTEX_COLOR
    in vec4 a_color;
    out vec4 v_color;
  #endif

  #if USE_TEXTURE
    in vec2 a_texCoord;
    out vec2 v_uv;
    out vec4 col;
    uniform TexCoords {
      vec4 numTexTiles;
      vec4 overColor;
      float replaySpeed;
    };
  #endif

  vec2 Rand(vec2 ij) {
    vec4 a = vec4(97.409091034f,54.598150033f,56.205410758f,44.687805943f);
    vec4 result = vec4(ij, ij);
    for(int i = 0; i < 2; i++) {
      result.x = fract(dot(result, a));
      result.y = fract(dot(result, a));
      result.z = fract(dot(result, a));
      result.w = fract(dot(result, a));
    }
    return result.xy;
  }

  highp vec4 vert () {
    vec4 position;
    CCVertInput(position);

    highp mat4 matWorld;
    CCGetWorldMatrix(matWorld);

    highp vec4 pos = cc_matProj * (cc_matView * matWorld) * position;

    float time = (a_color.a * 60 + cc_time.x) * replaySpeed;
    float itime = floor(time);
    float ntime = itime + 1;
    float ftime = time - itime;
    vec2 texTileSize = 1.f / numTexTiles.xy;
    vec4 tile;

    #if USE_TEXTURE
      v_uv = a_texCoord;
      #if FLIP_UV
        v_uv.y = 1.0 - v_uv.y;
      #endif
      tile.xy = vec2(itime, floor(itime / numTexTiles.x));
      tile.zw = vec2(ntime, floor(ntime / numTexTiles.x));
      tile = fmod(tile, numTexTiles.xyxy);
      v_uv = (v_uv.xyxy + tile) * texTileSize.xyxy;
      col = vec4(overColor.xyz * a_color.xyz,ftime);
    #endif

    #if USE_VERTEX_COLOR
      v_color = a_color;
    #endif

    return pos;
  }
}%

CCProgram unlit-fs %{
  precision mediump float;
  #include <output>

  #if USE_TEXTURE
    in vec2 v_uv;
    in vec4 col;
    uniform sampler2D mainTexture;
  #endif

  #if USE_COLOR
    uniform Constant {
      vec4 color;
    };
  #endif

  #if USE_VERTEX_COLOR
    in vec4 v_color;
  #endif

  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      o *= lerp(texture(mainTexture, v_uv.xy), texture(mainTexture, v_uv.zw), col.a);
    #endif

    #if USE_COLOR
      o *= color;
    #endif

    #if USE_VERTEX_COLOR
      o *= v_color;
    #endif

    return CCFragOutput(o);
  }
}%



参数配置

water.zip (104.4 KB)
fbx,shader及贴图打包

使用办法:

  1. 在项目资源里创建一个Effect文件,然后把上面的的shader代码全放进去
  2. 再创建一个Material文件,然后选中Material文件,在右边属性栏处,Effect选择第1步创建的Effect
  3. 再把贴图拉进MainTexture里面。其它参数可以自行修改试试,会出现不同的效果。
  4. 最后再把这个材质拉到你的对象材质上。

要说美观,肯定是没有其它的水面效果美观。这个shader的好处在用的序列帧的形式去实现的水面,性能会比较好。

1赞