Android OpenGL ES学习笔记之材质概念和添加光照
来源:互联网 发布:热传导有限元软件 编辑:程序博客网 时间:2024/04/28 18:33
一、光照概念
观察一个真实的3D物体,在不同的部位必然有不同的光照效果,有的地方暗一点,有的地方亮一点。而这种视觉差异是由光源和材质(物体的材料)共同决定的。光源强度由红、绿、蓝三色光强度共同决定,最终的光照效果由4部分组成:
- Emitted(光源) - diffuse(漫反射光) - specular(镜面反射光) - ambient(环境光)
这里附上一张网上的图:
Emitted(光源)
物体本身所发射出的光,有的物体不发射光,那就没有这个属性
diffuse(漫反射光)
漫反射和镜面反射大家应该都知道,初中物理有讲过。
漫反射,是投射在粗糙表面上的光向各个方向反射的现象。当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射,所以入射线虽然互相平行,由于各点的法线方向不一致,造成反射光线向不同的方向无规则地反射,这种反射称之为“漫反射”或“漫射”。
如下图:
specular(镜面反射光)
镜面反射是指若反射面比较光滑,当平行入射的光线射到这个反射面时,仍会平行地向一个方向反射出来,这种反射就属于镜面反射
ambient(环境光)
在环境中进行了多次散射的光,而最终无法分辨其方向的光。
二、材质概念
物体的材质属性通过反射不同方向的环境光,漫反射光,镜面光的RGB颜色来表示的。分为四种:
- 泛射材质 - 漫反射材质 - 镜面反射材质 - 发射材质
三、光照模型
添加光照效果也就是使用OpenGL的光照模型需要以下步骤
- 打开光源
- 设置光源的种类、位置和方向(对于平行光源)
- 设置顶点的法向量
- 设置材质
1、打开光源
首先需要打开光源的总开关
- 1
- 2
在OpenGL ES中,仅仅支持有限数量的光源。使用GL_LIGHT0表示第0号光源,GL_LIGHT1表示第1号光源,依次类推,OpenGL至少会支持8个光源 。GL_LIGHT0到GL_LIGHT7。
打开0号光源
- 1
- 2
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学习笔记之绘制一个正方体的代码为基础,添加光照效果。
首先是新建关于光源属性的浮点数组
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
我设置了白色光,光源位置为{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类型
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
然后在onDrawFrame加上
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
先打开光源总开关,再打开0号光源,然后设置光源位置,方向,各种类强度,聚光强度,聚光角度。
聚光强度取值范围为0~128f。
绘制出的效果如下:
可以加上材质
我设置了反射绿光的强度为0.3f,红、蓝为0f。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
然后转化为Buffer
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
然后设置材质各种类强度、镜面指数。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
效果如下图:
最后附上Demo:打开
密码:pw80
- Android OpenGL ES学习笔记之材质概念和添加光照
- Android OpenGL ES学习笔记之材质概念和添加光照
- Android OpenGL ES材质及光照示例
- OpengL学习之光照和材质小窥
- Android OpenGL ES 开发教程(27):材质及光照示例
- Android OpenGL ES 开发教程(27):材质及光照示例
- OpenGL光照和材质
- OpenGL 光照和材质
- Android OpenGL ES学习笔记之添加颜色
- Android OpenGL ES学习笔记之添加纹理
- opengl es 光照效果,材质设置
- Android OpenGL ES学习笔记之实现OpenGL ES接口
- OpenGL材质和光照(转)
- Android OpenGL ES学习笔记之概要
- OpenGL学习: 光照系列2-材质和lighting maps使用
- Android OpenGL ES :材质渲染
- OpenGL ES 学习教程(八) 精密控制光照元素的 Material 材质系统
- OpenGL ES 简单光照学习
- 最高分是多少
- javascript取对象方法的封装
- Android Stdio--------编译错误之appcompat
- POJ 1011 Sticks
- adb server version (31) doesn't match this client
- Android OpenGL ES学习笔记之材质概念和添加光照
- BZOJ3343
- Android 将App的内容延伸到状态栏/导航栏
- android vsnc 工作原理
- ZZULIOJ (1913: 小火山的计算能力)
- mysql系列之1.mysql基础
- android listview 分割线问题
- 通过节点,获取数据
- PullToRefreshExpandableListView的用法