用shader做一个柿子颜色的过场动画
想要提高編寫shader的水平,需要不斷學習和練習。
跪著看完大神們的shadertoy作品后打算自己找個軟柿子捏一捏。想了半天打算實現一下Nintendo Switch主機進eShop時的過場動畫,仔細一看個過場的顏色和柿子還有點像,。本文將各個技術點整理分享給大家。
先來看一下原效果:
(eShop禁用主機錄屏,視頻為手機錄制)
效果概括(可跳過)
原效果中有四種顏色輪流出現,并且互相覆蓋,在視覺上有一種層次感。
在第一層播放過程中,第二層就已經出現,最多同時出現三種顏色。
四種顏色輪播完畢后動畫暫停一小段時間,接著重新播放。第四種顏色和一開始的背景色相同,所以動畫首尾連接。
入場的形狀是階梯造型,并且階梯的距離在屏幕兩邊時比較窄,運行到屏幕中間時最大。
實現方案
運動軌跡
從原效果上看,運動時有緩入和緩出。
先簡化處理,只控制某個顏色出場時第一個像素的?x?位置,選擇?-cos(t)? 作為運動的速度曲線。
對應地,將屏幕的x范圍映射到(-1, 1)區間,x = 0的位置在屏幕中下方。
時間分片
控制某個顏色的動畫是否顯示的邏輯,采用“遮罩”的方式。原理和上一篇的“帶通”類似。只不過這里的“遮罩”不是處理空間,而是處理時間。
可以理解為四個顏色的動畫無時無刻都在自己運行,當時間處于某個區間內時,對應的顏色才會被畫出來。
按順序分配各顏色的出場時間,第一種顏色出場時間是0,第二種顏色是T1 = PI,第三種是T2 = 2PI,以此類推,第四種顏色播放完畢后是4PI。
實際運行時間不是4PI也沒有關系,對全局時間?iTime?進行縮放可以很方便控制整體動畫的節奏,所以4PI更像是一個邏輯時間單位。
階梯造型
階梯造型的規律性很強,可以看出是對y坐標做離散化拆成“行”,然后對各“行”進行一定的偏移。
// 對y離散化 float offsety = floor(uv.y * GRID_COUNT) / GRID_COUNT;// 時間t進行offsety偏移,為了避免在t = 0時出現負數導致三角函數“反彈”,做了clamp處理 mask = 1.0 - step(-cos(clamp(t - offsety, 0., TOTAL_TIME)), uv.x); col = mix(col, C1, mask);處理顏色交叉
本文一開始提到會有同屏出現三種顏色的情況。仔細觀察效果可以發現在第一種顏色到達末端前第二種顏色已經出場了。要處理這種情況只需要對t進行偏移使下一個動畫提前播放即可。
末尾動畫停留
本來規劃的4PI時間,但是由于上面將每個顏色的播放提前了,導致4PI長度的時間末尾會有一段空白時間,這段時間就剛好用來模擬原效果里的停留效果。想要調整停留時間可以修改?TOTAL_TIME?。
最后調整一下屏寬和動畫速度,完工!
總結
老實說這柿子有點硬,我肝了一整天。
每個基本功能單獨實現都很簡單,但是合并到一起后經常出現牽一發動全身的情況。
寫完shader再從頭到尾看一遍,可以發現一些可以簡化或者合并的部分。一開始我是采用?sin()?作為運動曲線,也嘗試過映射到不同的屏幕坐標范圍,后來都調整了。
目前的代碼沒有經過深度調優,盡量保持了和自己的思路比較匹配的寫法。
完整代碼可從下方領取。
Demo地址
shadertoy
https://www.shadertoy.com/view/ttfBDf
Cocos Creator
https://github.com/caogtaa/CCBatchingTricks
內含各種Cocos Creator編程技巧Demo
本文Demo可直接訪問場景文件?SceneEnterEShop
技術交流,歡迎加我微信:ezglumes ,拉你入技術交流群。
推薦閱讀:
音視頻面試基礎題
OpenGL ES 學習資源分享
一文讀懂 YUV 的采樣與格式
OpenGL 之 GPUImage 源碼分析
推薦幾個堪稱教科書級別的 Android 音視頻入門項目
覺得不錯,點個在看唄~
總結
以上是生活随笔為你收集整理的用shader做一个柿子颜色的过场动画的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OsWatcher 使用详解
- 下一篇: 图片实现水平垂直居中的方法