Android OpenGL ES 灯光

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

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, intpname, float param);
gl.glLightfv(int light, intpname, float[] params, int offset);
gl.glLightfv(int light, intpname, FloatBuffer params);
gl.glLightx(int light, intpname, int param);
gl.glLightxv(int light, intpname, int[] params, int offset);
gl.glLightxv(int light, intpname, 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,
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">5.0f,5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,-5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">5.0f,5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,-5.0f, -5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,5.0f, 5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,-5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">5.0f,5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, -5.0f, -5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f,</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">-5.0f,};</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

然后在 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);
<wbr><span style="font-size:18px"></span><wbr></wbr></wbr>
gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_AMBIENT, new float[] { 1.0f, 0.0f,
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">0.0f,1.0f }, 0);</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_DIFFUSE, new float[] { 1.0f, 1.0f,
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">1.0f,1.0f }, 0);</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_SPECULAR, new float[] { 0.0f, 0.0f,
<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">1.0f,1.0f }, 0);</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

灯光的位置我们在绘制时动态设置,让它有点点旋转效果。在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 OpenGL ES 灯光

相关推荐