iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 22
1
Modern Web

寫給工程師的 WebGL 學習心得系列 第 22

[WebGL - Day22] PixiJS 裡實作圓形淡入效果濾鏡

  • 分享至 

  • twitterImage
  •  

今天組合幾個先前介紹過的部分:

  • Fragment Shader 畫圓
  • 遮罩、Uniform
  • PixiJS 濾鏡

實作: PixiJS 圓形淡入效果
PixiJS Shader Fade

1- 在 Shadertoy 裡畫圓:

PixiJS Shader Fade

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord/iResolution.xy;
    uv -= 0.5;
    uv.x *= iResolution.x / iResolution.y;

    bool uDebugMode = false;
    float uRadius = 0.5;
    float uSmooth = 0.1;
    float d = length(uv);
    
    float c = smoothstep(uRadius, uRadius-uSmooth, d);
    
    fragColor = vec4(vec3(c), 1.0);
}

2- Debug 模式:

PixiJS Shader Fade
雖然非必要,但我想做 Debug 模式 (也方便說明)
uDebugModetrue 的時候,右邊遮罩為全白

在 Shadertoy 裡的實作:
PixiJS Shader Fade

其中有三個變數會透過 JavaScript 傳入:

  • bool uDebugMode = false; // Debug 用
  • float uRadius = 0.5; // 遮罩半徑
  • float uSmooth = 0.1; // 遮罩柔邊半徑
float c = smoothstep(uRadius, uRadius-uSmooth, d); // 剛剛的畫圈

float mask = 0.;
if( debugMode == true){
  if(uv.x >= 0. ){
    mask = 1.;
  }else{
    mask = c;
  }
}else{
  mask = c;
}  
  • 定義 float mask 的遮罩(類似 Photoshop 裡的 遮色片 的概念):
    由於遮罩只需要 黑白 一個色版,使用 float 就可

Debug 模式時右半邊全白,左邊為原本的圓形:

if(uv.x >= 0. ){
  mask = 1.;
}else{
  mask = c;
}

uv.x 的位置已調整過,uv.x >= 0. 就是畫面右半邊的意思

註: Shader 裡判斷 等於==,不是 ===

遮罩

PixiJS Shader Fade
圖片與遮罩:
與先前相同,在 iChannel0 選了圖片後,
輸出時使用圖片 遮罩,運算出最後的結果

vec4 texture_pic = texture(iChannel0, uv);
fragColor = vec4(texture_pic) * mask;

回到 PixiJS:

Debug 使用以前介紹過的 dat.GUI
介紹文:使用 dat.GUI 工具除錯

var gui = new dat.GUI();
effectController = {
  DebugMode: uDebugMode,
  Smooth: uSmooth
};
gui.add( effectController, 'DebugMode' ).onChange( modeChange );
gui.add( effectController, 'Smooth', 0, 1, 0.01 ).onChange( smoothChange );
function modeChange(){
  uDebugMode = effectController.DebugMode;
  //...
};
function smoothChange(){
  uSmooth = effectController.Smooth;
  //...
};

將有變化的 uDebugModeuSmooth 再帶進 Fragment Shader 裡,
就能控制 Debug 模式開/關 、柔邊遮罩的半徑

背景變化:

另一個透過 JavaScript 帶給 Fragment Shader 的值是 uRadius

TweenMax.to(this, 4,{tweenValue:1, repeat:-1, ease:Strong.easeOut, onUpdate:function(){
		uRadius = this.target.tweenValue;
	},onRepeat:function(){
		// change BG
	}
});

動畫本身使用 TweenMax 控制背景變換
淡入動態使用 TweenMax 更新 uRadius 並帶入 Fragment Shader

畫面上同時有兩個背景:
一個是舊的背景
一個是淡入的背景
舊背景一直在下方,當 TweenMax Repeat 時,
原本淡入的新背景會變成舊背景,另一個新背景在上層淡入出現
濾鏡只需套在 新背景 上即可


如果不是 WebGL 的情況,
要做到類似模糊遮罩的效果,運算上可能會叫吃較能


PixiJS 裡,調整 uv 的方式有點麻煩,
PixiJS v4v5 裡的寫法也不太相同,本篇沒列到細節


上一篇
[WebGL - Day21] Shadertoy + PixiJS,電視雜訊效果實作
下一篇
[WebGL - Day23] Ascii Filter 與實作
系列文
寫給工程師的 WebGL 學習心得30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言