Chinaunix首页 | 论坛 | 博客
  • 博客访问: 550963
  • 博文数量: 179
  • 博客积分: 3845
  • 博客等级: 中校
  • 技术积分: 2003
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-16 21:25
文章分类
文章存档

2012年(74)

2011年(105)

分类: 嵌入式

2012-01-17 12:37:26

最迷人的要算灯光了,所以上帝说的第一句话就是 — “要有光”。

OpenGL ES 1.1支持最多同时启用八个灯光,可以是平行光、点光源、聚光灯。

使用灯光前,先要启用灯光总开光,然后再启用 0-7 八个光源中的某(几)盏,通过 glEnable 函数可以打开这两种开关

1
2
gl.glEnable(GL10.GL_LIGHTING); // 启用灯光总开关
gl.glEnable(GL10.GL_LIGHTIn); // 启用第n盏灯 ( n = 0...7 )

然后通过 glLight 系统函数设置灯光属性即可,看下这几个函数

1
2
3
4
5
6
gl.glLightf(int light, int pname, float param);
gl.glLightfv(int light, int pname, float[] params, int offset);
gl.glLightfv(int light, int pname, FloatBuffer params);
gl.glLightx(int light, int pname, int param);
gl.glLightxv(int light, int pname, int[] params, int offset);
gl.glLightxv(int light, int pname, IntBuffer params);

这几个函数大同小异,其中x、f 表示设置的值的类型是整数还是浮点。

参数light 表示要设置哪个灯光,有效值为常量 GL10.GL_LIGHTn 。

参数pname 表示要设置的属性,包括

  • GL_POSITION:灯光的位置,值为四元组 (x,y,z,w),光w为0时表示平行光,xyz即变成了光源方向;光 w 不为0时,表示点光源或聚光灯的位置一般此时 w取值为1.0f。
  • GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR:灯光的颜色,分别代表环境光、漫射光、反射光。
  • GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION:衰减,后两个使灯光的强度随距离变化,三者共同作用的最终衰减系数为:1 / (kconstant + klinear * d + kquadratic * d2),其中d表示到光源的距离。
  • GL_SPOT_EXPONENT:设置聚光灯光圈中心到边缘的衰减程度。
  • GL_SPOT_CUTOFF:设置聚光灯光锥的扩散角度。
  • GL_SPOT_DIRECTION:设置聚光灯的照射方向。

参数param表示要设置的属性的整数值或浮点值。

参数params表示要设置的属性的序列值。

参数offset限定数组类型的params参数中要使用的部分的起始位置。

设置完灯光,还要在我们的模型上加上法线数据,法线即多边型平面反射光线时反射角的参考,入射角和反映角与法线的夹角相等,且入射光线、反射光线、法线在同一平面。

回到 HelloWorld 工程,加入点灯光进去。

首先我们要定义法线数据,

1
2
3
4
5
6
7
8
9
10
11
12
private float[] data_normals = { -5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,
        5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f,
        -5.0f, -5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f,
        5.0f, 5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,
        -5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f,
        -5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,
        -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,
        -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,
        -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,
        5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, -5.0f, -5.0f,
        -5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f,
        -5.0f, };

然后在 createBuffers 方法中将法线装入 FloatBuffer 中

1
2
3
4
normals = ByteBuffer.allocateDirect(data_normals.length * 4);
normals.order(ByteOrder.nativeOrder());
normals.asFloatBuffer().put(data_normals);
normals.position(0);

在 onSurfaceCreated 方法中启用灯光总开关及0号灯光并设置灯光颜色

1
2
3
4
5
6
7
8
9
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
  
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, new float[] { 1.0f, 0.0f,
        0.0f, 1.0f }, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, new float[] { 1.0f, 1.0f,
        1.0f, 1.0f }, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, new float[] { 0.0f, 0.0f,
        1.0f, 1.0f }, 0);

灯光的位置我们在绘制时动态设置,让它有点点旋转效果。在onDrawFrame中

1
2
3
4
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glRotatef(-angley, 0, 1, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, new float[]{50, 50, 50, 0}, 0);

绘制模型时需要启用法向量并设置法向量数据

1
2
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normals);

好了, 看下效果

最终代码  android-opengles-3.zip   

阅读(3628) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~