首先遇到一個(gè)新的事物,我們可以用3w來分析。
What:OpenGL ES是什么箕速?功能是什么?(do what)
Why:為什么要使用OpenGL ES朋譬?(Why do)
How:如何使用OpenGL ES盐茎?(How do)
大致從這里切入,對OpenGL ES有一個(gè)整體的了解徙赢,這樣有利于學(xué)習(xí)字柠,避免一葉障目。
what
OpenGL(全寫Open Graphics Library)是指定義了一個(gè)跨編程語言狡赐、跨平臺的編程接口規(guī)格的專業(yè)的圖形程序接口窑业。
是一個(gè)接口,是行業(yè)領(lǐng)域中最為廣泛接納的 2D/3D 圖形 API枕屉。
功能:
OpenGL是一個(gè)開放的三維圖形軟件包常柄,它獨(dú)立于窗口系統(tǒng)和操作系統(tǒng),以它為基礎(chǔ)開發(fā)的應(yīng)用程序可以十分方便地在各種平臺間移植搀擂;OpenGL可以與Visual C++緊密接口西潘,便于實(shí)現(xiàn)機(jī)械手的有關(guān)計(jì)算和圖形算法,可保證算法的正確性和可靠性哨颂;OpenGL使用簡便秸架,效率高。它具有七大功能:
1咆蒿、建模:OpenGL圖形庫除了提供基本的點(diǎn)东抹、線、多邊形的繪制函數(shù)外沃测,還提供了復(fù)雜的三維物體(球缭黔、錐、多面體蒂破、茶壺等)以及復(fù)雜曲線和曲面繪制函數(shù)馏谨。
2、變換:OpenGL圖形庫的變換包括基本變換和投影變換附迷【寤ィ基本變換有平移、旋轉(zhuǎn)喇伯、縮放喊儡、鏡像四種變換,投影變換有平行投影(又稱正射投影)和透視投 影兩種變換稻据。其變換方法有利于減少算法的運(yùn)行時(shí)間艾猜,提高三維圖形的顯示速度。
3、顏色模式設(shè)置:OpenGL顏色模式有兩種匆赃,即RGBA模式和顏色索引(Color Index)淤毛。
4、光照和材質(zhì)設(shè)置:OpenGL光有自發(fā)光(Emitted Light)算柳、環(huán)境光(Ambient Light)低淡、漫反射光(Diffuse Light)和高光(Specular Light)。材質(zhì)是用光反射率來表示瞬项。場景(Scene)中物體最終反映到人眼的顏色是光的紅綠藍(lán)分量與材質(zhì)紅綠藍(lán)分量的反射率相乘后形成的顏色查牌。
5、紋理映射(Texture Mapping)滥壕。利用OpenGL紋理映射功能可以十分逼真地表達(dá)物體表面細(xì)節(jié)纸颜。
6、位圖顯示和圖象增強(qiáng)圖象功能除了基本的拷貝和像素讀寫外绎橘,還提供融合(Blending)胁孙、抗鋸齒(反走樣)(Antialiasing)和霧(fog)的特殊圖象效果處理。以上三條可使被仿真物更具真實(shí)感称鳞,增強(qiáng)圖形顯示的效果涮较。
7、雙緩存動畫(Double Buffering)雙緩存即前臺緩存和后臺緩存冈止,簡言之狂票,后臺緩存計(jì)算場景、生成畫面熙暴,前臺緩存顯示后臺緩存已畫好的畫面闺属。
簡單地來說,一般用來處理圖形顯示相關(guān)方面周霉。
下面來看OpenGL ES掂器,是為用于嵌入式設(shè)備而設(shè)計(jì)的OpenGL子集。
OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三維圖形 API 的子集俱箱,針對手機(jī)国瓮、PDA和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì)。該API由Khronos集團(tuán)定義推廣狞谱,Khronos是一個(gè)圖形軟硬件行業(yè)協(xié)會乃摹,該協(xié)會主要關(guān)注圖形和多媒體方面的開放標(biāo)準(zhǔn)。
why
首先因?yàn)橐苿釉O(shè)備本身的圖形繪制只支持2D跟衅,想要做出絢麗的3D效果必須得借助OpenGL孵睬。也許有人會說,在android中使用camera不也能繪制出3D效果么与斤,對此我只能說:Camera只是對OpenGL做了一個(gè)封裝肪康,它本身仍然是屬于OpenGL范疇。 其次OpenGL直接操作native層的內(nèi)存撩穿。在android上會有更高的運(yùn)行效率磷支。而且由于OpenGL的繪制是在在主線程之外的另一條線程里操作,所以會更加流暢食寡,不會阻塞主線程雾狈。
How
為了能適應(yīng)各種硬件平臺,所以O(shè)penGL ES2.0并不包含任何執(zhí)行窗口任務(wù)或者處理用戶輸入的函數(shù)抵皱,我們需要通過應(yīng)用程序本身所運(yùn)行的窗口系統(tǒng)來提供相應(yīng)操作才能處理這些操作善榛。比如說:android手機(jī)上,我們想要調(diào)用OpenGL的話就必須得使用GLSurfaceView來渲染圖形呻畸。因?yàn)镚LSurfaceView可以為自己創(chuàng)建一個(gè)窗口移盆,并在視圖(View Hierarchy)層次上穿個(gè)洞讓底層的OpenGL surface顯示出來。對于大多數(shù)情況下這就足夠了伤为。(但是由于GLSurfaceView本身就是window的一部分咒循。所以它沒法像其他的View一樣進(jìn)行動畫和變形操作。)另外 OpenGL ES2.0也不包含任何表達(dá)三維模型绞愚,讀取圖像文件的操作叙甸,這個(gè)時(shí)候,我們需要通過一系列的幾何圖元(點(diǎn)位衩,線裆蒸,三角形)來創(chuàng)建三維空間的物體。GLSurfaceView和圖元(點(diǎn)線面)將是我們后面講述的重點(diǎn)糖驴。
Android支持OpenGL通過其框架API和本地開發(fā)工具包(NDK)僚祷。
在Android框架有兩個(gè)基本類,讓你創(chuàng)建和操作圖形與OpenGL ES API:GLSurfaceView GLSurfaceView.Renderer贮缕。
下面重點(diǎn)看如何使用
在講后面內(nèi)容的時(shí)候我們需要先思考一個(gè)問題久妆,假設(shè)讓你來畫一幅畫的話,你需要知道哪些要素了才能開始去畫這幅畫呢跷睦?
Android中View的源碼實(shí)現(xiàn)繪制的時(shí)候經(jīng)歷了三步筷弦,首先是測量控件的大小,因?yàn)橹挥兄来笮×瞬拍茉诓季种羞M(jìn)行定位抑诸。其次就是確定位置烂琴,不確定位置的話就不知道要畫在哪。最后才是開始繪制蜕乡。
如果按照這個(gè)步驟奸绷,那么OpenGL ES2中是如何去測量,定位還有繪制的呢层玲?
1.OpenGL中的定位和測量
相比起Android中View号醉,OpenGL的的定位測量要簡單的多反症,他只需要我們在它的坐標(biāo)系上 定義一些頂點(diǎn),這些頂點(diǎn)可以有很多屬性畔派,但最重要的屬性就是位置铅碍。位置屬性通過x,y线椰,z坐標(biāo)來體現(xiàn)胞谈。通過這些頂點(diǎn)與頂點(diǎn)的組合就形成了不同的圖形,而這些圖形的位置也根據(jù)每個(gè)點(diǎn)的位置而確定了下來憨愉。
通過代碼來體現(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
};
但這不就是一個(gè)普通的float數(shù)組么烦绳,float數(shù)組是java的類型,而OpenGL使用的是卻是另外一種語言配紫。那么我們怎么把這份數(shù)據(jù)傳遞給運(yùn)行在本地環(huán)境的OpenGL呢径密?下面就會解答這個(gè)問題。
2.如何將java數(shù)據(jù)傳遞給本地系統(tǒng)庫中的OpenGL躺孝。
要知道睹晒,Android運(yùn)行代碼的時(shí)候并不是直接運(yùn)行在硬件上的,而是運(yùn)行在Dalvik虛擬機(jī)上的括细。運(yùn)行在虛擬機(jī)上的代碼不能直接訪問本地環(huán)境伪很。除非通過特定的API的接口。Android這樣設(shè)計(jì)其實(shí)也是為了降低系統(tǒng)的耦合性奋单,讓開發(fā)者不用去關(guān)心CPU等硬件锉试,專心搞軟件就行了。這樣做一般也沒問題览濒,但在與本地系統(tǒng)交互的時(shí)候就比較麻煩了呆盖,比如說OpenGL。OpenGL作為本地系統(tǒng)庫直接運(yùn)行在硬件上贷笛。
繼續(xù)上面那個(gè)問題:如何將java數(shù)據(jù)傳遞給本地系統(tǒng)庫中的OpenGL应又。 有兩種技術(shù)可以實(shí)現(xiàn):1.使用本地接口JNI技術(shù),這個(gè)技術(shù)已經(jīng)集成在Android系統(tǒng)android.opengl.GLES20中乏苦,我們可以直接調(diào)用. 2.改變內(nèi)存分配的方式株扛,java有一個(gè)特殊的集合,他們可以分配本地內(nèi)存快汇荐,并且把java的數(shù)據(jù)復(fù)制到本地內(nèi)存洞就。而本地內(nèi)存是可以被本地環(huán)境讀取,這樣就可以達(dá)到傳遞數(shù)據(jù)的目的掀淘。
代碼實(shí)現(xiàn)如下:
private FloatBuffer vertexData; //緩存的頂點(diǎn)數(shù)據(jù)
vertexData =
//allocateDirect分配本地內(nèi)存float數(shù)組的長度乘以每一個(gè)float類型占用的字節(jié)數(shù)
ByteBuffer.allocateDirect(tableVertices.length * BYTES_PER_FLOAT)
//告訴字節(jié)緩沖區(qū)按照本地字節(jié)序組織它的內(nèi)容? ? ? ? ? ? ? ? ? ?
//當(dāng)一個(gè)值占用多個(gè)字節(jié)旬蟋,比如32位整形數(shù),字節(jié)按照從高位到低位 或者從低位到高位排序
//排什么順序其實(shí)不重要革娄,重要的是程序運(yùn)行過程中所有的字節(jié)都得按同樣的順序排序倾贰,
//不能有的排正序冕碟,有的排倒序。 而? //order(ByteOrder.nativeOrder()就能達(dá)到這個(gè)目的匆浙。
.order(ByteOrder.nativeOrder())
//根據(jù)分配的內(nèi)存獲取一個(gè)能分配本地內(nèi)存的FloatBuffer實(shí)例對象安寺。
.asFloatBuffer();
//將頂點(diǎn)數(shù)據(jù) 內(nèi)存從虛擬機(jī)中拷貝到本地
vertexData.put(tableVertices);
現(xiàn)在OpenGL已經(jīng)可以讀取這些數(shù)據(jù),那么它會如何去使用這些數(shù)據(jù)呢吞彤? 這就涉及到OpenGL管道的概念了我衬。
OpenGL管道
大部分圖形系統(tǒng)都可以比作工廠中的裝配線(Assemble line)或者稱為管道(Pipeline)叹放。前一道的輸出作為下道工序的輸入饰恕。主 CPU 發(fā)出一個(gè)繪圖指令,然后可能由硬件部件完成坐標(biāo)變換井仰,裁剪埋嵌,添加顏色或是材質(zhì),最后在屏幕上顯示出來俱恶。
通過打開OpenGL管道的相應(yīng)開關(guān)將頂點(diǎn)參數(shù)傳給 OpenGL 庫雹嗦。然后調(diào)用函數(shù),對這些頂點(diǎn)按一定的方式進(jìn)行繪制合是,以達(dá)到顯示不同的圖形的目的了罪。
OpenGL ES 所有能夠繪制的基本圖形,點(diǎn)聪全,線段和三角形泊藕。其它所有復(fù)雜的 2D 或 3D 圖形都是由這些基本圖形構(gòu)成。
下面來通過一個(gè)具體實(shí)例來認(rèn)識OpenGL ES
———————————坑的分割—————
參考鏈接:
http://blog.csdn.net/hejjunlin/article/details/61615215
https://lord198712071.gitbooks.io/youyang_opengl-es-2-0/content/chapter1.html(這個(gè)不完整难礼,沒寫完娃圆。)
https://blog.piasy.com/2016/06/07/Open-gl-es-android-2-part-1/
(這里有個(gè)挺全面的實(shí)例)
http://www.reibang.com/c/30e2e76bc140
http://wiki.jikexueyuan.com/project/opengl-es-guide/introduction.html
http://www.cnblogs.com/sunminmin/p/4478578.html