本文目錄
一. OpenGL ES是什么?
二. OpenGL ES的版本
三. EGL是什么棍丐?
四. 需要知道的兩個方法
五. 在Android中使用OpenGL ES的步驟
六. 例子1:簡單的程序+修改背景顏色
OpenGL ES是什么?
- OpenGL(Open Graphics Library): 是用于渲染2D、3D矢量圖形的跨語言绍填、跨平臺的應(yīng)用程序編程接口(API),使簡單的圖形構(gòu)建出復(fù)雜的三維景象栖疑。
- OpenGL ES(OpenGl for Embedded System):是 OpenGL三維圖形 API 的子集讨永,針對手機、PDA和游戲主機等嵌入式設(shè)備而設(shè)計遇革,簡單來說就是OpenGL在移動端的閹割版卿闹。
OpenGL ES 的版本
OpenGL ES版本 | Android版本 | 描述 |
---|---|---|
OpenGL ES1.0 | Android 1.0+ | OpenGL ES 1.x是針對固定硬件管線(Fixed Pipeline)的揭糕,通過它內(nèi)建的functions來設(shè)置諸如燈光、vertexes(圖形的頂點數(shù))锻霎、顏色和camera著角。 |
OpenGL ES2.0 | Android 2.2(API 8)+ | OpenGL ES 2.x是針對可編程硬件管線(Programmable Pipeline)的,不兼容OpenGL ES 1.x旋恼,需要自己動手編寫任何功能吏口。2.0相比于1.0更具靈活性,功能也更強大冰更〔玻可以自定義頂點和像素計算,可以讓表現(xiàn)方式更加準(zhǔn)確蜀细。 |
OpenGL ES3.0 | Android 4.3(API 18)+ | 向下兼容OpenGL ES 2.x舟铜,是OpenGL ES2.0的擴展,支持許多新的渲染技術(shù)奠衔、優(yōu)化和顯示質(zhì)量改進谆刨,包括引入了紋理相關(guān)的新功能,對著色語言進行了重大更新和支持著色器新功能的API特性归斤,引入了與幾何形狀規(guī)范和圖元渲染控制相關(guān)的新功能痴荐,引入了新的緩沖區(qū)對象,增添了許多與屏幕外渲染到幀緩沖區(qū)對象相關(guān)的新功能官册。 |
OpenGL ES3.x | Android 5.0 (API 21)+ | 向下兼容OpenGL ES3.0/2.0生兆,Android 5.0(API 21)和更高的版本支持這個API規(guī)范。 |
EGL是什么膝宁?
- EGL (Embedded Graphics Library):EGL 是連接 OpenGL ES 和本地窗口系統(tǒng)的接口鸦难,由于OpenGL ES是跨平臺的,引入EGL就是為了屏蔽不同平臺上的區(qū)別员淫。
另外合蔽,EGL定義了控制 Displays
、Contexts
以及 Surfaces
的統(tǒng)一的平臺接口介返,但一般情況在 Android 平臺上開發(fā) OpenGL ES 應(yīng)用拴事,無需直接使用javax.microedition.khronos.egl
包中的類按照EGL步驟來使用OpenGL ES繪制圖形,因為在Android平臺中提供了一個android.opengl
包圣蝎,GLSurfaceView類提供了對Display刃宵、Surface 和 Context 的管理,大大簡化了 OpenGL ES 的程序框架徘公,對應(yīng)大部分 OpenGL ES開發(fā)牲证,只需調(diào)用一個方法來設(shè)置 OpenGLView 需要的GLSurfaceView.Renderer 即可。
EGL提供如下機制:
- 與設(shè)備的原生窗口系統(tǒng)通信
- 查詢繪圖表面的可用類型和配置
- 創(chuàng)建繪圖表面
- 在OpenGL ES 和其他圖形渲染API之間同步渲染
- 管理紋理貼圖等渲染資源
- 為了讓OpenGL ES能夠繪制在當(dāng)前設(shè)備上关面,我們需要EGL作為OpenGL ES與設(shè)備的橋梁坦袍。
需要知道的兩個方法
GLSurfaceView:渲染表面類(android.opengl.GLSurfaceView)十厢,自動負(fù)責(zé)管理EGL執(zhí)行步驟,但用戶需要確定針對渲染表面 OpenGL ES 的版本捂齐,即調(diào)用 setEGLContextClientVersion(int version) 方法蛮放。隨后調(diào)用 setRenderer() 方法來為OpenGLES配置渲染表面。此外還有其他的 setEGL* 方法去配置上下文環(huán)境奠宜,例如渲染表面的 RGB 顏色分量的位深筛武。
GLSurfaceView.Renderer:渲染器類(android.opengl.GLSurfaceView.Renderer),GLSurfaceView 需要通過渲染器對象完成實際的渲染操作挎塌,自定義渲染器對象需要繼承 Renderer 接口類,并實現(xiàn)三個方法:onSurfaceCreated()内边、onSurfaceChanged()和onDrawFrame()榴都。
在Android中使用OpenGL ES的步驟:
- 創(chuàng)建
GLSurfaceView
組件,使用 Activity 來顯示 GLSurfaceView 組件漠其。 - 為 GLSurfaceView 配置渲染類
GLSurfaceView.Renderer
嘴高,實現(xiàn)GLSurfaceView.Renderer接口并重寫3個方法。- onSurfaceCreated():當(dāng)Surface被第一次創(chuàng)建或從其他Activity切換回來都會調(diào)用此方法和屎,方法中還可以初始化OpenGLES圖形(背景色)拴驮。
- onSurfaceChanged():在Surface被創(chuàng)建后,每次Surface尺寸變化柴信,還有屏幕橫豎切換都會調(diào)用此方法套啤。
- onDrawFrame():每繪制一幀都會調(diào)用此方法,在這個方法中必須繪制點什么随常,即使只是清空屏幕潜沦。因為如果什么都沒畫,會導(dǎo)致屏幕不斷閃爍绪氛。重點:此方法是繪制圖形的主要執(zhí)行點唆鸡。
- 調(diào)用GLSurfaceView組件的
setRenderer()
方法指定Renderer對象,該Renderer對象會完成GLSurfaceView里的3D圖形的繪制枣察。
例子1:簡單的程序+修改背景顏色 OpenGLESVersion
- 創(chuàng)建GLSurfaceView實例争占,檢查設(shè)備版本,Activity生命周期序目,配置上下文臂痕。
- 創(chuàng)建Renderer類,實現(xiàn)渲染方法猿涨。
- 效果展示刻蟹。
1.創(chuàng)建GLSurfaceView實例
我們通過 GLSurfaceView 來初始化 OpenGLES,如配置顯示設(shè)備 Display 以及在后臺線程中渲染嘿辟。在此之前舆瘪,我們需要對設(shè)備的進行版本檢查片效,以及在 Android Activity 生命周期的維護、渲染請求方式進行配置英古。最后才會配置這個 Surface 視圖和傳入自定義 Renderer 類淀衣。
public class VersionActivity extends AppCompatActivity {
private GLSurfaceView surfaceView;
private boolean rendererSet = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//檢查OpenGl ES版本
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
//獲取版本號
int VersionNum = configurationInfo.reqGlEsVersion;
//輸出196608 16進制=0x30000 3.0版本
if (VersionNum >= 196608) {
Toast.makeText(this, "OpenGLES version is 3.0 or more", Toast.LENGTH_SHORT).show();
rendererSet = true;
//執(zhí)行3.0版本的方法
}
//輸出131072 16進制=0x20000 2.0版本
else if (VersionNum >= 131072 && VersionNum < 196608) {
Toast.makeText(this, "OpenGLES version is 2.0", Toast.LENGTH_SHORT).show();
rendererSet = true;
//執(zhí)行2.0版本的方法, 配置ES 2.0的上下文
surfaceView = new GLSurfaceView(this);
//確定針對渲染表面 OpenGL ES 的版本
surfaceView.setEGLContextClientVersion(2);
//1.連續(xù)刷新頻率不停渲染召调,0.按請求來渲染
surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
surfaceView.setRenderer(new GLES20Renderer());
setContentView(surfaceView);
} else {
Toast.makeText(this, "Current devices do not support OpenGLES", Toast.LENGTH_SHORT).show();
return;
}
}
@Override
protected void onPause() {
super.onPause();
if (rendererSet) {
surfaceView.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (rendererSet) {
surfaceView.onResume();
}
}
}
注意:渲染線程方式setRenderMode:
1.RENDERMODE_CONTINUOUSLY
按設(shè)備刷新頻率不斷地渲染膨桥。
0.RENDERMODE_WHEN_DIRTY
按請求方式來渲染。
2.創(chuàng)建Renderer類
在GLSurfaceView中傳入了一個自定義Renderer類唠叛,那么Renderer是一個渲染器只嚣,他需要重寫3個方法來實現(xiàn)渲染的整個過程。
public class GLES20Renderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//第一次創(chuàng)建或切換回來都會調(diào)用此方法
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
//每次Surface尺寸變化艺沼,比如屏幕橫豎切換都會調(diào)用此方法
GLES20.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
//每繪制一幀都會調(diào)用此方法
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
}
-
onSurfaceCreated:其中的
glClearColor
是設(shè)置清空屏幕用的顏色册舞,四個參數(shù):紅綠藍(lán)透明,都是float類型障般,最大值為1调鲸,最小值為0。 -
onSurfaceChanged:其中的
glViewport
是設(shè)置視口的尺寸挽荡,告訴OpenGLES用來顯示Surface的大小藐石。 -
onDrawFrame:其中的
glClear(GL_COLOR_BUFFER_BIT)
表示清空屏幕,并會用glClearColor再次填充整個屏幕定拟。
問:參數(shù)中的
GL10
是什么于微?
GL10是OpenGLES 1.0的API遺留下來的。但是要編寫使用OpenGLES1.0的渲染器青自,就用這個參數(shù)角雷。但是對于OpenGLES2.0就直接通過靜態(tài)方法GLES20來直接獲取。OpenGLES3.0也是直接使用GLES30性穿。
3.結(jié)果
當(dāng)運行這個Activity的時候勺三,會看到屏幕渲染上了一層藍(lán)色背景色,這也就是我們在onSurfaceCreated中設(shè)置的glClearColor方法需曾。
總結(jié)
這雖然是學(xué)習(xí)OpenGLES20的第一課吗坚,只學(xué)習(xí)了GLSurfaceView和Renderer渲染器,但有了整個程序的大體框架呆万,是最接下來的學(xué)習(xí)有著大大的幫助商源。
參考文獻(xiàn)
- 《Android三維程序設(shè)計》
- 《OpenGL ES 應(yīng)用開發(fā)實踐指南》
- https://blog.csdn.net/matrix_laboratory/article/details/50897183
- http://www.reibang.com/nb/8716340
- http://www.reibang.com/p/a94c8ed639c7
- 內(nèi)容講得比較清晰,還有前提點https://blog.csdn.net/zhang_he_xiang/article/details/85015357
為什么要使用OpenGL ES
通常來說谋减,計算機系統(tǒng)中 CPU牡彻、GPU 是協(xié)同工作的。CPU 計算好顯示內(nèi)容提交到 GPU,GPU 渲染完成后將渲染結(jié)果放入幀緩沖區(qū)庄吼,隨后視頻控制器會按照 VSync 信號逐行讀取幀緩沖區(qū)的數(shù)據(jù)缎除,經(jīng)過可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。所以总寻,盡可能讓 CPU 和 GPU 各司其職發(fā)揮作用是提高渲染效率的關(guān)鍵器罐。
正如我們之前提到過,OpenGL 正是給我們提供了訪問 GPU 的能力渐行,不僅如此轰坊,它還引入了緩存(Buffer)這個概念,大大提高了處理效率祟印。
從一個內(nèi)存區(qū)域復(fù)制到另一個內(nèi)存區(qū)域的速度是相對較慢的肴沫,并且在內(nèi)存復(fù)制的過程中,CPU 和 GPU 都不能處理這區(qū)域內(nèi)存蕴忆,避免引起錯誤颤芬。此外,CPU / GPU 執(zhí)行計算的速度是很快的孽文,而內(nèi)存的訪問是相對較慢的,這也導(dǎo)致處理器的性能處于次優(yōu)狀態(tài)夺艰,這種狀態(tài)叫做 數(shù)據(jù)饑餓芋哭,簡單來說就是空有一身本事卻無用武之地。
針對此郁副,OpenGL 為了提升渲染的性能减牺,為兩個內(nèi)存區(qū)域間的數(shù)據(jù)交換定義了緩存。緩存是指 GPU 能夠控制和管理的連續(xù) RAM存谎。程序從 CPU 的內(nèi)存復(fù)制數(shù)據(jù)到 OpenGL ES 的緩存拔疚。通過獨占緩存,GPU 能夠盡可能以有效的方式讀寫內(nèi)存既荚。 這也意味著 GPU 使用緩存中的數(shù)據(jù)工作的同時稚失,運行在 CPU 中的程序可以繼續(xù)執(zhí)行。