一、基础知识:
1..光照介绍:
①环境光:
来自四面八方,所有场景中的对象都处于环境光的照射中。
②漫射光:
由特定的光源产生,并在场景中的对象表面产生反射。
处于漫射光直接照射下的任何对象表面都变得很亮,而几乎未被照射到的区域就显示得要暗一些。
2.光照使用:
①设定光源参数:
//定义环境光(r,g,b,a)
FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f,0.5f,0.5f,1.0f});
//定义漫射光
FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f,1.0f,1.0f,1.0f});
//定义光源的位置(前三个参数为坐标X,Y,Z; 第四个参数为1.0f,是告诉OpenGl这里指定的坐标就是光源的位置)
FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,0.0f,2.0f,1.0f});
②设置光源:
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, lightAmbient);
//设置漫射光
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse);
//设置光源的位置
gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition);
③启用光源:
//启用一号光源
gl.glEnable(GL10.GL_LIGHT1);
3、混合实现:
如果开启混合,则根据Alpha值来显示透明效果;
如果未开启混合,则不会显示透明效果;
①在onSurfaceCreated方法中加入代码:
//设置光线,,1.0f为全光线,a=50%
gl.glColor4f(1.0f,1.0f,1.0f,0.5f);
// 基于源象素alpha通道值的半透明混合函数
gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE);
其中,glColor4f以全亮度绘制此物体,并对其进行50%的alpha混合(半透明)。
当混合选项打开时,此物体将会产生50%的透明效果,
alpha通道的值为0.0意味着物体材质是完全透明的,
为1.0则意味着完全不透明。
②打开混合开关:
gl.glEnable(GL10.GL_BLEND); // 打开混合
二、实现:
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" /> </LinearLayout>
2.代码编辑:
【\src\com\yarin\android\Examples\Activity01.java】
package com.yarin.android.Examples_12_07; import android.app.Activity; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.KeyEvent; public class Activity01 extends Activity { GLRender render = new GLRender(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GLImage.load(this.getResources()); GLSurfaceView glView = new GLSurfaceView(this); glView.setRenderer(render); setContentView(glView); } } class GLImage { public static Bitmap mBitmap; public static void load(Resources resources) { mBitmap = BitmapFactory.decodeResource(resources, R.drawable.img); } }
【\src\com\yarin\android\Examples\GLRender.java】
package com.yarin.android.Examples_12_07; import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLUtils; import android.opengl.GLSurfaceView.Renderer; import android.view.KeyEvent; public class GLRender implements Renderer { boolean key = true; float xrot, yrot; float xspeed, yspeed; float z = -5.0f; int one = 0x10000; //光线参数 FloatBuffer lightAmbient = FloatBuffer.wrap(new float[]{0.5f,0.5f,0.5f,1.0f}); FloatBuffer lightDiffuse = FloatBuffer.wrap(new float[]{1.0f,1.0f,1.0f,1.0f}); FloatBuffer lightPosition = FloatBuffer.wrap(new float[]{0.0f,0.0f,2.0f,1.0f}); int filter = 1; int [] texture; IntBuffer vertices = IntBuffer.wrap(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, }); IntBuffer normals = IntBuffer.wrap(new int[]{ 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,0,one, 0,one,0, 0,one,0, 0,one,0, 0,one,0, 0,-one,0, 0,-one,0, 0,-one,0, 0,-one,0, one,0,0, one,0,0, one,0,0, one,0,0, -one,0,0, -one,0,0, -one,0,0, -one,0,0, }); IntBuffer texCoords = IntBuffer.wrap(new int[]{ one,0,0,0,0,one,one,one, 0,0,0,one,one,one,one,0, one,one,one,0,0,0,0,one, 0,one,one,one,one,0,0,0, 0,0,0,one,one,one,one,0, one,0,0,0,0,one,one,one, }); ByteBuffer indices = ByteBuffer.wrap(new byte[]{ 0,1,3,2, 4,5,7,6, 8,9,11,10, 12,13,15,14, 16,17,19,18, 20,21,23,22, }); @Override public void onDrawFrame(GL10 gl) { // 清除屏幕和深度缓存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); // 重置当前的模型观察矩阵 gl.glLoadIdentity(); gl.glEnable(GL10.GL_LIGHTING); //////////////// gl.glTranslatef(0.0f, 0.0f, z); //设置旋转 gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //设置纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[filter]); gl.glNormalPointer(GL10.GL_FIXED, 0, normals); gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices); gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords); gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //绘制四边形 gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_UNSIGNED_BYTE, indices); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); //修改旋转角度 xrot+=0.3f; yrot+=0.2f; //gl.glDisable(GL10.GL_BLEND); // 关闭混合 //gl.glEnable(GL10.GL_DEPTH_TEST); // 打开深度测试 ///* //混合开关 if (key) { gl.glEnable(GL10.GL_BLEND); // 打开混合 gl.glDisable(GL10.GL_DEPTH_TEST); // 关闭深度测试 } else { gl.glDisable(GL10.GL_BLEND); // 关闭混合 gl.glEnable(GL10.GL_DEPTH_TEST); // 打开深度测试 } //*/ } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { float ratio = (float) width / height; //设置OpenGL场景的大小 gl.glViewport(0, 0, 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.glDisable(GL10.GL_DITHER); // 告诉系统对透视进行修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); // 黑色背景 gl.glClearColor(0, 0, 0, 0); gl.glEnable(GL10.GL_CULL_FACE); // 启用阴影平滑 gl.glShadeModel(GL10.GL_SMOOTH); // 启用深度测试 gl.glEnable(GL10.GL_DEPTH_TEST); //设置光线,,1.0f为全光线,a=50% gl.glColor4f(1.0f,1.0f,1.0f,0.5f); // 基于源象素alpha通道值的半透明混合函数 gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE); //纹理相关 IntBuffer textureBuffer = IntBuffer.allocate(3); gl.glGenTextures(3, textureBuffer); texture = textureBuffer.array(); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST); // ( NEW ) gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); // ( NEW ) GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); // ( NEW ) gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR); // ( NEW ) GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[2]); gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); // ( NEW ) gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR); // ( NEW ) GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GLImage.mBitmap, 0); //深度测试相关 gl.glClearDepthf(1.0f); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); gl.glEnable(GL10.GL_TEXTURE_2D); //设置环境光 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient); //设置漫射光 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse); //设置光源位置 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition); //开启一号光源 gl.glEnable(GL10.GL_LIGHT1); //开启混合 gl.glEnable(GL10.GL_BLEND); key=true; } }
三、效果:
四、思考:
将四方体的每个面贴不同的图片,实现效果如下:
本文博客源地址:http://blog.csdn.net/ypist