Cocos Shader 高性能转场特效合集!免费开源!二次元卡牌必备!

COCOS

共 5917字,需浏览 12分钟

 ·

2023-07-10 04:22

引言:Cocos Creator 3.8.0 正式版本正在紧锣密鼓地准备中。在等待新版本的同时,社区的高产大户孙二喵同学给大家带来了 7 种炫酷的 Cocos Shader 转场特效方案,并附带了源码。

本文是孙二喵用 AIGC 制作的卡牌游戏项目中的产物,有兴趣的同学可以查看之前的文章: AIGC 制作 3D 贪吃蛇游戏  和  AIGC 制作卡牌游戏

前言

我利用 AIGC 工具配合 Cocos Creator 制作的卡牌游戏项目已接近尾声。

但最近遇到一个很头疼的问题,就是如何又流畅、又生动地实现转场效果。

在经过一番摸索后,最终我使用了 Cocos Shader 来实现,借助 GPU 的运算能力,这些转场特效可以高效地运行在各个平台。

在这个过程中,我实验了多个效果,一共写了 7 个转场特效,现在分享给大家,希望对大家有所帮助。

预览地址: http://learncocos.com/shader1/

5d1129b1d746117a498ddaf93cfa7a45.webp

接下来就让我们看看具体的实现以及对应的效果。

注意:参与转场效果的图片不能参与合图,合图会因为 UV 被转换导致效果不对。在 Assets 中选择对应图片,在属性面板中取消勾选 Packable 属性即可。

01 线性转场

转场的 Shader 需要两张图片,主图片使用默认的精灵,需要转场的图片,我们可以新建一个 subTexure 属性。

989a31d5018f7e4825df753cf430d565.webp

线性转场效果相对比较简单,关键的 Shader 代码如下:

      
        #include <builtin/uniforms/cc-global>

const float tranSize = 0.1; 
vec4 LinearTransition(vec4 color,vec4 mixcolor, vec2 uv, float progression,bool isUVX) {
  float dir = isUVX?uv.x:uv.y;
  float f = dir*(1.0-tranSize) + tranSize - (progression * (1.0 + tranSize));
  float m = smoothstep(0., -tranSize,f);
  color = mix(color,mixcolor,m);
  return color;
}

这里使用了 smoothstep 函数,我们先看下 smoothstep 的源码:

      
        float smoothstep(float t1, float t2, float x) {
  // Scale, bias and saturate x to 0..1 range
  x = clamp((x - t1) / (t2 - t1), 0.0, 1.0); 
  // Evaluate polynomial
  return x * x * (3 - 2 * x);
}

从源码中可以看出,它根据 x 在 t1 和 t2 之间的距离,返回 [0,1] 的平滑过渡值。

这里使用了 f = dir *(1-s)+s-p*(1+s) 使选定的 uv 轴向,返回在进度参数下的 混合系数

最终实现的效果如下:

46378159d0c133d43833aae1ff26c7bb.webp

02 风吹线性过度

在线性转场的基础上加入随机的风吹效果,Cocos Shader 代码如下:

      
        #include <builtin/uniforms/cc-global>

// Variables
const float tranSize = 0.25; 

