第一課 快速的開始一個Android OpenGL項目
首先,讀懂我們的教程,需要有android的初步基礎,我們這里只是通過android提供的SDK,來進行OpenGL的學習,所以你必須先學習如何建立一個android的項目,同時了解activity的生命周期和android下的屏幕或鍵盤響應機制。
好的,開始建立一個android的項目Lesson1,Activity的名字的名字我們叫Lesson。
Lesson類:
import android.app.Activity; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; public class Lesson extends Activity { private OpenGLView mOpenGLView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 去標題欄 requestWindowFeature(Window.FEATURE_NO_TITLE); // 設置全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); mOpenGLView = new OpenGLView(this); setContentView(mOpenGLView); } }
我們在這里用了一個OpenGLView類,把這個類直接設為contentView。
OpenGLView類:
import android.content.Context; import android.opengl.GLSurfaceView; /** * OpenGLView類繼承自GLSurfaceView,這個類是android提供的用opengl畫圖的類。 */ public class OpenGLView extends GLSurfaceView { private OpenGLRenderer mRenderer; public OpenGLView(Context context) { super(context); mRenderer = new OpenGLRenderer(); setRenderer(mRenderer); // TODO Auto-generated constructor stub } }
OpenGLView類繼承自GLSurfaceView,這個類是android提供的用opengl畫圖的類。這里用了OpenGLRenderer類,Render是渲染的意思,真正畫圖的操作在這個類里面。
OpenGLRenderer類:
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView.Renderer; /** * 渲染器類,實現了GLSurfaceView.Renderer接口,實現這個接口,需要實現3個方法:OnSurfaceCreated(), * OnSurfaceChanged(),OnDrawFrame()。 */ public class OpenGLRenderer implements Renderer { /** * 該方法是畫圖方法,類似於View類的OnDraw(),一般所有的畫圖操作都在這里實現。 */ @Override public void onDrawFrame(GL10 gl) { // 清除屏幕和深度緩存。 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 重置當前的模型觀察矩陣。 gl.glLoadIdentity(); } /** * 在Surface發生改變的時候調用,例如從豎屏切換到橫屏的時候 */ @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // 設置輸出屏幕大小 gl.glViewport(0, 0, width, height); } /** * 在Surface創建的時候調用,一般在這里做一個初始化openggl的操作 */ @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 啟用smooth shading(陰影平滑)。陰影平滑通過多邊形精細的混合色彩,並對外部光進行平滑。 gl.glShadeModel(GL10.GL_SMOOTH); // 設置清除屏幕時所用的顏色,參數對應(紅,綠,藍,Alpha值)。色彩值的范圍從0.0f到1.0f。0.0f代表最黑的情況,1.0f就是最亮的情況。 gl.glClearColor(0f, 0f, 0f, 0f); // 下面三行是關於depth buffer(深度緩存)的。將深度緩存設想為屏幕后面的層。深度緩存不斷的對物體進入屏幕內部有多深進行跟蹤。 gl.glClearDepthf(1.0f); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); // 這里告訴OpenGL我們希望進行最好的透視修正。這會十分輕微的影響性能。但使得透視圖看起來好一點。 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); } }
這個類實現了GLSurfaceView.Renderer接口,實現這個接口,需要實現3個方法:OnSurfaceCreated(),OnSurfaceChanged(),OnDrawFrame()。第一個方法在Surface創建的時候調用,我們一般在這里做一個初始化openggl的操作,第二個方法在Surface發生改變的時候調用,例如從豎屏切換到橫屏的時候;第三個方法是畫圖方法,類似於View類的OnDraw(),一般所有的畫圖操作都在這里實現。
注:現在我們大多是在JAVA層操作,后來學習深入后,這里畫圖的一些操作大多需要很多的計算,我們可以用NDK在C++層進行。
我們看OnSurfaceCreate里面的代碼,這里都是在做對OpengGL的初始化。
gl.glShadeModel(GL10.GL_SMOOTH);
啟用smooth shading(陰影平滑)。陰影平滑通過多邊形精細的混合色彩,並對外部光進行平滑,在以后的課程中會看到他的效果。
gl.glClearColor(0f, 0f, 0f, 0f);
設置清除屏幕時所用的顏色。如果您對色彩的工作原理不清楚的話,我快速解釋一下。色彩值的范圍從0.0f到1.0f。0.0f代表最黑的情況,1.0f就是最亮的情況。glClearColor 后的第一個參數是Red Intensity(紅色分量),第二個是綠色,第三個是藍色。最大值也是1.0f,代表特定顏色分量的最亮情況。最后一個參數是Alpha值。當它用來清除屏幕的時候,我們不用關心第四個數字。現在讓它為0.0f。我會用另一個教程來解釋這個參數。
通過混合三種原色(紅、綠、藍),您可以得到不同的色彩。希望您在學校里學過這些。因此,當您使用glClearColor(0.0f,0.0f,1.0f,0.0f),您將用亮藍色來清除屏幕。如果您用 glClearColor(0.5f,0.0f,0.0f,0.0f)的話,您將使用中紅色來清除屏幕。不是最亮(1.0f),也不是最暗 (0.0f)。要得到白色背景,您應該將所有的顏色設成最亮(1.0f)。要黑色背景的話,您該將所有的顏色設為最暗(0.0f)。我們在這里設置屏幕為黑色。
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
這三行是關於depth buffer(深度緩存)的。將深度緩存設想為屏幕后面的層。深度緩存不斷的對物體進入屏幕內部有多深進行跟蹤。我們本節的程序其實沒有真正使用深度緩存,但幾乎所有在屏幕上顯示3D場景OpenGL程序都使用深度緩存。它的排序決定那個物體先畫。這樣您就不會將一個圓形后面的正方形畫到圓形上來。深度緩存是OpenGL十分重要的部分。
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
這里告訴OpenGL我們希望進行最好的透視修正。這會十分輕微的影響性能。但使得透視圖看起來好一點。
在OnDrawFrame方法中
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
清除屏幕和深度緩存。
gl.glLoadIdentity();
重置當前的模型觀察矩陣。
本課的效果只是生成了一個黑色的屏幕,很多代碼並沒有發生應有的效果,后面的課程中,我們會使用到這些代碼,到時候大家就能看到這些代碼所產生的效果。
附:
1. 我們來改變背景的顏色
將gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);從SurfaceCreate放到OnDrawFrame里面,這里設置為紅色了,運行下看看,是不是背景成紅色了。
2. 加上點擊屏幕來改變背景的顏色
第一步,在render里面加3個float(成員變量)
private float cr,cg,cb;
第二步,加個設置r,g,b的函數
// (這是附加的)設置RGB顏色的方法 public void setColor(float r, float g, float b) { cr = r; cg = g; cb = b; }
第三步,在glclearColor里面用cr,cg,cb來設置顏色。
gl.glClearColor(cr, cg, cb, 0.0f);
第四步,在view (OpenGLView類)里面override onTouchEvent函數,在這里響應點擊屏幕的事件。
@Override public boolean onTouchEvent(final MotionEvent event) { /* * 由於渲染對象是運行在一個獨立的渲染線程中,所以需要采用跨線程的機制來進行事件的處理。 * 但是Android提供了一個簡便的方法: * 我們只需要在事件處理中使用queueEvent(Runnable)就可以了. */ queueEvent(new Runnable() { @Override public void run() { mRenderer.setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f); } }); return super.onTouchEvent(event); }
至於這里為什么用final,大家去網上查查,剛好也復習一下內部類調用參數,需要final這個知識點。
運行效果:
個人資料:http://blog.csdn.net/xiajun07061225/article/details/7455283
(注:本教程轉自其他網頁,並加以修改,查看原網頁請點擊這里)