转场shader分享

摘要

根据论坛孙二喵大佬分享的3.x的转场特效进行改成2.4.15可以使用的shader,理论上2.4的都可以使用吧。

开始

效果演示:

使用方法:

创建一个材质球要选择当前过度场景的shader然后设置图片大小(screenSize),并且选择要过滤到的图像纹理(subTexture),也可以设置方块大小(tranSize)

Shader代码和使用方法:
CCEffect %{
  techniques:
  - passes:
    - vert: vs
      frag: fs
      blendState:
        targets:
        - blend: true
      rasterizerState:
        cullMode: none
      properties:
        texture: { value: white }
        alphaThreshold: { value: 0.5 }
        screenSize: { value: [ 720, 1280 ] }
        subTexture: { value: grey }
        tranSize: { value: 36 }
        progression: { value: 0 }
}%
 
 
CCProgram vs %{
  precision highp float;
 
  #include <cc-global>
  #include <cc-local>
 
  in vec3 a_position;
  in vec4 a_color;
  out vec4 v_color;
 
  #if USE_TEXTURE
  in vec2 a_uv0;
  out vec2 v_uv0;
  #endif
 
  void main () {
    vec4 pos = vec4(a_position, 1);
 
    #if CC_USE_MODEL
    pos = cc_matViewProj * cc_matWorld * pos;
    #else
    pos = cc_matViewProj * pos;
    #endif
 
    #if USE_TEXTURE
    v_uv0 = a_uv0;
    #endif
 
    v_color = a_color;
 
    gl_Position = pos;
  }
}%
 
 
CCProgram fs %{
  precision highp float;
 
  #include <alpha-test>
  #include <texture>
 
  in vec4 v_color;
 
  #if USE_TEXTURE
  in vec2 v_uv0;
  uniform sampler2D texture;
  #endif
 
  uniform UBO_1 {
    //屏幕尺寸,用来计算格子的尺寸
    vec2 screenSize;
    //progression 控制了过渡的进度,从 0 到 1。在 progression 值为 0 时,显示的是原图;当 progression 为 1 时,显示的是新图。
    float progression = 0;
    //过渡是通过格子状的更新方式进行的,格子的大小由 tranSize 控制。每个像素位置的判断决定了是否显示原图或新图
    float tranSize;
  };
 
 
  uniform sampler2D subTexture;
 
  vec4 BoxTransition(vec4 color, vec4 mixcolor, vec2 uv, float progression) {
    vec2 fragCoord = gl_FragCoord.xy;
 
    fragCoord.y = screenSize.y - fragCoord.y; // 反转y轴,使其从上到下
 
    vec2 blockPos = vec2(progression) * screenSize.xy; // 计算当前过渡进度所在的格子位置
    vec2 p = ceil(fragCoord / tranSize) * tranSize; // 计算当前像素所属的格子位置
 
    // 计算进度,基于格子的相对位置
    float progress = (p.x + p.y) / (blockPos.x + blockPos.y);
 
    vec2 v = abs(fragCoord - p + vec2(tranSize / 2.));
 
    // 使用格子更新效果,若进度较高,则显示新图
    if (max(v.x, v.y) * progress < tranSize / 2.) {
      color = mixcolor;
    }
 
    return color;
  }
 
  void main () {
    vec4 o = vec4(1, 1, 1, 1);
 
    #if USE_TEXTURE
      CCTexture(texture, v_uv0, o); // 显示原图
    #endif
 
    vec4 mixColor = vec4(1, 1, 1, 1);
    CCTexture(subTexture, v_uv0, mixColor); // 显示新图
 
    o = BoxTransition(o, mixColor, v_uv0, progression); // 进行过渡
 
    o *= v_color; // 混合颜色
 
    ALPHA_TEST(o);
 
    #if USE_BGRA
      gl_FragColor = o.bgra;
    #else
      gl_FragColor = o.rgba;
    #endif
  }
}%

在需要用到转场过度的地方进行调用代码

 	// 初始值设置为 0
 	let start = { num: 0 }; 
 	// 目标值设置为 1
	let end = { num: 1 };
	// 获取节点上的Material,各版本可能存在差异
    let sprite = this.node.getComponent(cc.Sprite);
    let mat = sprite.getMaterial(0);
    // 利用tween进行过渡
    cc.tween(start)
      .delay(0.0010)
      .to(1.5, end, {
          onUpdate(target:any, ratio:any) {
              // 根据动画的进度比例来更新
              mat.setProperty("progression", target.num);
          },
      })
      .start();
5赞

只有背景吗?能先截图,再转场吗

肯定可以的,看这个大佬的分享https://forum.cocos.org/t/topic/93743