編輯:關於Android編程
OpenGL已經成了3D的一個"標准" 因為它能跨平台,接口也比較豐富,幾乎大部分的手機3D游戲都和OpenGL有關系。
當然還有微軟有direct X 但只能在微軟平台上使用。
OpenGL底層是c/c++實現,JAVA中使用都是用封裝好的類庫。Android提供了以下幾個接口包 可使用,基本能達到3D技術的要求。
Android平台用OpenGL ES 這個子集來處理圖像,現在OpenGL ES基本用2.0的了,很少再用1.0的,3.0還未流行起來。
首先編寫判斷Android設備是否支持OpenGL 2.0.
GLHelper.java加入一個判斷是否支持2.0版本的代碼方法。
public static boolean enableOpenGL2(Activity act) {
final ActivityManager mg = (ActivityManager) act.getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo configuration = mg.getDeviceConfigurationInfo();
boolean b = configuration.reqGlEsVersion >= 0x20000);
return b;
}我們需要擴展 android.opengl.GLSurfaceView 這個類,讓圖像繪制在SurfaceView上面,看看源碼發現這個類其實是擴展了SurfaceView做了寫封裝。
public class MyOpenGLView extends GLSurfaceView { //這個類就先空著,這一次沒有太多的代碼
public MyOpenGLView(Context context) {
super(context);
}
public MyOpenGLView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
我們把處理的各種方法封裝一下。
public class GLData {
public GLData() {
}
public static float[] singelTriangles = { //定義了2個三角形,組成了一個正方形,因為openGL ES只能是點,線和三角形
-0.3f, -0.3f,
0.3f, 0.3f,
-0.3f, 0.3f,
-0.3f, -0.3f,
0.3f, -0.3f,
0.3f, 0.3f
};
}

編寫2個簡單的頂點著色器和片段做色器。
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">public class GLScript {
public GLScript() {
}
public static final String vertex1 = "attribute vec4 mPosition;\n" +
"void main()\n" +
"{\n" +
"gl_Position=mPosition;\n " +
"}\n";
public static final String fragment1 = "precision mediump float;\n" +
"uniform vec4 mColor;\n" +
"void main(){ gl_FragColor=mColor;\n}";
}
vec4 mPosition 這個表示定義了一個4分量(x,y,z,w)的頂點,然後付給gl_Position 內置的變量中,OpenGL會編譯並且自動處理。
vec4 mColor 這個表示定義了一個顏色分量RGBA,最後一個是透明度,即是 紅綠藍.
腳本語言是OpenGL ES的核心,很多的渲染效果都需要腳本處理。
GLHelper.java添加編譯腳本的代碼方法.
public static int compileScript(int type, String script){
int objID = GLES20.glCreateShader(type); //創建一個著色器對象,TYPE表示頂點著色器和片段著色器
if (objID == 0) { //0表示有錯誤
return 0;
}
GLES20.glShaderSource(objID, script); //把腳本代碼傳給OpenGL 引擎
GLES20.glCompileShader(objID); //開始編譯
int[] status = new int[1];
GLES20.glGetShaderiv(objID, GLES20.GL_COMPILE_STATUS, status, 0); //看看編譯結果是否有錯誤。
Log.d("OPENGL","compileScript status info:" + GLES20.glGetShaderInfoLog(objID));
if (status[0] == 0) {
GLES20.glDeleteShader(objID);//有錯誤我們刪除這個對象。
Log.e("OPENGL", "Error Compile Script:" + script);
return 0;
}
return objID;
}如果編譯成功我們開始關聯OpenGL ES程序。
public static int linkGL(){
int programId = GLES20.glCreateProgram();//創建一個程序
if (programId == 0) {
Log.e("OPENGL", "Error Create Link Program");
return 0;
}
return programId;
}
public static int linkAttach(int vertexsharder,int fragmentsharder){
int programId = linkGL();
GLES20.glAttachShader(programId, vertexsharder); //和著色器進行關聯
GLES20.glAttachShader(programId, fragmentsharder);//和著色器進行關聯
GLES20.glLinkProgram(programId); //把program鏈接起來
int status[] = new int[1];
GLES20.glGetProgramiv(programId, GLES20.GL_LINK_STATUS, status, 0); //這地方一樣是檢查是否有錯誤發生。
Log.d("OPENGL","linkAttach link status is " + GLES20.glGetProgramInfoLog(programId));
if (status[0] == 0) {
Log.e("OPENGL","link status is error.");
GLES20.glDeleteProgram(programId);
return 0;
}
return programId;
}最後我們驗證程序是否有錯誤
public static boolean checkProgram(int programId){
GLES20.glValidateProgram(programId);
int status[] = new int[1];
GLES20.glGetProgramiv(programId,GLES20.GL_VALIDATE_STATUS, status,0);
if (status[0] == 0) {
Log.e("OPENGL","program is error");
return false;
}
return true;
}我們把代碼加入到渲染類中Renderer
public class MyOpenGLRenderer implements Renderer {
public static FloatBuffer verDataBuffer;
int colorLocation ;
int positionLocation ;
public MyOpenGLRenderer() {
// 申請直接內存空間,並使用native字節序列
verDataBuffer = ByteBuffer.allocateDirect(4 * GLData.singelTriangles.length)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
verDataBuffer.put(GLData.singelTriangles); //這是一個正方形,等會貼代碼。
}
@Override
public void onDrawFrame(GL10 arg0) { //這個方法會不斷的重繪
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUniform4f(colorLocation, 0f, 0f, 0F, 0f); //這裡是黑色,顏色將傳入給colorLocation
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);//畫三角形,有6個頂點 所以從0,6開始
}
@Override
public void onSurfaceChanged(GL10 arg0, int w, int h) {
GLES20.glViewport(0, 0, w, h);
}
@Override
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1) {
GLES20.glClearColor(1F, 1F, 1F, 0.0F); //下面的代碼都是組織起來用我們編寫的GLHelper類.
int vertexsharder = GLHelper.compileScript(GLES20.GL_VERTEX_SHADER, GLScript.vertex1);
int fragmentsharder = GLHelper.compileScript(GLES20.GL_FRAGMENT_SHADER, GLScript.fragment1);
int programId = GLHelper.linkAttach(vertexsharder, fragmentsharder);
boolean isOK = GLHelper.checkProgram(programId);
if (isOK) {
Log.d("","start draw..............");
GLES20.glUseProgram(programId); //我們開始使用這個程序
colorLocation = GLES20.glGetUniformLocation(programId, "mColor");//獲得變量位置,可以理解為內存地址,OpenGL 將為在這個地址中取數據
positionLocation = GLES20.glGetAttribLocation(programId, "mPosition");
verDataBuffer.position(0);//數據開始端讀取
GLES20.glVertexAttribPointer(positionLocation, 2, GLES20.GL_FLOAT, false, 0, verDataBuffer);//這個地方把頂點數據與變量關聯起來
GLES20.glEnableVertexAttribArray(positionLocation);//這地方使得能夠使用頂點數組
}
}
} private MyOpenGLView gLView;
private boolean openGLEnable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (GLHelper.enableOpenGL2(this)) {
openGLEnable = true;
}
Log.d("","OpenGL is Enable:" + openGLEnable);
gLView = new MyOpenGLView(this);
gLView.setEGLContextClientVersion(2);//可以使用OpenGL ES 2.0
gLView.setRenderer(new MyOpenGLRenderer());
setContentView(gLView);
}
運行結果很簡單就是中間一個正方形。
OpenGL ES入門相對還是比較復雜的,因為函數的調用和平時用的JAVA,, C++ 庫都不太一樣
3D的東西復雜不僅僅是多了一個坐標Z,還有很多的渲染技術。
工程結構:

Android編程之基於Log演示一個activity生命周期實例詳解
本文實例講述了Android編程之基於Log演示一個activity生命周期。分享給大家供大家參考,具體如下:利用Android的Log 演示一個activity的生命周
Android Socket編程學習筆記
通常也稱作套接字,用於描述IP地址和端口,是一個通信鏈的句柄。在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定
Android clipChildren屬性實例詳解
前言 前幾天有在微博上推薦過一個博客,看他文章時發現了這個屬性。有些屬性不常用,但需要的時候非常有用,於是做了個例子,正好項目用到,與大家分享一下。
android:模擬水波效果的自定義View
歡迎Fork,歡迎Star1.先看效果2.再看關鍵代碼描繪函數y = Asin(wx+d)+offset /** * 使用路徑描繪繪制的區域 *