之前讲到了opengl es基本图形的绘制,变换,下面我们来看看光照和材质的应用。
光照模型:
为图形添加光照,就能使图形看上去有立体效果。在 OpenGL 光照模型中光源和光照效果可以细分为红,绿,蓝三个部分,光源由红,绿,蓝强度来定义,而物体表面材料由其反射红,绿,蓝的程度和方向来定义。
OpenGL 光照模型中最终的光照效果可以分为四个组成部分:Emitted(光源), ambient(环境光),diffuse(漫射光)和specular(镜面反射光),最终结果由这四种光叠加而成。
Emitted : 发光物体或光源
ambient: 指光线经过多次反射后已经无法得知其方向,该光源如果射到某个平面,其反射方向为所有方向。Ambient 不依赖于光源的方向。
diffuse:只依赖于光源的方向和法线的方向。
specular : 一般指物体被光源直射的高亮区域。specular 依赖于光源的方向,法线的方向和视角的方向。
opengl es设置光照效果基本步骤:
1、设置光源
2、设置法线
3、设置物体材料熟悉
设置光源:
OpenGL ES 中可以最多同时使用八个光源,分别使用0到7表示。
OpenGL ES光源可以分为
平行光源, 代表由位于无限远处均匀发光体,太阳可以近似控制平行光源。
点光源,如灯泡就是一个点光源,发出的光可以指向360度,可以为点光源设置光衰减属性或者让点光源只能射向某个方向。
打开光源: 打开光源总开关:
gl.glEnable(GL10.GL_LIGHTING);
再打开某个光源:
gl.glEnable(GL10.GL_LIGHTI0);//这里打开0号光源
设置光源属性:
public void glLightfv(int light,int pname, FloatBuffer params)
public void glLightfv(int light,int pname,float[] params,int offset)
public void glLightf(int light,int pname,float param)
light 指光源的序号,OpenGL ES可以设置从0到7共八个光源。
pname: 光源参数名称,可以有如下:GL_SPOT_EXPONENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION, GL_QUADRATIC_ATTENUATION, GL_AMBIENT, GL_DIFFUSE,GL_SPECULAR, GL_SPOT_DIRECTION, GL_POSITION
params 参数的值(数组或是Buffer类型)。
其中为光源设置颜色的参数类型为 GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,可以分别指定R,G,B,A 的值。
指定光源的位置的参数为 GL_POSITION,值为(x,y,z,w):
平行光将 w 设为0.0,(x,y,z)为平行光的方向,
对于点光源,将 w 设成非0值,通常设为1.0. (x,y,z)为点光源的坐标位置
将点光源设置成聚光灯,需要同时设置 GL_SPOT_DIRECTION,GL_SPOT_CUTOFF 等参数,GL_POSITION的设置和点光源类似:将 w 设成非0值,通常设为1.0. (x,y,z)为点光源的坐标位置。而对于GL_SPOT_DIRECTION 参数,设置聚光的方向(x,y,z)
GL_SPOT_CUTOFF 参数设置聚光等发散角度(0到90度)
GL_SPOT_EXPONENT 给出了聚光灯光源汇聚光的程度,值越大,则聚光区域越小(聚光能力更强)
设置法线:设置了法线,光源才能在所会物体上出现光照效果
glNormal3f(float nx,float ny,float nz) 为后续所有平面设置同样的方向,直到重新设置新的法线为止
glNormalPointer(int type,int stride, Buffer pointer) 为某个顶点设置法线
设置物体材质:
设置物体表面材料(Material)的反光属性(颜色和材质)的方法如下:
public void glMaterialf(int face,int pname,float param)
public void glMaterialfv(int face,int pname,float[] params,int offset)
public void glMaterialfv(int face,int pname,FloatBuffer params)
face : 在OpenGL ES中只能使用GL_FRONT_AND_BACK,表示修改物体的前面和后面的材质光线属性。
pname: 参数类型,可以有GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION, GL_SHININESS。这些参数用在光照方程。
param:参数的值。
其中 GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR ,GL_EMISSION 为颜色 RGBA 值,GL_SHININESS 值可以从0到128,值越大,光的散射越小:
下面看设置光源和材质的例子,具体代码都有注释:
public void drawLight(GL10 gl){ //环境光强度 float[] amb_light = {1f,0f, 0f, 1f }; //漫反射光强度 float[] diff_light = { 1f, 0f, 0f, 1f }; //镜面反射光强度 float[] spec_light = {1f, 0f, 0f, 1f }; //光源位置 float[] pos_light = {1f, 0f, 0f, 0.2f}; //光源方向 float[] spot_dir = { -1f, 0f, 0f, }; //获取浮点型环境光材质数据 amb_mat_buffer= BufferUtils.getFloatBuffer(amb_mat); //获取浮点型漫反射光材质数据 diff_mat_buffer= BufferUtils.getFloatBuffer(diff_mat); //获取浮点型镜面反射光材质数据 spec_mat_buffer= BufferUtils.getFloatBuffer(spec_mat); //获取浮点型本身颜色数据 emi_mat_buffer= BufferUtils.getFloatBuffer(emi_mat); //获取浮点型环境光数据 FloatBuffer amb_light_buffer= BufferUtils.getFloatBuffer(amb_light); //获取浮点型漫反射光数据 FloatBuffer diff_light_buffer= BufferUtils.getFloatBuffer(diff_light); //获取浮点型镜面反射光数据 FloatBuffer spec_light_buffer= BufferUtils.getFloatBuffer(spec_light); //获取浮点型光源位置数据 FloatBuffer pos_light_buffer= BufferUtils.getFloatBuffer(pos_light); //获取浮点型光源方向数据 FloatBuffer spot_dir_buffer= BufferUtils.getFloatBuffer(spot_dir); angle++; angle = angle%360; angle = 60; ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length*2); ibb.order(ByteOrder.nativeOrder()); ShortBuffer mIndixBuffer = ibb.asShortBuffer(); mIndixBuffer.put(indices); mIndixBuffer.position(0); ByteBuffer cbb = ByteBuffer.allocateDirect(cubeColors.length * 4); cbb.order(ByteOrder.nativeOrder()); colorBuffer = cbb.asFloatBuffer(); colorBuffer.put(cubeColors); colorBuffer.position(0); ByteBuffer vbb = ByteBuffer.allocateDirect(cubeVertices.length*4); vbb.order(ByteOrder.nativeOrder()); FloatBuffer vertex = vbb.asFloatBuffer(); vertex.put(cubeVertices); vertex.position(0); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 启用顶点座标数据 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); //启用法线设置 gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); //打开光源总开关 gl.glEnable(GL10.GL_LIGHTING); //打开0号光源 gl.glEnable(GL10.GL_LIGHT0); //设置光源位置 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, pos_light_buffer); //设置光源方向 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPOT_DIRECTION , spot_dir_buffer); //设置光源种类 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT , amb_light_buffer ); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE , diff_light_buffer ); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, spec_light_buffer); //设置聚光强度 gl.glLightf(GL10.GL_LIGHT0, GL10.GL_SPOT_EXPONENT, 64f); //设置聚光角度 gl.glLightf(GL10.GL_LIGHT0, GL10.GL_SPOT_CUTOFF, 45f); //设置材质种类 gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, amb_mat_buffer); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_DIFFUSE, diff_mat_buffer); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_SPECULAR, spec_mat_buffer); //设置镜面指数 gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, shini_mat); // 启用顶点颜色数据 gl.glEnableClientState(GL10.GL_COLOR_ARRAY); // 重置当前的模型视图矩阵 gl.glLoadIdentity(); // 沿着Y轴旋转 gl.glRotatef(angle, 0.2f, 1f, 0f); // 设置顶点的位置数据 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vbb); //设置顶点法线 gl.glNormalPointer(GL10.GL_FLOAT, 0, vbb); // 设置顶点的颜色数据 gl.glColorPointer(4, GL10.GL_FLOAT, 0, cbb); //绘制三角形,按照顶点数组画三角形 // gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP , 0, 24); //绘制三角形,按照mIndixBuffer中索引画三角形 gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, mIndixBuffer); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); }
demo下载地址:链接:http://pan.baidu.com/s/1c2oXQes 密码:7jz2