前端實現旗幟飄動效果系列 (Ⅴ):pixi.js實現

時隔兩年,繼續完成這個系列,現在回顧一下兩年前的這篇文章 前端實現旗幟飄動效果系列 (Ⅳ):webgl實現 ,發現自己當初對webgl的理解不透徹,產生了很多紕漏,也走了不少歪路,實際上使用shader有更方便的實現方法,新的思路不再需要做複雜的仿射,只需通過簡單的三角函數控制片元着色器的採樣位置即可。

核心是pixi過濾器PIXI.Filter以及片元着色器。

① PIXI.Filter類可以忽略頂點着色器,因爲pixi.js內置了一套默認的頂點着色器,如果傳入空,就是用該着色器模板(pixi v5版):

attribute vec2 aVertexPosition;

uniform mat3 projectionMatrix;

varying vec2 vTextureCoord;

uniform vec4 inputSize;
uniform vec4 outputFrame;

vec4 filterVertexPosition( void )
{
    vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;

    return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);
}

vec2 filterTextureCoord( void )
{
    return aVertexPosition * (outputFrame.zw * inputSize.zw);
}

void main(void)
{
    gl_Position = filterVertexPosition();
    vTextureCoord = filterTextureCoord();
}

aVertexPosition 是歸一化有過濾區域的座標

vTextureCoord 是歸一化後貼圖的座標

aVertexPosition * outputFrame.zw 過濾器區域的座標,單位是像素,但是原點是區域左上角而非屏幕左上角

vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy 表示屏幕的座標,單位是像素

② PIXI.Filter 如果不傳入片元着色器,則使用下面的着色器模板:

varying vec2 vTextureCoord;

uniform sampler2D uSampler;

void main(void){
   gl_FragColor = texture2D(uSampler, vTextureCoord);
}

vTextureCoord 是從頂點着色器傳入的歸一化後貼圖的座標

這裏我們不能使用默認,需要對它進行修改:

varying vec2 vTextureCoord;// 區間[0,1]

uniform sampler2D uSampler;

uniform float time;
uniform float period;// 週期
uniform float velocity;// 波速
uniform float amplitude;// 最大振幅
uniform float brightness;// 高光亮度

float PI = 3.14159;

void main(void){
  float v = sin((vTextureCoord.x - time * velocity) * 2.0 * PI * period);
  vec4 color = texture2D(uSampler, vTextureCoord + vec2(0.0, v * amplitude * vTextureCoord.x));

  if (color.a > 0.0) {
    // 取x正方向+0.001,獲取函數單調性
    float delta = sin((vTextureCoord.x + 0.001 - time * velocity) * 2.0 * PI * period) - v;
    if (delta < 0.0) {
      color = mix(color, vec4(1.0), -delta * brightness);
    }
  }
  gl_FragColor = color;
}

v 是根據橫座標,以及傳入的週期計算出來的正弦波形

texture2D(uSampler, vTextureCoord + vec2(0.0, v * amplitude * vTextureCoord.x)) 中乘以vTextureCoord.x是爲了讓振幅根據橫座標遞增

delta 是取x軸正方向+0.001位置的函數值,獲取函數在該位置的單調性

mix(color, vec4(1.0), -delta * brightness) 通過mix函數,以brightness入參把原色值與白色混合

 

爲了調試方便,我添加了dat.gui插件,最終效果如圖:

如果本文對您有幫助還請點個贊😁

 完整代碼戳這裏

在線演示1在線演示2

目錄指引:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章