水波擴散效果(shader)

水波擴散是一個比較好看的交互效果,特別是在某些以水爲故事發生場景的遊戲中,擴散的水波會讓場景更加栩栩如生web

demo

實現思路

若是水波靜止,咱們看到的實際上是像素點圍繞着某個中心點的拉伸效果,咱們只需讓每一個像素點疊加上它和中心點的向量差,就可以呈現出畫面上的全部像素圍繞中心點的拉伸感。canvas

void main() {
 vec2 uv = normalize(vec2(0.50.5) - v_uv0) * 0.2 + v_uv0;
  gl_FragColor = texture(texture, uv);
}
demo

這個時候若是咱們加上時間參數,咱們就能夠獲得一個往外不停井噴的「黑洞」:微信

void main() {
 vec2 uv = normalize(vec2(0.50.5) - v_uv0) * 0.2 * cc_time.x + v_uv0;
  gl_FragColor = texture(texture, uv);
}
掏空式往外涌

可是水波往外擴散是呼吸燈式的一波波往外涌,並且不是這種無盡式的一直把東西往外掏的感受,因此咱們要給cc_time.x加上一個週期性的變化,讓它能表現出這種週期性的往外擴散的感受。app

void main() {
 vec2 uv = normalize(vec2(0.50.5) - v_uv0) * 0.2 * sin(cc_time.x) + v_uv0;
  gl_FragColor = texture(texture, uv);
}
週期性往外涌

這種呼吸燈式的涌動其實和咱們的最終效果有很大區別,由於它永遠在循環涌動,可是咱們的水波是從中心擴散出去以後,中間部分就再也不動了的,怎麼讓中間的像素再也不屢次涌動呢?若是把一圈水波比做圓,那水波的擴散行爲其實就是這個圓的半徑在不斷的增大,圓外面的波紋有效,圓裏面的波紋靜止。所以咱們能夠多加一個距離取樣,像素離擴散中心的距離大於半徑才保留不然丟棄,而這個半徑從零開始逐漸增大。async

void main() {
  vec2 distance_vec = vec2(0.50.5) - v_uv0;
  float sin_factor = sin(cc_time.x) * 0.2;

  float wave_radius = 0.3;
  float distance = sqrt(distance_vec.x * distance_vec.x + distance_vec.y * distance_vec.y);
  // 其中waveOffset是隨時間增加的,經過外部傳入
  float dis_factor = clamp(wave_radius - abs(distance - wave_offset), 0.01.0);

  vec2 uv = v_uv0 + normalize(distance_vec) * sin_factor * dis_factor;
  gl_FragColor = texture(texture, uv);
}
未調優效果

接下來的就是參數的調試,主要是三角函數的採樣那裏,咱們但願水波可以產生多個波動,因此咱們須要乘上必定的倍數,讓函數的做用範圍足夠大,纔能有足夠多的波峯谷底。另外就是sin函數的輸出值域在(-1, 1)之間,因此咱們的輸出也須要縮小必定的倍數,才能讓函數的峯值變化處於一個合理的範圍編輯器

void main() {
  vec2 distance_vec = center - v_uv0;
  distance_vec = distance_vec * vec2(canvas_size.x / canvas_size.y, 1.0);
  float distance = sqrt(distance_vec.x * distance_vec.x + distance_vec.y * distance_vec.y);

  // distance小於1,可是咱們但願能有多個波峯波谷,因此在sin的內部乘上一個比較大的倍數
  // sin函數的值在-1到1之間,咱們但願偏移值很小,因此輸出的時候須要縮小必定的倍數倍
  float sin_factor = sin(distance * 100.0 + cc_time.x) * 0.05;
  float discard_factor = clamp(wave_radius - abs(wave_offset - distance), 0.01.0);

  // 計算總的uv的偏移值
  vec2 offset = normalize(distance_vec) * sin_factor * discard_factor;
  vec2 uv = offset + v_uv0;

  gl_FragColor = texture(texture, uv);
}
demo

效果預覽

源碼獲取請點擊查看原文,長按二維碼查看效果👇函數

ewm

我是異名,你的閱讀是個人動力ui



 

溶解效果(shader)   追光效果(shader)   
url

放大鏡效果     微信小遊戲首包超出4M以後  spa

移動殘影效果    刮刮卡實現    子彈跟蹤效果

遙控杆實現    背景無限滾動   鏡面光澤效果(shader)

金幣落袋效果    富文本打字機效果

圓形頭像(shader)   Cocos遊戲開發入門最佳實踐

使用cocos進行2D和3D混合開發 


本文分享自微信公衆號 - 異名(async-code)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索