Android OpenGL ES 光照glDrawArrays

一、基礎知識:

 

1..光照介紹:

①環境光:

 來自四面八方,所有場景中的對象都處於環境光的照射中。

②漫射光:

 由特定的光源產生,並在場景中的對象表面產生反射。

 處於漫射光直接照射下的任何對象表面都變得很亮,而幾乎未被照射到的區域就顯示得要暗一些。

 

2.光照使用:

①設定光源參數:

 //環境光

 private float[] lightAmbient;

 private FloatBuffer AmbientBuffer;

 //漫射光

 private float[] lightDiffuse;

 private FloatBuffer diffuseBuffer;

 //光源位置

 private float[] lightPosition;

 private FloatBuffer positionBuffer;

 //燈光

 lightAmbient = new float[]{0.5f,0.5f,0.5f,1.0f};

 lightDiffuse = new float[]{1.0f,1.0f,1.0f,1.0f};

 lightPosition = new float[]{0.0f,0.0f,2.0f,1.0f};

 //環境光

 ByteBuffer ambientbb = ByteBuffer.allocateDirect(lightAmbient.length * 4 * 6);

 ambientbb.order(ByteOrder.nativeOrder());

 AmbientBuffer = ambientbb.asFloatBuffer();

 AmbientBuffer.put(lightAmbient);

 AmbientBuffer.position(0);

  

 //漫射光

 ByteBuffer diffusebb = ByteBuffer.allocateDirect(lightDiffuse.length * 4 * 6);

 diffusebb.order(ByteOrder.nativeOrder());

 diffuseBuffer = diffusebb.asFloatBuffer();

 diffuseBuffer.put(lightDiffuse);

 diffuseBuffer.position(0);

  

 //燈光位置

 ByteBuffer positionbb = ByteBuffer.allocateDirect(lightPosition.length * 4 * 6);

 positionbb.order(ByteOrder.nativeOrder());

 positionBuffer = positionbb.asFloatBuffer();

 positionBuffer.put(lightPosition);

 positionBuffer.position(0);

 

②設置光源:

 glLightfv (

  int light,  // 光源的ID

  int pname,   // 光源的類型

  FloatBuffer params // 光源的數組

 ) 

設定的屬性,主要由第二個參數決定:

GL_AMBIENT 環境光(光源泛光強度的RGBA值)

GL_DIFFUSE 漫射光(光源漫反射強度的RGBA值)

GL_SPECULAR 高光(光源鏡面反射強度的RGBA值)

GL_POSITION 位置(光源的位置)

GL_SPOT_DIRECTION 方向(聚光燈的方向)

GL_SPOT_CUTOFF 光的角度(聚光燈的截止角度)

 

 // 設置環境光

 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, AmbientBuffer);

 // 設置漫射光

 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseBuffer);

 // 設置燈光位置

 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionBuffer);

③啟用光源:

 //啟用一號光源

 gl.glEnable(GL10.GL_LIGHT1);

 

 

 

二、實現:

1. 界面編輯:

【res\layout\main.xml】

[html]  

<?xml version="1.0" encoding="utf-8"?>  

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  

    android:orientation="vertical"  

    android:layout_width="fill_parent"  

    android:layout_height="fill_parent"  

    >  

<TextView    

    android:layout_width="fill_parent"   

    android:layout_height="wrap_content"   

    android:text="@string/hello"  

    />  

  

<Button  

    android:id="@+id/button1"  

    android:layout_width="145dp"  

    android:layout_height="wrap_content"  

    android:text="演示開始" />  

  

</LinearLayout>  

 

 

2.代碼編輯:

【\src\com\yarin\android\Examples\Activity01.java】

[java]  

package com.yarin.android.Examples_12_05;  

  

import java.io.IOException;  

import java.io.InputStream;  

  

import javax.microedition.khronos.opengles.GL10;  

  

import android.app.Activity;  

import android.content.res.Resources;  

import android.graphics.Bitmap;  

import android.graphics.BitmapFactory;  

import android.opengl.GLSurfaceView;  

import android.opengl.GLUtils;  

import android.opengl.GLSurfaceView.Renderer;  

import android.os.Bundle;  

import android.view.View;  

import android.widget.Button;  

  

public class Activity01 extends Activity  

{  

    Renderer render = new GLRender();  

    GLSurfaceView glView;  

    Button start;           // 演示開始  

  

      

    /** Called when the activity is first created. */  

    @Override  

    public void onCreate(Bundle savedInstanceState)  

