首先遇到一個新的事物,我們可以用3w來分析。
What:OpenGL ES是什么?功能是什么?(do what)
Why:為什么要使用OpenGL ES?(Why do)
How:如何使用OpenGL ES?(How do)
大致從這里切入,對OpenGL ES有一個整體的了解,這樣有利于學習,避免一葉障目。
what
OpenGL(全寫Open Graphics Library)是指定義了一個跨編程語言、跨平臺的編程接口規(guī)格的專業(yè)的圖形程序接口。
是一個接口,是行業(yè)領域中最為廣泛接納的 2D/3D 圖形 API。
功能:
OpenGL是一個開放的三維圖形軟件包,它獨立于窗口系統(tǒng)和操作系統(tǒng),以它為基礎開發(fā)的應用程序可以十分方便地在各種平臺間移植;OpenGL可以與Visual C++緊密接口,便于實現(xiàn)機械手的有關計算和圖形算法,可保證算法的正確性和可靠性;OpenGL使用簡便,效率高。它具有七大功能:
1、建模:OpenGL圖形庫除了提供基本的點、線、多邊形的繪制函數(shù)外,還提供了復雜的三維物體(球、錐、多面體、茶壺等)以及復雜曲線和曲面繪制函數(shù)。
2、變換:OpenGL圖形庫的變換包括基本變換和投影變換。基本變換有平移、旋轉、縮放、鏡像四種變換,投影變換有平行投影(又稱正射投影)和透視投 影兩種變換。其變換方法有利于減少算法的運行時間,提高三維圖形的顯示速度。
3、顏色模式設置:OpenGL顏色模式有兩種,即RGBA模式和顏色索引(Color Index)。
4、光照和材質設置:OpenGL光有自發(fā)光(Emitted Light)、環(huán)境光(Ambient Light)、漫反射光(Diffuse Light)和高光(Specular Light)。材質是用光反射率來表示。場景(Scene)中物體最終反映到人眼的顏色是光的紅綠藍分量與材質紅綠藍分量的反射率相乘后形成的顏色。
5、紋理映射(Texture Mapping)。利用OpenGL紋理映射功能可以十分逼真地表達物體表面細節(jié)。
6、位圖顯示和圖象增強圖象功能除了基本的拷貝和像素讀寫外,還提供融合(Blending)、抗鋸齒(反走樣)(Antialiasing)和霧(fog)的特殊圖象效果處理。以上三條可使被仿真物更具真實感,增強圖形顯示的效果。
7、雙緩存動畫(Double Buffering)雙緩存即前臺緩存和后臺緩存,簡言之,后臺緩存計算場景、生成畫面,前臺緩存顯示后臺緩存已畫好的畫面。
簡單地來說,一般用來處理圖形顯示相關方面。
下面來看OpenGL ES,是為用于嵌入式設備而設計的OpenGL子集。
OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三維圖形 API 的子集,針對手機、PDA和游戲主機等嵌入式設備而設計。該API由Khronos集團定義推廣,Khronos是一個圖形軟硬件行業(yè)協(xié)會,該協(xié)會主要關注圖形和多媒體方面的開放標準。
why
首先因為移動設備本身的圖形繪制只支持2D,想要做出絢麗的3D效果必須得借助OpenGL。也許有人會說,在android中使用camera不也能繪制出3D效果么,對此我只能說:Camera只是對OpenGL做了一個封裝,它本身仍然是屬于OpenGL范疇。 其次OpenGL直接操作native層的內(nèi)存。在android上會有更高的運行效率。而且由于OpenGL的繪制是在在主線程之外的另一條線程里操作,所以會更加流暢,不會阻塞主線程。
How
為了能適應各種硬件平臺,所以OpenGL ES2.0并不包含任何執(zhí)行窗口任務或者處理用戶輸入的函數(shù),我們需要通過應用程序本身所運行的窗口系統(tǒng)來提供相應操作才能處理這些操作。比如說:android手機上,我們想要調用OpenGL的話就必須得使用GLSurfaceView來渲染圖形。因為GLSurfaceView可以為自己創(chuàng)建一個窗口,并在視圖(View Hierarchy)層次上穿個洞讓底層的OpenGL surface顯示出來。對于大多數(shù)情況下這就足夠了。(但是由于GLSurfaceView本身就是window的一部分。所以它沒法像其他的View一樣進行動畫和變形操作。)另外 OpenGL ES2.0也不包含任何表達三維模型,讀取圖像文件的操作,這個時候,我們需要通過一系列的幾何圖元(點,線,三角形)來創(chuàng)建三維空間的物體。GLSurfaceView和圖元(點線面)將是我們后面講述的重點。
Android支持OpenGL通過其框架API和本地開發(fā)工具包(NDK)。
在Android框架有兩個基本類,讓你創(chuàng)建和操作圖形與OpenGL ES API:GLSurfaceView GLSurfaceView.Renderer。
下面重點看如何使用
在講后面內(nèi)容的時候我們需要先思考一個問題,假設讓你來畫一幅畫的話,你需要知道哪些要素了才能開始去畫這幅畫呢?
Android中View的源碼實現(xiàn)繪制的時候經(jīng)歷了三步,首先是測量控件的大小,因為只有知道大小了才能在布局中進行定位。其次就是確定位置,不確定位置的話就不知道要畫在哪。最后才是開始繪制。
如果按照這個步驟,那么OpenGL ES2中是如何去測量,定位還有繪制的呢?
1.OpenGL中的定位和測量
相比起Android中View,OpenGL的的定位測量要簡單的多,他只需要我們在它的坐標系上 定義一些頂點,這些頂點可以有很多屬性,但最重要的屬性就是位置。位置屬性通過x,y,z坐標來體現(xiàn)。通過這些頂點與頂點的組合就形成了不同的圖形,而這些圖形的位置也根據(jù)每個點的位置而確定了下來。
通過代碼來體現(xiàn)就是
float[] tableVertices = {
? ? ? ? 0f, 0f,0f,
? ? ? ? -0.5f,-0.8f,0f,
? ? ? ? 0.5f,-0.8f,0f,
? ? ? ? 0.5f,0.8f,0f,
? ? ? ?-0.5f,0.8f,0f,
? ? ? ?-0.5f,-0.8f,0f
};
但這不就是一個普通的float數(shù)組么,float數(shù)組是java的類型,而OpenGL使用的是卻是另外一種語言。那么我們怎么把這份數(shù)據(jù)傳遞給運行在本地環(huán)境的OpenGL呢?下面就會解答這個問題。
2.如何將java數(shù)據(jù)傳遞給本地系統(tǒng)庫中的OpenGL。
要知道,Android運行代碼的時候并不是直接運行在硬件上的,而是運行在Dalvik虛擬機上的。運行在虛擬機上的代碼不能直接訪問本地環(huán)境。除非通過特定的API的接口。Android這樣設計其實也是為了降低系統(tǒng)的耦合性,讓開發(fā)者不用去關心CPU等硬件,專心搞軟件就行了。這樣做一般也沒問題,但在與本地系統(tǒng)交互的時候就比較麻煩了,比如說OpenGL。OpenGL作為本地系統(tǒng)庫直接運行在硬件上。
繼續(xù)上面那個問題:如何將java數(shù)據(jù)傳遞給本地系統(tǒng)庫中的OpenGL。 有兩種技術可以實現(xiàn):1.使用本地接口JNI技術,這個技術已經(jīng)集成在Android系統(tǒng)android.opengl.GLES20中,我們可以直接調用. 2.改變內(nèi)存分配的方式,java有一個特殊的集合,他們可以分配本地內(nèi)存快,并且把java的數(shù)據(jù)復制到本地內(nèi)存。而本地內(nèi)存是可以被本地環(huán)境讀取,這樣就可以達到傳遞數(shù)據(jù)的目的。
代碼實現(xiàn)如下:
private FloatBuffer vertexData; //緩存的頂點數(shù)據(jù)
vertexData =
//allocateDirect分配本地內(nèi)存float數(shù)組的長度乘以每一個float類型占用的字節(jié)數(shù)
ByteBuffer.allocateDirect(tableVertices.length * BYTES_PER_FLOAT)
//告訴字節(jié)緩沖區(qū)按照本地字節(jié)序組織它的內(nèi)容? ? ? ? ? ? ? ? ? ?
//當一個值占用多個字節(jié),比如32位整形數(shù),字節(jié)按照從高位到低位 或者從低位到高位排序
//排什么順序其實不重要,重要的是程序運行過程中所有的字節(jié)都得按同樣的順序排序,
//不能有的排正序,有的排倒序。 而? //order(ByteOrder.nativeOrder()就能達到這個目的。
.order(ByteOrder.nativeOrder())
//根據(jù)分配的內(nèi)存獲取一個能分配本地內(nèi)存的FloatBuffer實例對象。
.asFloatBuffer();
//將頂點數(shù)據(jù) 內(nèi)存從虛擬機中拷貝到本地
vertexData.put(tableVertices);
現(xiàn)在OpenGL已經(jīng)可以讀取這些數(shù)據(jù),那么它會如何去使用這些數(shù)據(jù)呢? 這就涉及到OpenGL管道的概念了。
OpenGL管道
大部分圖形系統(tǒng)都可以比作工廠中的裝配線(Assemble line)或者稱為管道(Pipeline)。前一道的輸出作為下道工序的輸入。主 CPU 發(fā)出一個繪圖指令,然后可能由硬件部件完成坐標變換,裁剪,添加顏色或是材質,最后在屏幕上顯示出來。
通過打開OpenGL管道的相應開關將頂點參數(shù)傳給 OpenGL 庫。然后調用函數(shù),對這些頂點按一定的方式進行繪制,以達到顯示不同的圖形的目的。
OpenGL ES 所有能夠繪制的基本圖形,點,線段和三角形。其它所有復雜的 2D 或 3D 圖形都是由這些基本圖形構成。
下面來通過一個具體實例來認識OpenGL ES
———————————坑的分割—————
參考鏈接:
http://blog.csdn.net/hejjunlin/article/details/61615215
https://lord198712071.gitbooks.io/youyang_opengl-es-2-0/content/chapter1.html(這個不完整,沒寫完。)
https://blog.piasy.com/2016/06/07/Open-gl-es-android-2-part-1/
(這里有個挺全面的實例)
http://www.lxweimin.com/c/30e2e76bc140
http://wiki.jikexueyuan.com/project/opengl-es-guide/introduction.html
http://www.cnblogs.com/sunminmin/p/4478578.html