Android OpenGL ES 開發教程(二)

最近在總結Android OpenGL ES的開發學習過程。本章爲總結第二章。主要就兩大重要內容聊起。

一、OpenGL ES中的基本幾何圖形。
想要在OpenGL ES中畫出複雜、炫酷的圖形出來(比如遊戲中的場景),必須掌握OpenGL ES中基本幾何圖形的繪製。本章使用的是GL10。
1. GL10.GL_POINTS:散點
這裏寫圖片描述
2. GL10.GL_LINES:無關聯的線段
這裏寫圖片描述
3. GL10.GL_LINE_STRIP:連續但不封閉線段
這裏寫圖片描述
4. GL10.GL_LINE_LOOP:連續封閉線段
這裏寫圖片描述
5. GL10.GL_TRIANGLES:無關聯三角形
這裏寫圖片描述
6. GL10.GL_TRIANGLE_STRIP:關聯三角形(說明一下,設P0P1P2P3P4P5爲頂點,此時將繪製△P0P1P2、△P1P2P3、△P2P3P4、△P3P4P5四個三角形)
這裏寫圖片描述
7. GL10.GL_TRIANGLE_FAN:共頂點三角形(說明一下,設P0P1P2P3P4P5爲頂點,此時將繪製△P0P1P2、△P0P2P3、△P0P3P4、△P0P4P5四個三角形)
這裏寫圖片描述

GL10只支持這集中基本幾何圖形,其他複雜的圖形都是有這些基本圖形合成的!!!

二、 OpenGL ES中的基本數據
要畫圖先要告訴設備怎麼畫,那麼就要有圖形的數據(物體上的點的座標或者點的座標的規律,是不是很拗口,這麼說吧,就是要繪製的物體的表面的數學模型)
1. Vertex(頂點)
一個實際場景,比如有一盆仙人球(圖片自行腦補)。仙人球的表面(一個粗略的球面,部分地方有點異型),球面的繪製要使用多個三角形來繪製(越多越好,當三角形的個數足夠多時,這裏寫圖片描述 特麼的,這個我打不出來,x表示三角形的個數,或者點的個數。x趨向於無窮大,就可以繪製出一個完美的球出來)
繪製散點(頂點)需要給出點的座標,並且數據類型必須轉化爲指定的類型(java.nio.Buffer),下面是一個例子:

    private float vertices[] = {
        -1.0f, 1.0f, 0.0f,
        -1.0f, -1.0f, 0.0f,
        1.0f, -1.0f, 0.0f,
        1.0f, 1.0f, 0.0f
    }
    /** {@link ByteBuffer#allocateDirect(int size)}
     * 因爲在OpenGL ES 中要求的數據類型是Buffer類型。
     * 因此要對float進行轉化,即將float數組轉換成FloatBuffer
     * allocateDirect中設置的是Buffer的大小:
     * 複習下Java中各基本數據類型之間的關係(你就會明白爲什麼要乘以4):
     * byte       8bit       1字節
     * char       16bit      2字節
     * short      16bit      2字節
     * int        32bit      4字節
     * long       64bit      8字節
     * float      32bit      4字節
     * double     64bit      8字節
     * 
     * 可以清晰的看出 1 float = 4 byte
     */
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteBuffer.nativeOrder());
    FloatBuffer vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

2.Edge(邊) 無需直接創建,在繪製面(三角形)時,會自動繪製三條邊。
3.Face(面) 在定義面時,頂點的順序是有要求的:
因爲在繪製面時,頂點的順序不同,繪製的面的方向也是不同的:
1) 頂點的順序如果是逆時針排布,那麼你看到的面就是此面的正面。
2) 頂點的順序如果是順時針排布,那麼你看到的面是此面的背面。
*一般來說繪製面爲了提升性能,只繪製面的正面,而不繪製面的背面:

    // 1.繪製正面
    gl.glFrontFace(GL10.GL_CCW);
    // 2.打開“忽略”設置
    gl.glEnable(GL10.GL_CULL_FACE);
    // 3.指定忽略的對象
    gl.glCullFace(GL10.GL_BACK);

4.Buffer
爲了提升繪圖性能,通常將vertex、color存儲在Buffer中。
Buffer這個類放在了Java.nio包中,nio表示的是new io的意思,是一個新的IO流包,流就是將文件等數據看作是byte數組。這種方法一般無法指定字節順序(不同的計算機系統Byte order 可能不同),操作如“在文件偏移10個字節出讀取一個四字節Little-endian整數“在使用Stream方式讀取文件時就不十分方便。此外,Stream 方法是按一個字節一個字節方式處理的,讀寫性能上不是很好。
java.nio 解決了上述java.io 包的這些侷限,java.io 包包含了Buffer,Channel, Charset 等,但OpenGL ES 只用到Buffer,Buffer具有以下特點:
1). 允許以內存緩衝區(buffer)的方式來管理一個Buffer 數組,可以整塊整塊的讀寫內存區域,並可以指定Byte order.(大頭或是小頭)。
2). 提供了在指定位置讀寫各種基本數據類型的簡便方法如 putInt ,putLong等。
3). 可以充分利用JVM提供的各種優化方法以達到和使用Native Code類型的讀寫性能。
4). 可以直接從OS的內存分配空間,這部分空間可以不受Java 的Garbage collector控制。稱爲Direct buffer.

詳情可參考:http://www.apkbus.com/thread-50879-1-1.html
另外關於Java GC機制可以參看我的博客:JVM中內存劃分和GC機制

————————不怎麼華麗的分割線———————-

下一章:Android OpenGL ES 開發教程(三)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章