Android OpenGL 簡介

1、什麼是 OpenGL?

  OpenGL 是個專業的3D程序接口,是一個功能強大,調用方便的底層3D圖形庫。OpenGL  的前身是 SGI 公司爲其圖形工作站開的 IRIS GL。IRIS GL 是一個工業標準的3D圖形軟件接口,功能雖然強大但是移植性不好,於是 SGI 公司便在 IRIS GL 的基礎上開發 OpenGL  。具體詳細的介紹請。

2、OpenGL 的發展歷程

  1992年7月 發佈了 OpenGL 1.0 版本,並與微軟共同推出 Windows NT 版本的 OpenGL 。

  1995年 OpenGL 1.1 版本面市,加入了新功能,並引入了紋理特性等等。

  一直到 2009年8月Khronos小組發佈了OpenGL 3.2,這是一年以來OpenGL進行的第三次重要升級。

        具體特點及功能、 OpenGL 現狀、發展歷程、OpenGL 規範、編程入門請 點擊這裏

3、OpenGL  ES 簡介

      Android 3D 引擎採用的是OpenGL ES。OpenGL ES是一套爲手持和嵌入式系統設計的3D引擎API,由Khronos公司維護。在PC領域,一直有兩種標準的3D API進行競爭,OpenGL 和 DirectX。一般主流的遊戲和顯卡都支持這兩種渲染方式,DirectX在Windows平臺上有很大的優勢,但是 OpenGL 具有更好的跨平臺性。

由於嵌入式系統和PC相比,一般說來,CPU、內存等都比PC差很多,而且對能耗有着特殊的要求,許多嵌入式設備並沒有浮點運算協處理器,針對嵌入式系統的以上特點,Khronos對標準的 OpenGL 系統進行了維護和改動,以期望滿足嵌入式設備對3D繪圖的要求。

4、 Android OpenGL ES 簡介

Android系統使用 OpenGL 的標準接口來支持3D圖形功能,android 3D 圖形系統也分爲 java 框架和本地代碼兩部分。本地代碼主要實現的 OpenGL 接口的庫,在 Java 框架層,javax.microedition.khronos.opengles 是 java 標準的 OpenGL 包,android.opengl包提供了 OpenGL 系統和 Android GUI 系統之間的聯繫。

 5、Android 支持 OpenGL 列表

1、GL
2、GL 10
3、GL 10 EXT
4、GL 11
5、GL 11 EXT
6、GL 11 ExtensionPack
我們將使用 GL10 這個類開始接觸 OpenGL ,探索3D 領域。

6、一步一步實現自己的 Renderer 類

在 Android 中我們使用 GLSurfaceView 來顯示 OpenGL 視圖,該類位於 android.opengl 包裏面。它提供了一個專門用於渲染3D 的接口 Renderer 。接下來我們就來一步步構建自己的 Renderer 類。

1、爲 Renderer 類趕回命名空間

import android.opengl.GLSurfaceView.Renderer;
 

 

2、新建一個類來實現 Renderer 接口,代碼如下:

public class ThreeDGl implements Renderer 
{}

 

3、如上代碼所寫,程序實現了 Renderer 類,則必須重寫以下方法

public void onDrawFrame(GL10 gl) 
{}
public void onSurfaceChanged(GL10 gl, int width, int height)
{}
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{}

 

4、當窗口被創建時需要調用 onSurfaceCreate ,我們可以在這裏對 OpenGL 做一些初始化工作,例如:

       // 啓用陰影平滑
        gl.glShadeModel(GL10.GL_SMOOTH);
        
        // 黑色背景
        gl.glClearColor(0, 0, 0, 0);
        
        // 設置深度緩存
        gl.glClearDepthf(1.0f);                            
        // 啓用深度測試
        gl.glEnable(GL10.GL_DEPTH_TEST);                        
        // 所作深度測試的類型
        gl.glDepthFunc(GL10.GL_LEQUAL);                            
        
        // 告訴系統對透視進行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

 

glHint 用於告訴 OpenGL 我們希望進行最好的透視修正,這會輕微地影響性能,但會使得透視圖更好看。
glClearColor 設置清除屏幕時所用的顏色,色彩值的範圍從 0.0f~1.0f 大小從暗到這的過程。
glShadeModel 用於啓用陰影平滑度。陰影平滑通過多邊形精細地混合色彩,並對外部光進行平滑。
glDepthFunc 爲將深度緩存設想爲屏幕後面的層,它不斷地對物體進入屏幕內部的深度進行跟蹤。
glEnable 啓用深度測試。
5、當窗口大小發生改變時系統將調用 onSurfaceChange 方法,可以在該方法中設置 OpenGL 場景大小 ,代碼如下:
//設置OpenGL場景的大小
gl.glViewport(0, 0, width, height);
 

6、場景畫出來了,接下來我們就要實現場景裏面的內容,比如:設置它的透視圖,讓它有種越遠的東西看起來越小的感覺,代碼如下:

        //設置投影矩陣
        gl.glMatrixMode(GL10.GL_PROJECTION);
        //重置投影矩陣
        gl.glLoadIdentity();
        // 設置視口的大小
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
        // 選擇模型觀察矩陣
        gl.glMatrixMode(GL10.GL_MODELVIEW);    
        // 重置模型觀察矩陣
        gl.glLoadIdentity();    

 

gl.glMatrixMode(GL10.GL_PROJECTION); 指明接下來的代碼將影響 projection matrix (投影矩陣),投影矩陣負責爲場景增加透視度。
 gl.glLoadIdentity(); 此方法相當於我們手機的重置功能,它將所選擇的矩陣狀態恢復成原始狀態,調用  glLoadIdentity(); 之後爲場景設置透視圖。
gl.glMatrixMode(GL10.GL_MODELVIEW);   指明任何新的變換將會影響 modelview matrix (模型觀察矩陣)。
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 此方法,前面4個參數用於確定窗口的大小,而後面兩個參數分別是在場景中所能繪製深度的起點和終點。
7、瞭解了上面兩個重寫方法的作用和功能之後,第三個方法 onDrawFrame 從字面上理解就知道此方法做繪製圖操作的。嗯,沒錯。在繪圖之前,需要將屏幕清除成前面所指定的顏色,清除嘗試緩存並且重置場景,然後就可以繪圖了, 代碼如下:
// 清除屏幕和深度緩存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 重置當前的模型觀察矩陣
gl.glLoadIdentity();
 

8、Renderer 類在實現了上面的三個重寫之後,在程序入口中只需要調用

Renderer render=new ThreeDGl(this);
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GLSurfaceView gview=new GLSurfaceView(this);
        gview.setRenderer(render);
        setContentView(gview);
    }

 

即可將我們繪製的圖形顯示出來。
下面分享一段使用Renderer類繪製的三角形和四邊形的代碼:

 

OpenGL 參考代碼

package com.terry;

import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;

public class GLRender implements Renderer{

    float rotateTri,rotateQuad;
    int one=0x10000;
    
    //三角形的一個頂點
    private IntBuffer triggerBuffer=IntBuffer.wrap(new int[]{
            0,one,0,     //上頂點
            -one,-one,0,    //左頂點
            one,-one,0    //右下點
    });
    
    //正方形的四個頂點
    private IntBuffer quateBuffer=IntBuffer.wrap(new int[]{
            one,one,0,
            -one,-one,0,
            one,-one,0,
            -one,-one,0
    });
    
    
    private IntBuffer colorBuffer=IntBuffer.wrap(new int[]{
            one,0,0,one,
            0,one,0,one,
            0,0,one,one
    });
    
    
    
    @Override
    public void onDrawFrame(GL10 gl) {
        // TODO Auto-generated method stub
        
        // 清除屏幕和深度緩存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 重置當前的模型觀察矩陣
        gl.glLoadIdentity();


        // 左移 1.5 單位,並移入屏幕 6.0
        gl.glTranslatef(-1.5f, 0.0f, -6.0f);
         //設置旋轉
        gl.glRotatef(rotateTri, 0.0f, 1.0f, 0.0f);
        
        //設置定點數組
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        //設置顏色數組
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        
        gl.glColorPointer(4, GL10.GL_FIXED, 0, colorBuffer);
        // 設置三角形頂點
        gl.glVertexPointer(3, GL10.GL_FIXED, 0, triggerBuffer);
        //繪製三角形
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
        
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        
        //繪製三角形結束
        gl.glFinish();
        
        /***********************/
        /* 渲染正方形 */
        // 重置當前的模型觀察矩陣
        gl.glLoadIdentity();
        
        // 左移 1.5 單位,並移入屏幕 6.0
        gl.glTranslatef(1.5f, 0.0f, -6.0f);
        
        // 設置當前色爲藍色
        gl.glColor4f(0.5f, 0.5f, 1.0f, 1.0f);
        //設置旋轉
        gl.glRotatef(rotateQuad, 1.0f, 0.0f, 0.0f);
        
        //設置和繪製正方形
        gl.glVertexPointer(3, GL10.GL_FIXED, 0, quateBuffer);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        
        //繪製正方形結束
        gl.glFinish();

        //取消頂點數組
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        
        //改變旋轉的角度
        rotateTri += 0.5f;
        rotateQuad -= 0.5f;
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // TODO Auto-generated method stub
        
        float ratio = (float) width / height;
        //設置OpenGL場景的大小
        gl.glViewport(0, 0, width, height);
        //設置投影矩陣
        gl.glMatrixMode(GL10.GL_PROJECTION);
        //重置投影矩陣
        gl.glLoadIdentity();
        // 設置視口的大小
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
        // 選擇模型觀察矩陣
        gl.glMatrixMode(GL10.GL_MODELVIEW);    
        // 重置模型觀察矩陣
        gl.glLoadIdentity();    
        
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // TODO Auto-generated method stub
        // 啓用陰影平滑
        gl.glShadeModel(GL10.GL_SMOOTH);
        
        // 黑色背景
        gl.glClearColor(0, 0, 0, 0);
        
        // 設置深度緩存
        gl.glClearDepthf(1.0f);                            
        // 啓用深度測試
        gl.glEnable(GL10.GL_DEPTH_TEST);                        
        // 所作深度測試的類型
        gl.glDepthFunc(GL10.GL_LEQUAL);                            
        
        // 告訴系統對透視進行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
    }

}

 

到此基本對 OpenGL 有一些瞭解,當然OpenGL 還有更多的東西需要我們去探索,努力吧。

 

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