【摘 要】本文介紹了手機(jī)動(dòng)態(tài)壁紙的設(shè)計(jì)方法,以及實(shí)現(xiàn)的過(guò)程。運(yùn)行的目標(biāo)平臺(tái)為Android,使用OpenGL ES3.0渲染技術(shù)。
【關(guān)鍵詞】Android;動(dòng)態(tài)壁紙;設(shè)計(jì)
一、引言
隨著移動(dòng)互聯(lián)網(wǎng)的快速發(fā)展,單一的圖片壁紙已經(jīng)不能滿足用戶的需求,動(dòng)態(tài)壁紙用動(dòng)態(tài)的影像替換了原始古板的靜態(tài)壁紙,并且不影響圖標(biāo)的顯示和應(yīng)用程序的使用。通過(guò)動(dòng)態(tài)壁紙讓桌面顯得更加酷炫、個(gè)性,增加手機(jī)的魅力。本項(xiàng)目采用的動(dòng)態(tài)壁紙為3D水族館,在該壁紙中有許多自由游動(dòng)的魚(yú),地面有不斷一張一合的珍珠貝和不斷閃爍的珍珠。還有幾處不斷冒出氣泡,并且這些氣泡隨高度增加而不斷變大。用戶可以單擊地面給魚(yú)喂食,也可以左右滑動(dòng)屏幕,使壁紙跟隨滑動(dòng)。使用3ds Max對(duì)模型進(jìn)行設(shè)計(jì)與貼圖,所有相關(guān)圖片資源統(tǒng)一放在一個(gè)項(xiàng)目文件夾中。采用OpenGL ES3.0渲染技術(shù),使得場(chǎng)景中有很強(qiáng)的立體感,以及非常逼真的光影效果。
二、類的設(shè)計(jì)
在水族館壁紙的制作中設(shè)計(jì)了很多類,主要有以下五個(gè)方面。(1)壁紙實(shí)現(xiàn)類,具體又有壁紙服務(wù)類和自定義場(chǎng)景渲染器類。前者是水族館壁紙的基礎(chǔ)類,通過(guò)繼承GLWallpaperService類,重寫(xiě)onCreateEngine方法等來(lái)實(shí)現(xiàn)壁紙功能;后者是水族館壁紙的核心類,在本類中首先設(shè)置使用渲染技術(shù),然后創(chuàng)建需要繪制的所有對(duì)象,設(shè)置繪制方式,加載各類物體模型以及所需紋理,設(shè)置攝像機(jī)位置,使用投影矩陣,初始化光源位置等。
(2)繪制類,具體包括群魚(yú)控制類、單條魚(yú)類、單個(gè)魚(yú)群類、喂食類、魚(yú)食類、氣泡控制類以及珍珠貝類等。群魚(yú)控制類定義了群魚(yú)列表,存放所有的單條魚(yú)對(duì)象,創(chuàng)建并啟動(dòng)魚(yú)的移動(dòng)線程,最后遍歷列表對(duì)魚(yú)進(jìn)行繪制。單條魚(yú)類定義了魚(yú)的所有屬性,包括位置、速度、外力、質(zhì)量以及旋轉(zhuǎn)角度等,單個(gè)魚(yú)群類定義了魚(yú)群中每條魚(yú)的所有相關(guān)屬性。喂食類是食物的控制類,其中的startFeed方法由攝像機(jī)與觸控點(diǎn)確定一條與場(chǎng)景地面高度交叉的拾取射線,并計(jì)算出交點(diǎn)的坐標(biāo)。魚(yú)食類的作用是創(chuàng)建并啟動(dòng)線程,繪制魚(yú)食。
(3)線程類,具體包括群魚(yú)游動(dòng)線程類、魚(yú)食移動(dòng)線程類和氣泡移動(dòng)線程類等。群魚(yú)游動(dòng)線程類的作用是通過(guò)遍歷群魚(yú)列表判斷兩條魚(yú)之間的距離,若距離小于閾值,則兩條魚(yú)之間產(chǎn)生力的作用。還可以進(jìn)行碰撞檢測(cè),修改外力、速度和位置等屬性值。魚(yú)食移動(dòng)線程類的主要作用是判斷魚(yú)群中的魚(yú)與相對(duì)位置的距離,若大于閾值就會(huì)對(duì)該魚(yú)產(chǎn)生向心力,并對(duì)魚(yú)群進(jìn)行碰撞檢測(cè)。氣泡移動(dòng)線程類的作用是遍歷氣泡列表,判斷氣泡移動(dòng)方向,然后調(diào)用氣泡對(duì)象中的bubbleMove方法,實(shí)現(xiàn)氣泡的移動(dòng)。
(4)工具常量類,具體包括常量類、向量類、屏幕拾取類和存儲(chǔ)矩陣狀態(tài)類等。常量類是整個(gè)壁紙中用到的所有靜態(tài)常量的集合,向量類包含了相關(guān)向量算法、獲取力的大小等方法。屏幕拾取類通過(guò)拾取計(jì)算獲得觸控點(diǎn)在攝像機(jī)坐標(biāo)系中的坐標(biāo),再乘以攝像機(jī)矩陣的逆矩陣,即可得到該點(diǎn)在世界坐標(biāo)系中的坐標(biāo)。
(5)輔助繪制類,具體包括背景圖輔助繪制類、氣泡輔助繪制類和珍珠貝輔助繪制類等。以背景圖輔助繪制類為例,它給出背景圖的頂點(diǎn)坐標(biāo)和紋理坐標(biāo),并生成緩沖送進(jìn)渲染管線,用來(lái)繪制背景圖。
三、類的實(shí)現(xiàn)
以自定義場(chǎng)景渲染器類為例,介紹動(dòng)態(tài)壁紙相關(guān)類的實(shí)現(xiàn)。首先清除深度緩沖與顏色緩沖,進(jìn)行現(xiàn)場(chǎng)保護(hù),依次繪制背景圖、魚(yú)食、單條魚(yú)魚(yú)群以及珍珠貝。相關(guān)代碼如下:
GLE30.glClear(GLES30.GL_DEPTH_BUFFER_BIT| GLES30.GL_COLOR_BUFFER_BIT);
if(bg!=null){bg.drawSelf(back);}
if(singlefood!=null){singlefood.drawSelf();}
if(fishControl!=null){fishControl.drawSelf();}
…………
重寫(xiě)onSurfaceChanged方法,設(shè)置視窗的尺寸和位置,計(jì)算寬高比,產(chǎn)生投影矩陣以及攝像機(jī)參數(shù)位置矩陣。相關(guān)代碼如下:
GLES30.glViewport(0,0,width,height);
float ratio=(float)width/height;
…………
重寫(xiě)onSurfaceCreated方法,初始化光源位置,加載紋理,加載BNModel模型,創(chuàng)建魚(yú)群、珍珠貝等對(duì)象,開(kāi)啟深度檢測(cè)等。相關(guān)代碼如下:
MatrixState.setInitStack();
MatrixState.setLightLocation(0,9,13);
dpm=initTexture(MySurfaceView,this,getResources(),”dpm.png”);
back=initTexture(MySurfaceView,this,getResources(),”background.png”);
…………
重寫(xiě)initTexture方法,通過(guò)輸入流從assets中加載圖片,生成紋理ID,設(shè)置紋理的拉伸方式,設(shè)置紋理采樣方式,最后釋放Bitmap。相關(guān)代碼如下:
GLES30.glGenTextures(1,textures,0);
int textureId=textures[0];
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,textureId);
back=initTexture(MySurfaceView,this,getResources(),”background.png”);
…………
bitmapTmp.recycle();
四、結(jié)語(yǔ)
在軟件設(shè)計(jì)過(guò)程中,重點(diǎn)是著色器的應(yīng)用,以及魚(yú)游動(dòng)過(guò)程中魚(yú)與魚(yú)之間作用力的變化規(guī)律等。動(dòng)態(tài)壁紙的界面和風(fēng)格還可以繼續(xù)改進(jìn),使其更加完美。例如水族館背景壁紙、魚(yú)的骨骼動(dòng)畫(huà)及紋理圖、珍珠貝的紋理圖都可以進(jìn)一步完善,從而達(dá)到更加理想的效果。本項(xiàng)目將明暗紋理和法向量的計(jì)算放在了片元著色器上進(jìn)行,這樣的處理方式占用資源過(guò)多。可以考慮將片元著色器中這部分計(jì)算任務(wù)轉(zhuǎn)移到頂點(diǎn)著色器中進(jìn)行,預(yù)期會(huì)顯著減少壁紙?jiān)谶\(yùn)行時(shí)對(duì)手機(jī)GPU資源的消耗。
【參考文獻(xiàn)】
[1] 吳亞峰. Android應(yīng)用案例開(kāi)發(fā)大全(第4版)[M].北京:人民郵電出版社, 2018.
作者簡(jiǎn)介:王曉東(1971—),男,漢族,湖北十堰人,副教授,主要研究方向:軟件開(kāi)發(fā)。