当前位置: 代码迷 >> Android >> 【Android开发学习18】Android OpenGL ES 日照glDrawArrays
  详细解决方案

【Android开发学习18】Android OpenGL ES 日照glDrawArrays

热度:68   发布时间:2016-05-01 11:36:59.0
【Android开发学习18】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

<?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

 

 

 

  相关解决方案