    {  

        super.onCreate(savedInstanceState);  

        GLImage.load(this.getResources());  

        glView = new GLSurfaceView(this);  

          

          

        glView.setRenderer(render);  

        setContentView(R.layout.main);  

        start=(Button)findViewById(R.id.button1);   // "演示開始"按鈕初始化  

        start.setOnClickListener(new View.OnClickListener() {  

              

            @Override  

            public void onClick(View v) {  

                // TODO Auto-generated method stub  

                setContentView(glView);  

            }  

        });  

          

        //setContentView(glView);  

    }  

}  

  

class GLImage  

{  

    public static Bitmap iBitmap;  

    public static Bitmap jBitmap;  

    public static Bitmap kBitmap;  

    public static Bitmap lBitmap;  

    public static Bitmap mBitmap;  

    public static Bitmap nBitmap;  

    public static Bitmap close_Bitmap;  

      

      

    public static void load(Resources resources)  

    {  

        iBitmap = BitmapFactory.decodeResource(resources, R.drawable.img);  

        jBitmap = BitmapFactory.decodeResource(resources, R.drawable.jmg);  

        kBitmap = BitmapFactory.decodeResource(resources, R.drawable.kmg);  

        lBitmap = BitmapFactory.decodeResource(resources, R.drawable.lmg);  

        mBitmap = BitmapFactory.decodeResource(resources, R.drawable.mmg);  

        nBitmap = BitmapFactory.decodeResource(resources, R.drawable.nmg);  

        close_Bitmap = BitmapFactory.decodeResource(resources, R.drawable.close);  

    }  

}  

 

 

【\src\com\yarin\android\Examples\GLRender.java】

[java]  

package com.yarin.android.Examples_12_05;  

  

import java.io.IOException;  

import java.io.InputStream;  

import java.nio.ByteBuffer;  

import java.nio.IntBuffer;  

import java.nio.ByteOrder;    

import java.nio.FloatBuffer;  

  

import javax.microedition.khronos.egl.EGLConfig;  

import javax.microedition.khronos.opengles.GL10;  

  

import android.graphics.Bitmap;  

import android.graphics.BitmapFactory;  

import android.opengl.GLUtils;  

import android.opengl.GLSurfaceView.Renderer;  

import android.content.Context;  

  

public class GLRender implements Renderer  

{  

    /** 

     * 渲染類 

     * author:pis 

     */  

  

    private int one = 0x10000;  

  

    public boolean mFlag ;  

    public boolean bLight = true;//是否開啟燈光  

      

    private int[] vertices;//頂點數組  

    private int[] textCood;//紋理數組  

      

    float step = 0.3f;  

    float xrot,yrot; //旋轉  

    float xSpeed,ySpeed; //移動速度  

    private int[] textures = new int[1];  

      

    private IntBuffer vertexBuffer; //頂點緩沖  

    private IntBuffer textCoodBuffer; //紋理緩沖  

    /** 

     * 設置燈光 

     * @param context 

     */  

    //環境光  

    private float[] lightAmbient;  

    private FloatBuffer AmbientBuffer;  

    //漫射光  

    private float[] lightDiffuse;  

    private FloatBuffer diffuseBuffer;  

    //光源位置  

    private float[] lightPosition;  

    private FloatBuffer positionBuffer;  

      

    /** 

     * 初始化緩沖數據 

     */  

    private void initBuffer(){  

        //頂點  

        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);  

        vbb.order(ByteOrder.nativeOrder());  

        vertexBuffer = vbb.asIntBuffer();  

        vertexBuffer.put(vertices);  

        vertexBuffer.position(0);  

          

        //紋理  

        ByteBuffer tbb = ByteBuffer.allocateDirect(textCood.length * 4 * 6);  

        tbb.order(ByteOrder.nativeOrder());  

        textCoodBuffer = tbb.asIntBuffer();  

        for (int i = 0; i < 6; i++) {              

            textCoodBuffer.put(textCood);  

        }  

        textCoodBuffer.position(0);  

          

        //環境光  

        ByteBuffer ambientbb = ByteBuffer.allocateDirect(lightAmbient.length * 4 * 6);  

        ambientbb.order(ByteOrder.nativeOrder());  

        AmbientBuffer = ambientbb.asFloatBuffer();  

        AmbientBuffer.put(lightAmbient);  

        AmbientBuffer.position(0);  

          

        //漫射光  

        ByteBuffer diffusebb = ByteBuffer.allocateDirect(lightDiffuse.length * 4 * 6);  

        diffusebb.order(ByteOrder.nativeOrder());  

        diffuseBuffer = diffusebb.asFloatBuffer();  

        diffuseBuffer.put(lightDiffuse);  

        diffuseBuffer.position(0);  

          

        //燈光位置  

        ByteBuffer positionbb = ByteBuffer.allocateDirect(lightPosition.length * 4 * 6);  

