這是我參與8月更文挑戰的第5天,活動詳情查看: 8月更文挑戰算法
其中關鍵須要用到的 iChannel0 是一幅由一系列連貫動做的 2233 娘組成的序列幀圖像,以下圖所示markdown
因爲咱們能夠提早知道設計師給定的一維序列幀紋理其中包含了多少幀的動畫(2233 孃的話就是 7 幀),因此咱們能夠對 uv 座標進行手動劃分。 接下來主要的核心思想就是在不一樣的時刻可以顯示出序列幀紋理 「下一幀」 的圖像內容。app
GLSL 代碼與詳細算法註釋以下:函數
#iChannel0 "file://../images/bilibili.png"
#iUniform vec2 off = vec2(0.33, 0.15) in {vec2(0., 0.), vec2(1., 1.)}
#iUniform float scale = 1. in {0.1, 4.}
const float FRMS = 7.;
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 p = vec2(fragCoord.xy / iResolution.xy) ;
// 控制 2233 孃的上升的 uv
// vec2 uv = vec2( p.x + mod(iTime, FRMS * 10.), p.y );
vec2 uv = vec2( p.x, p.y - mod(iTime, FRMS * 10.) );
// 從新計算uv,比例和位置的調整
uv = (uv - off) * vec2(scale);
// uv = clamp( uv, 0.0, 1.0 );
// 控制切換到下一幀, floor 很重要
float ofx = floor( mod( iTime * 20.0, FRMS ) );
// 換算單幀 2233 孃的大小 (uv scale)
float ww = 1.0 / FRMS;
// 將偏移後的 uv 換算到單隻 2233 孃的位置,不然會把下一幀一併顯示出來
uv.x = ( uv.x + ofx) * ww;
vec4 fg = texture2D( iChannel0, uv );
// fragColor = fg; ///< 直接顯示透明通道可能有問題
// fragColor = vec4(fg.a); ///< 測試
fragColor = vec4(mix(vec3(.9), fg.xyz, fg.a), 1.);
}
複製代碼
相似的,咱們能夠更進一步實現如下效果post
iChannel0 是一幅由一系列連貫動做的彩虹貓組成的序列幀圖像,以下圖所示測試
所使用的一維幀動畫,這部分原理和 2233 孃的序列幀動畫相同,只不過序列幀圖像的幀數變爲了 6 。動畫
iChannel1 是任意一副背景圖像,這也是和 2233 娘效果的最大區別 —— 多了須要與背景圖片進行混合,以及用代碼繪製的抖動彩虹效果。其中彩虹效果的核心思想是在不一樣高度即不一樣層的彩虹經過 sin 函數來模擬。ui
GLSL 代碼與詳細算法註釋以下:url
uniform float iGlobalTime;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
vec2 iResolution = vec2(512., 512.);
void main() {
vec2 p = vec2(gl_FragCoord.x/ iResolution.x, gl_FragCoord.y/ iResolution.y) ;
// 背景滾動的uv
vec2 uv = vec2( p.x+mod(iGlobalTime,2.0), p.y );
vec3 bg = vec3(0.0,51.0/255.0,102.0/255.0);
float f = texture2D( iChannel1, uv ).x;
f = f*f;
bg = mix( bg, vec3(1.0), f );
float a = 0.01*sin(40.0*p.x + 40.0*iGlobalTime);
float h = (a+p.y-0.3)/(0.7-0.3);
// 彩虹的位置
if( p.x<0.6 && h>0.0 && h<1.0 )
{
// 彩虹的寬度
h = floor( h*6.0 );
// 在不一樣高度繪製彩虹
bg = mix( bg, vec3(1.0,0.0,0.0), 1.0 - smoothstep( 0.0, 0.1, abs(h-5.0) ) );
bg = mix( bg, vec3(1.0,0.6,0.0), 1.0 - smoothstep( 0.0, 0.1, abs(h-4.0) ) );
bg = mix( bg, vec3(1.0,1.0,0.0), 1.0 - smoothstep( 0.0, 0.1, abs(h-3.0) ) );
bg = mix( bg, vec3(0.2,1.0,0.0), 1.0 - smoothstep( 0.0, 0.1, abs(h-2.0) ) );
bg = mix( bg, vec3(0.0,0.6,1.0), 1.0 - smoothstep( 0.0, 0.1, abs(h-1.0) ) );
bg = mix( bg, vec3(0.4,0.2,1.0), 1.0 - smoothstep( 0.0, 0.1, abs(h-0.0) ) );
}
// 從新計算uv,比例和位置的調整
uv = (p - vec2(0.33,0.15)) / (vec2(1.3, 1.) - vec2(0.33,0.15));
uv = clamp( uv, 0.0, 1.0 );
// 控制彩虹貓圖像的偏移, floor很重要
float ofx = floor( mod( iGlobalTime*10.0*2.0, 6.0 ) );
// 換算單隻彩虹貓的紋理大小 (uv scale)
float ww = 31.0/200.0;
// uv.y = 1.0-uv.y;
// 將偏移後的uv換算到單隻彩虹貓的紋理大小,不然會把以後的彩虹貓一併顯示出來
uv.x = clamp( ( uv.x + ofx)*ww, 0.0, 1.0 );
vec4 fg = texture2D( iChannel0, uv );
vec3 col = mix( bg, fg.xyz, .8 );
gl_FragColor = vec4( col, 1.0 );
}
複製代碼
還能夠進一步引伸到二維幀動畫 爆炸火焰spa
所使用的二維幀動畫