ShaderLab:spine和sprite受击闪白特效

更多笔记,请关注公众号:
qrcode_for_gh_5f59886669d1_258

// 演示 //

640

// 实现 //

1 编写 effect

声明相关属性,既可以通过代码赋值,也可以通过编辑器修改

CCEffect %{
  techniques:
  - passes:
    - vert: vs
      frag: fs
      blendState:
        targets:
        - blend: true
      rasterizerState:
        cullMode: none
      properties:
        texture: { value: white }
        alphaThreshold: { value: 0.5 }
        u_color: { value: [1,1,1,1], editor: {type: color} }
        u_rate: { value: 1 }
}%

顶点着色器,我们这里 spine 和 sprite 使用的是同一份材质,所以会存在两者相关的宏定义

CCProgram vs %{
  precision highp float;

  #include <cc-global>
  #include <cc-local>

  in vec3 a_position;
  in vec4 a_color;
  out vec4 v_light;

  #if USE_TINT
    in vec4 a_color0;
    out vec4 v_dark;
  #endif

  #if USE_TEXTURE
    in vec2 a_uv0;
    out vec2 v_uv0;
  #endif

  void main () {
    mat4 mvp;
    
    #if CC_USE_MODEL
      mvp = cc_matViewProj * cc_matWorld;
    #else
      mvp = cc_matViewProj;
    #endif

    #if USE_TEXTURE
      v_uv0 = a_uv0;
    #endif

    v_light = a_color;
    #if USE_TINT
      v_dark = a_color0;
    #endif

    gl_Position = mvp * vec4(a_position, 1);
  }
}%

片段着色器,通过 mix 函数获得最终色值


CCProgram fs %{
  precision highp float;
  
  #include <alpha-test>
  #include <texture>

  in vec4 v_light;
  #if USE_TINT
    in vec4 v_dark;
  #endif

  #if USE_TEXTURE
    in vec2 v_uv0;
    uniform sampler2D texture;
  #endif

  uniform ARGS {
    vec4 u_color;
    float u_rate;
  };

  void main () {
    vec4 texColor = vec4(1.0);

    #if USE_TEXTURE
      CCTexture(texture, v_uv0, texColor);
    #endif
    
    vec4 finalColor;

    #if USE_TINT
      finalColor.a = v_light.a * texColor.a;
      finalColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;
    #else
      finalColor = texColor * v_light;
    #endif

    ALPHA_TEST(finalColor);

    vec3 result = mix(u_color.rgb, finalColor.rgb, u_rate);
    gl_FragColor = vec4(result.rgb, finalColor.a);
  }
}%

2编写脚本组件

在 onLoad 中初始化所需属性

onLoad() {
    this._median = this.duration / 2;
    // 获取材质
    if (this.node.getComponent(cc.Sprite)) {
        this._material = this.node.getComponent(cc.Sprite).getMaterial(0);
    } else {
        this._material = this.node.getComponent(sp.Skeleton).getMaterial(0);
    }
    // 设置材质对应的属性
    this._material.setProperty("u_rate", 1);
}

在 update 中计算时间流逝,依此来计算差值,并赋值给片段着色器

update(dt) {
    if (this._time > 0) {
        this._time -= dt;
        this._time = this._time < 0 ? 0 : this._time;
        let rate = Math.abs(this._time - this._median) * 2 / this.duration;
        this._material.setProperty("u_rate", rate);
    }
}

3 我来组成头部

将材质文件拖拽到 spine/sprite 的材质位置,脚本文件也拖到该节点下,设置闪烁的时间

也可以在材质中设置相关参数,比如目标色值等

[

—END—

获取源码请在公众号回复:

受击闪白

19赞

mark.
支持。

鸭哥威武!

Mark!!

感谢分享,mark支持。

mark 1

老哥 这样弄会增加dc 有没有办法既可以有闪白效果 又不增加dc

2赞

安卓手机上有效果吗?

测试安卓上 可用。
测试包: 链接: https://pan.baidu.com/s/1SCxustaz4nNSv824_IIHDg 密码: mj2s

3.0版本 可以参考 https://gitee.com/yeshao2069/cocos-creator-shader/tree/v3.0.0/HitWhite

我用你提供的DEMO测试了一下,2.4.5版本,在web上都没问题,在android手机上,图片没问题,spine动画没有任何变化。。

大佬,我关注公众号之后,获取了源码,然后直接将demo用cocos2.4.3到2.4.5打包了一个安卓版本,发现只有图片能闪白,那个骨骼动画的人物没有效果。不知道大佬有遇到过没呢。

原生的spine设置参数后,要_updateMaterial()才会生效

3赞

这里发现一个问题,当spine导出的图片达到2张时,然后动作用到第二张图片上的资源时,闪白无效了,求解决

我也试了,spine的shader在android下没法动态改变属性

在3.x版本上无法使用,报 Error EFX2001: can not resolve ‘texture’;The “path” argument must be of type string or an instance of Buffer or URL. Received undefined;本人小白,不太清除要这么修复此报错

3.x 的话,可以参考这个

https://gitee.com/yeshao2069/cocos-creator-shader/tree/v3.6.x/demo/2d/Creator3.6.0_2D_HitWhite

1赞

点赞,就很强

markmarkmark