float rand (vec2 co) {
  return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

vec4 WindTransition(vec4 color,vec4 mixcolor, vec2 uv, float progression) {
  float r = rand(vec2(0, uv.y));
  float m = smoothstep(0.0, -tranSize, uv.x*(1.0-tranSize) + tranSize*r - (progression * (1.0 + tranSize)));
  color = mix(color,mixcolor,m);
  return color;
}

最终实现的效果如下:

9c95855ddad2286e7b0ca1e3d605bec3.webp

03 圆形过度

      
        #include <builtin/uniforms/cc-global>

float rule(vec2 coord)
{
    vec2 uv2 = coord - vec2(0.5, 0.5);
    float angle = atan(uv2.x, uv2.y);
    return angle / 2.0 / 3.1416 + 0.5;
}

vec4 CircleTransition(vec4 color,vec4 mixcolor, vec2 uv, float progression) {
  float rule = rule(uv);
  float vague = 0.2;
  float phase = progression * (1.0 + vague);
  float p0 = smoothstep(rule, rule + vague, phase);
  color = color * (1.0 - p0) + mixcolor * p0;
  return color;
}

效果见下:

da264fe08e32ad737f5b4a125b6c489b.webp

04 随机方块过度

      
        float smoothness = 0.5; // 0-1

float rand (vec2 co) {
  return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
const float tranSize = 10.;

vec4 RandomTransition(vec4 color,vec4 mixcolor, vec2 uv, float progression) {
  float r = rand(floor(vec2(tranSize) * uv));
  float m = smoothstep(0.0, -smoothness, r - (progression * (1.0 + smoothness)));
  color=  mix(color, mixcolor, m);
  return color;
}

效果见下: 52180a31d2c1cd09094ca0d41282fbb8.webp

05 规则方块过度

这个效果来自 shadertoy

      
        #include <builtin/uniforms/cc-global>

const float tranSize = 32.;

vec4 BoxTransition(vec4 color,vec4 mixcolor, vec2 uv, float progression) {
  vec2 fragCoord = gl_FragCoord.xy;
  vec2 blockPos = vec2(progression) * cc_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;
}

效果见下: b3b5613d9111af6f534fb06eac8cbc7b.webp

06 棱形过度

      
        #include <builtin/uniforms/cc-global>

const float tranSize = 32.;

vec4 SideTransition(vec4 color,vec4 mixcolor, vec2 uv, float progression) {
  uv.x = 1.0 - uv.x;
  float xFraction = fract(gl_FragCoord.x / tranSize);
  float yFraction = fract(gl_FragCoord.y / tranSize);
  
  float xDistance = abs(xFraction - 0.5);
  float yDistance = abs(yFraction - 0.5);

  if (xDistance + yDistance + uv.x + uv.y < progression * 4.0) {
      color = mixcolor;
  }
  return color;
}

效果演示: dd78a74627fc4c1183c26474afd1a7bb.webp

07 燃烧转场

注意:此效果由于未使用第二张图,因此可以合图

      
        float fr(vec2 c, float seed) 
{
return fract(43.0 * sin(c.x + 7.0 * c.y) * seed);
}

float fn(vec2 p, float seed)
{
    vec2 i = floor(p), w = p - i, j = vec2(1.0, 0.0);
    w = w * w * (3.0 - w - w);
    return mix(mix(fr(i, seed), fr(i + j, seed), w.x), mix(fr(i + j.yx, seed), fr(i + 1.0, seed), w.x), w.y);
}

float fa(vec2 p, float seed) 
{
    float m = 0.0, f = 2.0;
    for (int i = 0; i < 6; i++) {
    m += fn(f * p, seed) / f; 
    f += f;
    }
    return m;
}
vec4 BurnOut(vec4 MainColor, vec2 UV, float Intensity) 
{
    float t = fract(Intensity * 0.9999);
    float cc = smoothstep(t / 1.2, t + 0.1, fa(3.5 * UV, 1.));
    vec4 c = vec4(cc);
    c = MainColor * c;
    c.r = mix(c.r, c.r * 15.0 * (1.0 - c.a) * 8.0, Intensity);
    c.g = mix(c.g, c.g * 10.0 * (1.0 - c.a) * 4.0, Intensity);
    c.b = mix(c.b, c.b * 5.0 * (1.0 - c.a), Intensity);
    return vec4(c.rgb, c.a);
}

演示效果: 29679e612c22f35bbd447f8bf1c5e4d4.webp

你可以把这些效果,应用于画面截图、场景切换、战斗开始、卡牌溶解、抽奖系统等等。

希望上面的分享能够给大家的项目带来效果和开发效率上的提升,使大家可以用 Cocos Creator 更快地制作出更好的产品。

08 代码下载

上面的源码已在 Cocos Store 上免费开源!

3c01eeacf3eed3b699c07f01c54b0242.webp

今天的分享就到这里,快去下载吧!点击阅读原文可直达源码页面。


浏览 96
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报