        positionbb.order(ByteOrder.nativeOrder());  

        positionBuffer = positionbb.asFloatBuffer();  

        positionBuffer.put(lightPosition);  

        positionBuffer.position(0);  

          

    }  

    /** 

     * 初始化頂點、紋理、燈光數據 

     */  

    private void initData(){  

        //頂點數組  

        vertices = new int[] { -one, -one, one, one, -one, one, -one, one, one,  

                one, one, one, one, -one, one, one, -one, -one, one, one, one,  

                one, one, -one, one, -one, -one, -one, -one, -one, one, one,  

                -one, -one, one, -one, -one, -one, -one, -one, -one, one, -one,  

                one, -one, -one, one, one, -one, one, -one, one, one, -one,  

                -one, one, one, one, one, one, -one, -one, -one, -one, -one,  

                one, one, -one, -one, one, -one, one };  

  

        //紋理數組,貼圖時註意android中坐標與OpengGL 中定義的不同,android,y軸是向下的  

        textCood = new int[] { 0, 0, one, 0, 0, one, one, one };  

        //燈光  

        lightAmbient = new float[]{0.5f,0.5f,0.5f,1.0f};  

        lightDiffuse = new float[]{1.0f,1.0f,1.0f,1.0f};  

        lightPosition = new float[]{0.0f,0.0f,2.0f,1.0f};  

  

          

    }  

    public GLRender() {  

        mFlag=true;  

        initData();  

        initBuffer();  

    }  

  

      

    @Override  

    public void onDrawFrame(GL10 gl) {  

        //清除顏色和深度緩存  

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);  

        gl.glLoadIdentity();  

          

        //啟用燈光  

        gl.glEnable(GL10.GL_LIGHTING);  

          

        //啟用頂點和紋理緩存  

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  

        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  

        //移動和旋轉設置  

        gl.glTranslatef(0.0f, 0.0f, -6.0f);  

        gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);  

        gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);  

          

        //設置頂點和紋理,經常忘記設置,唉!  

        gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertexBuffer);  

        gl.glTexCoordPointer(2,GL10.GL_FIXED,0,textCoodBuffer);  

          

        //繪制六個面,貼圖  

        for (int i = 0; i < 6; i++) {  

            switch(i)  

            {  

            case 0:  

                // 8.生成紋理  

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.iBitmap, 0);  

                break;  

            case 1:  

                // 生成紋理  

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.jBitmap, 0);  

                break;  

            case 2:  

                // 生成紋理  

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.kBitmap, 0);  

                break;  

            case 3:  

                // 生成紋理  

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.lBitmap, 0);  

                break;  

            case 4:  

                // 生成紋理  

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0);  

                break;  

            case 5:  

                // 生成紋理  

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.nBitmap, 0);  

                break;                                

            }             

            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, i * 4, 4);  

        }  

        //取消緩存,需我們自己手動  

        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);  

        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  

        gl.glLoadIdentity();  

          

        if (mFlag) {  

            xrot += 0.5f;  

            yrot += 0.5f;  

        }  

        if (!bLight) {  

            gl.glDisable(GL10.GL_LIGHT1);  

        } else {  

            gl.glEnable(GL10.GL_LIGHT1);  

        }  

    }  

  

    @Override  

    public void onSurfaceChanged(GL10 gl, int width, int height) {  

        //場景大小  

        gl.glViewport(0, 0, width, height);  

        float ratio = (float) 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) {  

        //透視效果  

        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);  

        //清屏  

        gl.glClearColor(0, 0, 0, 0);  

        //啟用陰影平滑  

        gl.glShadeModel(GL10.GL_SMOOTH);  

        //清除深度緩存  

        gl.glClearDepthf(one);  

        //啟用深度緩存  

        gl.glEnable(GL10.GL_DEPTH_TEST);  

        //深度緩存模式  

        gl.glDepthFunc(GL10.GL_LEQUAL);  

          

        /** 

         * 設置紋理 

         */  

        //啟用紋理  

        gl.glEnable(GL10.GL_TEXTURE_2D);  

        //創建紋理  

        gl.glGenTextures(1, textures, 0);  

        //綁定紋理  

        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);  

        //生成紋理  

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.kBitmap, 0);  

        //線性濾波處理  

        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,  

                GL10.GL_LINEAR);  

        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,  

                GL10.GL_LINEAR);  

        /** 

         * 設置燈光 

         */  

          

        //設置環境光  

        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, AmbientBuffer);  

        //設置漫射光  

        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseBuffer);  

        //設置燈光位置  

        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionBuffer);  

        //啟用1號燈光  

        gl.glEnable(GL10.GL_LIGHT1);      

          

    }  

}  

 

 

 

三、效果:

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *