本篇文章屬于 使用 OpenGL ES 進(jìn)行圖形繪制 這個(gè)系列的第一篇文章拳魁,主要內(nèi)容是介紹在 Android 應(yīng)用使用 OpenGL ES 時(shí)需要配置的開發(fā)環(huán)境和整體流程說明京革。
要在 Android 應(yīng)用中使用 OpenGL ES 繪制圖像栈源,我們必須為它們創(chuàng)建一個(gè) View 容器合是。一種比較直接的方法是實(shí)現(xiàn) GLSurfaceView 類和 GLSurfaceView.Renderer 類厨诸。其中 GLSurfaceView 是一個(gè)視圖容器身诺,它用來存放使用 OpenGL 繪制的圖形蜜托,而 GLSurfaceView.Renderer 則用來控制在該視圖內(nèi)容的繪制(渲染器)。關(guān)于這兩個(gè)類的更多信息霉赡,可以閱讀 OpenGL ES 開發(fā)手冊(cè)橄务。
Note: GLSurfaceView 是一個(gè) View container,用來存放繪制的圖像穴亏。
GLSurfaceView.Renderer 是用來控制 View 中繪制的內(nèi)容的渲染器蜂挪。
使用 GLSurfaceView 是一種將 OpenGL ES 集成到應(yīng)用中的方法之一。對(duì)于一個(gè)全屏的或者接近全屏的圖形 View嗓化,使用它是一個(gè)理想的選擇棠涮。開發(fā)者如果希望把 OpenGL ES 的圖形集成在布局的一小部分里面,那么可以考慮使用 TextureView刺覆。對(duì)于喜歡自己動(dòng)手實(shí)現(xiàn)的開發(fā)者來說严肪,還可以通過使用
SurfaceView 搭建一個(gè) OpenGL ES View,但這將需要編寫更多的代碼。
下面將展示如何在一個(gè) Activity 中完成 GLSurfaceView 和 GLSurfaceView.Renderer 的最簡(jiǎn)單直接的實(shí)現(xiàn)驳糯。
1. 1 在 Manifest 配置文件中聲明使用 OpenGL ES
為了讓應(yīng)用能夠使用 OpenGL ES 2.0 接口篇梭,我們必須將下列聲明添加到 Manifest 配置文件當(dāng)中:
<!--0x00020000 代表使用 OpenGL ES 2.0 接口-->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
如果應(yīng)用要使用紋理壓縮(Texture Compression),則必須聲明對(duì)紋理壓縮格式的支持酝枢,這樣確保應(yīng)用僅安裝在可以兼容的設(shè)備上:
<!--紋理壓縮格式格式聲明-->
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />
紋理壓縮通過減少內(nèi)存需求并更有效地利用內(nèi)存帶寬恬偷,可以顯著提高 OpenGL 應(yīng)用程序的性能。更多關(guān)于紋理壓縮的內(nèi)容可以閱讀 OpenGL 開發(fā)手冊(cè) 帘睦。
1.2 為 OpenGL ES 圖形創(chuàng)建一個(gè) Activity
使用 OpenGL ES 的 Android 應(yīng)用跟其它類型的應(yīng)用主要的區(qū)別體現(xiàn)在 Activity 布局內(nèi)容上的差異袍患。通常我們會(huì)使用 TextView、Button等已經(jīng)封裝好的控件官脓。而如果使用 OpenGL ES 的我們就得依賴 GLSurfaceView 來自己實(shí)現(xiàn)了协怒。
所以最簡(jiǎn)單的使用方式是直接創(chuàng)建一個(gè) GLSurfaceView 實(shí)例,并把它作為 ContentView 設(shè)置到 Activity 中卑笨。
public class OpenGLSample01Activity extends AppCompatActivity {
GLSurfaceView mGLSurfaceView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("OpenGLSample01");
// Create a GLSurfaceView instance and set it
// as the ContentView for this Activity.
mGLSurfaceView = new MyGLSurfaceView(this);
setContentView(mGLSurfaceView);
}
}
OpenGL ES 2.0 需要Android 2.2(API Level 8)或更高版本的系統(tǒng)孕暇,所以確保你的Android項(xiàng)目的 API 版本滿足該要求。
1.3 構(gòu)建一個(gè) GLSurfaceView 對(duì)象
GLSurfaceView 是一種比較特殊的 View赤兴,我們可以在該 View 中繪制 OpenGL ES 圖形妖滔,不過它自己并不做太多和繪制圖形相關(guān)的任務(wù)。繪制對(duì)象的任務(wù)是由你在該 View 中配置的 GLSurfaceView.Renderer 所控制的桶良。因此在實(shí)際開發(fā)中不建議直接使用 GLSurfaceView 來創(chuàng)建實(shí)例座舍。
事實(shí)上,GLSurfaceView 的核心代碼非常簡(jiǎn)短陨帆,你可能會(huì)直接創(chuàng)建一個(gè)未經(jīng)修改的 GLSurfaceView 實(shí)例曲秉,不過請(qǐng)不要這么做,因?yàn)槲覀冃枰^承該類來捕捉觸控事件疲牵,這方面知識(shí)會(huì)在 響應(yīng)觸摸事件 中做進(jìn)一步的介紹承二。
class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context){
super(context);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
mRenderer = new MyGLRenderer();
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(mRenderer);
}
}
另一個(gè)對(duì)于 GLSurfaceView 的可選選項(xiàng)是將渲染模式設(shè)置為:GLSurfaceView.RENDERMODE_WHEN_DIRTY,其含義是僅在你的繪制數(shù)據(jù)發(fā)生變化時(shí)才在視圖中進(jìn)行繪制操作:
// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
如果選用這一配置選項(xiàng)纲爸,那么除非調(diào)用了 requestRender()亥鸠,否則 GLSurfaceView 不會(huì)被重新繪制,這樣做可以讓應(yīng)用的性能及效率得到提高识啦。
1.4 構(gòu)建一個(gè)渲染器類
在一個(gè)使用 OpenGL ES 的應(yīng)用中负蚊,必定少不了 GLSurfaceView.Renderer 類的實(shí)現(xiàn)。該類會(huì)控制和其相關(guān)聯(lián)的 GLSurfaceView 的繪制行為和內(nèi)容颓哮,Renderer 這個(gè)類中有三個(gè)方法會(huì)被系統(tǒng)調(diào)用家妆,所以需要實(shí)現(xiàn)下面三個(gè)方法:
- onSurfaceCreated():調(diào)用一次,用來配置 View 的 OpenGL ES 環(huán)境冕茅。
- onDrawFrame():每次重新繪制View時(shí)被調(diào)用伤极。
- onSurfaceChanged():如果View的幾何形態(tài)發(fā)生變化時(shí)會(huì)被調(diào)用腰鬼,例如當(dāng)設(shè)備的屏幕方向發(fā)生改變時(shí)。
下面是一個(gè)非乘芑模基本的 OpenGL ES 渲染器的實(shí)現(xiàn),它僅僅在GLSurfaceView 中畫一個(gè)黑色的背景:
public class MyGLRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
}
通過上述代碼姜挺,我們完成一個(gè)完整的 OpenGL ES 簡(jiǎn)單使用場(chǎng)景齿税,程序運(yùn)行起來會(huì)是一個(gè)黑色的背景。
下面來簡(jiǎn)單回顧一下在應(yīng)用中使用 OpenGL ES 的整個(gè)流程:
- 在 Manifest 中對(duì)使用 OpenGL ES 進(jìn)行聲明
- 給 OpenGL ES 繪制的圖像創(chuàng)建 Activity
- 創(chuàng)建一個(gè) GLSurfaceView 對(duì)象并設(shè)置到 Activity 中
- 創(chuàng)建一個(gè) Renderer 類實(shí)現(xiàn)繪制邏輯炊豪,并設(shè)置到 GLSurfaceView
文章中所有的代碼示例都已放在 Github 上凌箕,可以去項(xiàng)目 OpenGL-ES-Learning 中查看 。
通過基于上面的內(nèi)容词渤,相信你對(duì)于如何使用 OpenGL 繪制圖形有了基本的認(rèn)識(shí)和鋪墊牵舱。當(dāng)然,這些都是相當(dāng)基礎(chǔ)的知識(shí)缺虐,如果你對(duì) OpenGL ES 接口很熟悉芜壁,那么你現(xiàn)在就可以在應(yīng)用中構(gòu)建一個(gè) OpenGL ES 的環(huán)境并繪制圖形了。如果你希望獲取更多關(guān)于 OpenGL 的內(nèi)容高氮,請(qǐng)繼續(xù)看后面的內(nèi)容慧妄。
-
OpenGL ES 定義圖形形狀
學(xué)習(xí)如何在 OpenGL 中定義圖形形狀 -
OpenGL ES 繪制形狀(Shape)
學(xué)習(xí)如何在應(yīng)用中利用 OpenGL 繪制形狀。 -
OpenGL ES 運(yùn)用投影與相機(jī)視角
學(xué)習(xí)如何通過投影和相機(jī)視角剪芍,獲取圖形對(duì)象的一個(gè)新的透視效果塞淹。 -
OpenGL ES 添加視圖動(dòng)作
學(xué)習(xí)如何對(duì)一個(gè) OpenGL 圖形對(duì)象添加基本的運(yùn)動(dòng)效果。 -
OpenGL ES 響應(yīng)觸摸事件
學(xué)習(xí)如何與 OpenGL 圖形進(jìn)行基本的交互罪裹。