我是靠谱客的博主 畅快小霸王,最近开发中收集的这篇文章主要介绍Android OpenGL ES学习笔记之材质概念和添加光照,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、光照概念

观察一个真实的3D物体,在不同的部位必然有不同的光照效果,有的地方暗一点,有的地方亮一点。而这种视觉差异是由光源和材质(物体的材料)共同决定的。光源强度由红、绿、蓝三色光强度共同决定,最终的光照效果由4部分组成:

 - Emitted(光源)
- diffuse(漫反射光)
- specular(镜面反射光)
- ambient(环境光)

这里附上一张网上的图:

这里写图片描述


Emitted(光源)

物体本身所发射出的光,有的物体不发射光,那就没有这个属性


diffuse(漫反射光)

漫反射和镜面反射大家应该都知道,初中物理有讲过。
漫反射,是投射在粗糙表面上的光向各个方向反射的现象。当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射,所以入射线虽然互相平行,由于各点的法线方向不一致,造成反射光线向不同的方向无规则地反射,这种反射称之为“漫反射”或“漫射”。

如下图:

这里写图片描述


specular(镜面反射光)

镜面反射是指若反射面比较光滑,当平行入射的光线射到这个反射面时,仍会平行地向一个方向反射出来,这种反射就属于镜面反射


ambient(环境光)

在环境中进行了多次散射的光,而最终无法分辨其方向的光。

二、材质概念

物体的材质属性通过反射不同方向的环境光,漫反射光,镜面光的RGB颜色来表示的。分为四种:

 - 泛射材质
- 漫反射材质
- 镜面反射材质
- 发射材质

三、光照模型

添加光照效果也就是使用OpenGL的光照模型需要以下步骤

  1. 打开光源
  2. 设置光源的种类、位置和方向(对于平行光源)
  3. 设置顶点的法向量
  4. 设置材质

1、打开光源

首先需要打开光源的总开关


//打开光源总开关
gl.glEnable(GL10.GL_LIGHTING);

在OpenGL ES中,仅仅支持有限数量的光源。使用GL_LIGHT0表示第0号光源,GL_LIGHT1表示第1号光源,依次类推,OpenGL至少会支持8个光源 。GL_LIGHT0到GL_LIGHT7。

打开0号光源


//打开0号光源
gl.glEnable(GL10.GL_LIGHT0);

2、设置光源的种类、位置和方向(对于平行光源)

设置光源的方法如下

 - glLightfv(int light, int pname, FloatBuffer params)
- glLightfv(int light, int pname, float[] params, int offset)

各个参数含义如下

 - light—————— 光源的序号
- pname—————— 光源属性名称
- params—————— 光源属性的值(float 数组或是Buffer类型)
- offset——————
偏移量

params有以下几种

 - GL_SPOT_EXPONENT————表示聚光的程度,为零时表示光照范围内向各方向发射的光线强度相同,为正数时表示光照向中央集中,正对发射方向的位置受到更多光照,其它位置受到较少光照。数值越大,聚光效果就越明显
- GL_SPOT_CUTOFF————表示一个角度,它是光源发射光线所覆盖角度的一半,其取值范围在0到90之间,也可以取180这个特殊值。取值为180时表示光源发射光线覆盖360度,即不使用聚光灯,向全周围发射
- GL_CONSTANT_ATTENUATION————表示光线按常量衰减
- GL_LINEAR_ATTENUATION————表示光线按距离线性衰减
- GL_QUADRATIC_ATTENUATION————表示光线按距离以二次函数衰减
- GL_AMBIENT————表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度
- GL_DIFFUSE————表示光线照射到该材质上,经过漫反射后形成的光线强度
- GL_SPECULAR————表示光线照射到该材质上,经过镜面反射后形成的光线强度
- GL_SPOT_DIRECTION————表示一个向量,即光源发射的方向。默认方向是(0.0,0.0,-1.0)
- GL_POSITION————表示光源所在的位置,由四个值(X, Y, Z, W)表示,W为0表示平行光源,表示该光源位于无限远处,类似太阳,W不为0表示位置性光源,(X/W, Y/W, Z/W)表示了光源的位置,可以设置各种衰减因子

上面说的与聚光强度、角度、衰减等有关的属性只适用于位置光源


3、设置顶点的法向量

设置法向量来确定图元的明暗程度,不过我的例子并没有用到。有两个方法可以为平面设置法线。

 - public void glNormal3f(float nx,float ny,float nz) ————为后续所有平面设置同样的方向,直到重新设置新的法线为止
- public void glNormalPointer(int type,int stride, Buffer pointer)————为某个顶点设置法线

4、设置材质

设置材质的方法如下

 - 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 ———— 表示物体的前、后面,有GL_FRONT(正面),GL_BACK(反面),GL_FRONT_AND_BACK(正反两面)
- pname ———— 材质属性类型
- param ———— 材质属性类型的对应的值(float 数组或者Buffer 类型)
- offset ———— 偏移量

其中pname 有以下几种

 - GL_AMBIENT————表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度
- GL_DIFFUSE ————表示光线照射到该材质上,经过漫反射后形成的光线强度
- GL_SPECULAR————表示光线照射到该材质上,经过镜面反射后形成的光线强度
- GL_SHININESS————“镜面指数”,取值范围是0到128。该值越小,表示材质越粗糙,点光源发射的光线照射到上面,也可以产生较大的亮点。该值越大,表示材质越类似于镜面,光源照射到上面后,产生较小的亮点
- GL_EMISSION————该属性由四个值组成,表示一种颜色。OpenGL认为材质本身就微微的向外发射光线,以至于眼睛感觉到它有这样的颜色,但这光线又比较微弱,以至于不会影响到其它物体的颜色
- GL_COLOR_INDEXES———— 颜色索引

四、例子

以上一篇文章Android OpenGL ES学习笔记之绘制一个正方体的代码为基础,添加光照效果。

首先是新建关于光源属性的浮点数组


//环境光强度
float[] amb_light = {1f, 1f, 1f, 1f };
//漫反射光强度
float[] diff_light = { 1f, 1f, 1f, 1f };
//镜面反射光强度
float[] spec_light = {1f, 1f, 1f, 1f };
//光源位置
float[] pos_light = {0f, 0.0f, 1f, 0.4f};
//光源方向
float[] spot_dir = { 0.0f, 0.0f,
-1f, };

我设置了白色光,光源位置为{0f, 0.0f, 1f, 0.4f},参数w=0.4f,前面说了w不为0表示位置性光源,光源的位置为(X/W, Y/W, Z/W),即(0f,0f,2.5f)

设置光源方向为{ 0.0f, 0.0f, -1f, },沿着Z轴负方向

然后将它们转化为Buff类型


//获取浮点型环境光数据
amb_light_buffer= Utils.getFloatBuffer(amb_light);
//获取浮点型漫反射光数据
diff_light_buffer= Utils.getFloatBuffer(diff_light);
//获取浮点型镜面反射光数据
spec_light_buffer= Utils.getFloatBuffer(spec_light);
//获取浮点型光源位置数据
pos_light_buffer= Utils.getFloatBuffer(pos_light);
//获取浮点型光源方向数据
spot_dir_buffer= Utils.getFloatBuffer(spot_dir);

然后在onDrawFrame加上


//打开光源总开关
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);

先打开光源总开关,再打开0号光源,然后设置光源位置,方向,各种类强度,聚光强度,聚光角度。
聚光强度取值范围为0~128f。

绘制出的效果如下:

这里写图片描述

可以加上材质

我设置了反射绿光的强度为0.3f,红、蓝为0f。


//环境光材质
float amb_mat[]
= { 0f,
0.3f, 0f, 1f };
//漫反射光材质
float diff_mat[]
={ 0f,
0.3f, 0f, 1f };
//镜面反射光材质
float spec_mat[] = { 0f,
0.3f, 0f, 1f };
//本身颜色
float emi_mat[] = { 0.0f, 0f, 0.0f, 1.0f };
//镜面指数 
float shini_mat
=
0f; 

然后转化为Buffer


//获取浮点型环境光材质数据
amb_mat_buffer= Utils.getFloatBuffer(amb_mat);
//获取浮点型漫反射光材质数据
diff_mat_buffer= Utils.getFloatBuffer(diff_mat);
//获取浮点型镜面反射光材质数据
spec_mat_buffer= Utils.getFloatBuffer(spec_mat);
//获取浮点型本身颜色数据
emi_mat_buffer= Utils.getFloatBuffer(emi_mat);

然后设置材质各种类强度、镜面指数。


//设置材质种类
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);

效果如下图:

这里写图片描述

最后附上Demo:打开
密码:pw80

最后

以上就是畅快小霸王为你收集整理的Android OpenGL ES学习笔记之材质概念和添加光照的全部内容,希望文章能够帮你解决Android OpenGL ES学习笔记之材质概念和添加光照所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部