【小不溜】Shader学习之流动背景

以后在论坛我(wing)还是用我吃鸡的id:小不溜,用中文ID,用国产引擎

游戏中,流动图标的背景应该是常用需求,有的同学喜欢用动画实现,这里简单的用shader实现一版,线上效果图:
GIF 2023-9-21 16-48-30

参数很简单,就一个角度,一个重复次数,一个速度

核心函数,将uv进行旋转,然后朝一个方向移动就行了

vec2 rotateUV(vec2 uv, float rotation, float repeat) {
    uv -= 0.5;
    float r = length(uv);
    float s = sin(rotation);
    float c = cos(rotation);
    mat2 m = mat2(c, -s, s, c);
    uv = m * uv;
    uv += 0.5;
    uv.y += speed * cc_time.x;
    return uv * repeat;
  }

一下是完整shader

// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
CCEffect %{
  techniques:
  - passes:
    - vert: sprite-vs:vert
      frag: sprite-fs:frag
      depthStencilState:
        depthTest: false
        depthWrite: false
      blendState:
        targets:
        - blend: true
          blendSrc: src_alpha
          blendDst: one_minus_src_alpha
          blendDstAlpha: one_minus_src_alpha
      rasterizerState:
        cullMode: none
      properties:
        alphaThreshold: { value: 0.5 }        
        angle:          { value: 0.0, editor: { type: float, min: -360.0, max: 360.0, step: 1.0 } }
        repeat:         { value: 1, editor: { type: vec2, min: 1.0, max: 100.0, step: 1 } }
        speed:          { value: 1, editor: { type: vec2, min: -10.0, max: 10.0, step: 1 } }
}%

CCProgram sprite-vs %{
  precision highp float;
  #include <builtin/uniforms/cc-global>
  #if USE_LOCAL
    #include <builtin/uniforms/cc-local>
  #endif
  #if SAMPLE_FROM_RT
    #include <common/common-define>
  #endif
  in vec3 a_position;
  in vec2 a_texCoord;
  in vec4 a_color;

  out vec4 color;
  out vec2 uv0;

  vec4 vert () {
    vec4 pos = vec4(a_position, 1);

    #if USE_LOCAL
      pos = cc_matWorld * pos;
    #endif

    #if USE_PIXEL_ALIGNMENT
      pos = cc_matView * pos;
      pos.xyz = floor(pos.xyz);
      pos = cc_matProj * pos;
    #else
      pos = cc_matViewProj * pos;
    #endif

    uv0 = a_texCoord;
    #if SAMPLE_FROM_RT
      CC_HANDLE_RT_SAMPLE_FLIP(uv0);
    #endif
    color = a_color;

    return pos;
  }
}%

CCProgram sprite-fs %{
  precision highp float;

  #include <builtin/internal/embedded-alpha>
  #include <builtin/internal/alpha-test>
  #include <builtin/uniforms/cc-global>

  in vec4 color;

  #if USE_TEXTURE
    in vec2 uv0;
    #pragma builtin(local)
    layout(set = 2, binding = 12) uniform sampler2D cc_spriteTexture;
  #endif

  uniform Constant {
    float repeat;
    float angle;
    float speed;
  };

  vec2 rotateUV(vec2 uv, float rotation, float repeat) {
    uv -= 0.5;
    float r = length(uv);
    float s = sin(rotation);
    float c = cos(rotation);
    mat2 m = mat2(c, -s, s, c);
    uv = m * uv;
    uv += 0.5;
    uv.y += speed * cc_time.x;
    return uv * repeat;
  }
  
  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      vec2 uv = rotateUV(uv0, radians(angle), repeat);
      o *= CCSampleWithAlphaSeparated(cc_spriteTexture, uv);
      #if IS_GRAY
        float gray  = 0.2126 * o.r + 0.7152 * o.g + 0.0722 * o.b;
        o.r = o.g = o.b = gray;
      #endif
    #endif

    o *= color;
    ALPHA_TEST(o);
    return o;
  }
}%

用法:
创建材质球,使用此shader,然后赋给sprite的自定义材质:

Tips:
纹理的拼接模式需要改成:重复-repeat
且纹理不能参与合图

希望对大家有所帮助!!

12赞

好好好,码一下。确实很常用

收藏后 礼貌回复 + 1


吔?为什么我是这样子的

原来还要设置拼接模式

必然的,而且还不能合图

美得很美得很

这个既强大又实用

额,移植到2.4.8开启repeat的时候报错:image

2.4.8是在这里勾选么image

果断换了一张64x64的图片,成功了。ccc

字节小游戏runtime异常,只显示一点点
后续:
错怪老哥了,老哥对不起
我贴图尺寸有问题

真的6666

嗯,有的平台不支持非2幂,处理下就行了

自己要用,翻出来看看

mask 一下