用 shader + mesh 立個 flag 吧! 文章底部獲取完整代碼!
效果預覽
使用方法
- 創建一個空節點
- 添加用戶腳本組件
mesh-texture-flag
- 添加圖片
- 修改對應屬性
實現原理
概括來說就是創建 mesh 網格模型,通過頂點着色器對頂點坐標不斷的修改,達到飄動的效果。關於 mesh 的介紹,可以參考上一篇文章。
確定頂點坐標
為了讓頂點着色器里有多個頂點可以改變位置,需要把一個形狀分割成多個方形(三角形)。分割數量越大,效果越精細,但需要消耗更多的性能消耗。下圖是分割成兩行三列的例子。
根據分割的行列數和節點大小,節點錨點,從左到右從上到下,算出每個頂點的位置信息。可以先算出相對左上角的位置,然后再根據錨點偏移,參考代碼如下。
const x = (_col - this._col * this.node.anchorX) * _width / this._col;
const y = (_row - this._row * this.node.anchorY) * _height / this._row;
確定紋理uv坐標
紋理uv坐標系在左上角,u
軸是向右,v
軸是向下,范圍是 0-1。而我們的坐標系是根據錨點確定的,x
軸向右,y
軸向上。
根據錨點求出位置坐標在左下角的占比,然后再翻轉一下v就可以求出對應的uv坐標了。參考代碼如下。
const u = (pt.x + this.texture.width * this.node.anchorX + this.offset.x) / this.texture.width;
const v = 1.0 - (pt.y + this.texture.height * this.node.anchorY + this.offset.y) / this.texture.height;
確定頂點索引
從網格左上角的格子開始,依次確定三角形頂點畫法。下圖是分割成兩行兩列的索引。
每個格子有兩個三角形,參考代碼如下。
// 計算頂點索引
let ids = [];
let getIndexByRowCol = (_row, _col) => {
return _row * (this._col + 1) + _col;
}
for (let _row = 0; _row < this._row; _row++) {
for (let _col = 0; _col < this._col; _col++) {
ids.push(getIndexByRowCol(_row, _col), getIndexByRowCol(_row, _col + 1), getIndexByRowCol(_row + 1, _col));
ids.push(getIndexByRowCol(_row + 1, _col), getIndexByRowCol(_row + 1, _col + 1), getIndexByRowCol(_row, _col + 1));
}
};
頂點着色器編寫
使用的是sin
函數對頂點進行修改。
一個波浪就是一個 PI
, 所以要把位置坐標變化幅度映射到 wave * PI
。通過求出占寬度比就可以得到 sin
函數的角度了。
通過內置變量 cc_time
可以使坐標隨着時間變化。不過得在非編輯器下才能預覽到,因為默認是不會賦值的。
參考代碼如下。
float angleSpanH = wave * 3.14159265;
float pz = amplitude * sin(cc_time.x * speed - (a_position.x - startPos.x + a_position.y - startPos.y) / textureWidth * angleSpanH);
vec4 position = vec4(a_position.x, a_position.y + pz, a_position.z, 1);
小結
以上為白玉無冰使用 Cocos Creator v2.2.2 開發 "飄揚的旗幟!" 的技術分享。有想法歡迎留言!如果這篇對你有點幫助,歡迎分享給身邊的朋友。