一、基础知识:
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】
<?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】
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】
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); }}
三、效果:
本文博客源地址:http://blog.csdn.net/ypist