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 簡介 5、Android 支持 OpenGL 列表
Android系統使用 OpenGL 的標准接口來支持3D圖形功能,android 3D 圖形系統也分為 java 框架和本地代碼兩部分。本地代碼主要實現的 OpenGL 接口的庫,在 Java 框架層,javax.microedition.khronos.opengles 是 java 標准的 OpenGL 包,android.opengl包提供了 OpenGL 系統和 Android GUI 系統之間的聯系。
- 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 還有更多的東西需要我們去探索,努力吧。
轉自:http://www.cnblogs.com/TerryBlog/archive/2010/07/09/1774475.html