Android OpenGL教程-第一課【轉】


第一課 快速的開始一個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

(注:本教程轉自其他網頁,並加以修改,查看原網頁請點擊這里


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM