首页 > 程序开发 > 移动开发 > Android >

[Android开发学习17]Android OpenGL ES 光照与混合glDrawElements

2013-04-06

一、基础知识:1..光照介绍:①环境光:来自四面八方,所有场景中的对象都处于环境光的照射中。②漫射光:由特定的光源产生,并在场景中的对象表面产生反射。处于漫射光直接照射下的任何对象表面都变得很亮,而几乎未...

一、基础知识:


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】

[java]
<?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>

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

[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);
}
}

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】

[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;
}
}

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;
}
}


三、效果:

\

四、思考:

将四方体的每个面贴不同的图片,实现效果如下:

\

相关文章
最新文章
热点推荐