close
以上濾鏡的源碼,可以在文章末尾加我微信獲取。
效果圖用在春節上百花齊放

用在情人節上



愛心❤煙花,不僅春節可以放,情人節也可以放~
設計思路簡介首先,我們實現一個發光的粒子,代碼為
vec3burst(vec2st,vec2pos,floatr,vec3col){st-=pos;r=0.6*r*r;///發光效果return(r/dot(st,st))*col*0.6;}然後就是根據中學的物理知識,基於粒子一個上升的初速度,以及重力加速度的影響下逐漸變慢,繼而達到它所能達到的最大高度。
相關代碼如下
///s=p0+ut+0.5at^2///距離加速度公式vec2get_pos(vec2u,vec2a,vec2p0,floatt,floatang){///根據初始位置、水平和垂直的速度、加速度來更新當前的位置vec2d=p0+vec2(u.x*cos(ang),u.y*sin(ang))*t+0.5*a*t*t;returnd;}//t時刻的粒子速度vec2get_velocity(vec2u,vec2a,floatt,floatang){///根據加速度、當前水平和垂直的速度來更新當前的速度returnvec2(u.x*cos(ang),u.y*sin(ang))+a*t;}然後我們要考慮的是 —— 粒子達到一定高度後再發生爆(心形)爆炸,產生的新粒子的初始位置和速度。接着,還和之前一樣,垂直方向的位置和速度也要伴隨着重力加速度而繼續更新。
相關代碼為
///@note爆炸後的粒子擴散///當粒子停止上升,且粒子的當前時間已經達到了上升的時間if(v.y>-6.5&&v.y<0.0&&t_i>=t_up/*&&SPAWN==1*/){///把一個圓根據角度分成若干份扇形floatunit=(360./snp);for(floatj=0.0;j<snp;j++){floatang=rad(j*unit);floatr=0.035;///<心形粒子的半徑r-=(t_i-t_up)*R_RATIO;///<根據時間差來改變粒子的大小(變小)///--------------------------------------------------///@note根據(單位圓的)角度計算笛卡爾坐標floatx=cos(ang);//coordsofunitcirclefloaty=sin(ang);///心形公式y=y+abs(x)*sqrt((8.-abs(x))/50.0);///心形速度向量,隨着時間而變小vec2heart=vec2(x*x+y*y)*(0.4/(t_i*sqrt(t_i)));///根據心形的當前速度和加速度、初始位置等更新粒子的位置vec2S=get_pos(heart,acc*ACC_RATIO,h_max,t_i-(t_up),ang);///--------------------------------------------------//vec3pcol=colors[int(rand.x*float(NUM_COLS))];vec3pcol=vec3(1.);particles+=burst(uv,S,max(0.0,r),pcol);}}其中心形公式的函數示意圖為

根據它我們可以得到爆炸時每個粒子的初始位置。
值得注意的是,粒子的半徑(尺寸)也會隨着時間而逐漸變小
floatr=0.035;///<心形粒子的半徑r-=(t_i-t_up)*R_RATIO;///<根據時間差來改變粒子的大小(變小)完整代碼和詳細注釋//randomvaluevec2N22(vec2p){vec3a=fract(p.xyx*vec3(123.34,234.34,345.65));a+=dot(a,a+34.45);returnfract(vec2(a.x*a.y,a.y*a.z));}vec3burst(vec2st,vec2pos,floatr,vec3col){st-=pos;r=0.6*r*r;///發光效果return(r/dot(st,st))*col*0.6;}///s=p0+ut+0.5at^2///距離加速度公式vec2get_pos(vec2u,vec2a,vec2p0,floatt,floatang){///根據初始位置、水平和垂直的速度、加速度來更新當前的位置vec2d=p0+vec2(u.x*cos(ang),u.y*sin(ang))*t+0.5*a*t*t;returnd;}//t時刻的粒子速度vec2get_velocity(vec2u,vec2a,floatt,floatang){///根據加速度、當前水平和垂直的速度來更新當前的速度returnvec2(u.x*cos(ang),u.y*sin(ang))+a*t;}#definerad(x)radians(x)floatnp=100.;floatsnp=20.;floatR=0.032;floatR_RATIO=0.04;floatACC_RATIO=0.03;floatANG=90.;voidmainImage(outvec4fragColor,invec2fragCoord){vec2uv=(2.*fragCoord-iResolution.xy)/iResolution.y;floataspect=iResolution.x/iResolution.y;vec3col=vec3(0.0);floatt=mod(iTime,10.);vec2u=vec2(0.);///<初速度constvec2acc=vec2(0.0,-9.8);///<重力加速度accfloatang=rad(ANG);///<上升粒子的發射角度vec3particles=vec3(0.0);//particlefor(floati=0.;i<np;i++){floatr=R;vec2rand=N22(vec2(i));///@note爆炸前的粒子上升///初始位置vec2ip=vec2(sin(30.*rand.x)*aspect,-1.+r);///真正初始化速度u=vec2(sin(5.*rand.x),5.+sin(4.*rand.y));floatt_i=t-i/5.;///<時間差異化vec2s=get_pos(u,acc,ip,t_i,ang);vec2v=get_velocity(u,acc,t_i,ang);///計算豎直向上的運動時間floatt_up=u.y*sin(ang)/abs(acc.y);///根據時間計算出向上運動的最大高度vec2h_max=get_pos(u,acc,ip,t_up,ang);vec3pcol=vec3(1.,1.,1.);if(v.y<-0.5)///<下落速度超過一定大小則消失{r=0.0;///<隱藏}particles+=burst(uv,s,r,pcol);///<發射上升的粒子///@note爆炸後的粒子擴散///當粒子停止上升,且粒子的當前時間已經達到了上升的時間if(v.y>-6.5&&v.y<0.0&&t_i>=t_up/*&&SPAWN==1*/){///把一個圓根據角度分成若干份扇形floatunit=(360./snp);for(floatj=0.0;j<snp;j++){floatang=rad(j*unit);floatr=0.035;///<心形粒子的半徑r-=(t_i-t_up)*R_RATIO;///<根據時間差來改變粒子的大小(變小)///--------------------------------------------------///@note根據(單位圓的)角度計算笛卡爾坐標floatx=cos(ang);//coordsofunitcirclefloaty=sin(ang);///心形公式y=y+abs(x)*sqrt((8.-abs(x))/50.0);///心形速度向量,隨着時間而變小vec2heart=vec2(x*x+y*y)*(0.4/(t_i*sqrt(t_i)));///根據心形的當前速度和加速度、初始位置等更新粒子的位置vec2S=get_pos(heart,acc*ACC_RATIO,h_max,t_i-(t_up),ang);///--------------------------------------------------vec3pcol=vec3(1.);particles+=burst(uv,S,max(0.0,r),pcol);}}}col=particles;fragColor=vec4(col,1.0);}通過以上代碼則可以實現以下「核心」效果

經過少許的修改,則達到文章開頭的效果,更多有趣效果,敬請關注 ShaderJoy 專欄的其他文章。
-- END --
進技術交流群,掃碼添加我的微信:Byte-Flow
獲取視頻教程和源碼
推薦:
FFmpeg 音視頻和 OpenGL ES 乾貨匯總
抖音傳送帶特效是怎麼實現的?
所有你想要的圖片轉場效果,都在這了
面試官:如何利用 Shader 實現 RGBA 到 NV21 圖像格式轉換?
我用 OpenGL ES 給小姐姐做了幾個抖音濾鏡
全站熱搜