转载请注明出处:【huachao1001的专栏:http://blog.csdn.net/huachao1001】

在上一篇文章【 Android OpenGL显示随意3D模型文件 】中。我们学习了怎样读取并显示STL格式的3D文件,可是,最后。看到的并没有加入光照效果。导致尽管模型在旋转,可是我们看到的画面却像一个平面。今天我们開始学习怎样给模型加入灯照效果,以及怎样为模型加入材料属性,使得终于看到的旋转模型真正为3D效果。首先。看看终于效果,例如以下图所示:

1 光照效果

由于我们所做的立体效果是依据真实世界原理来计算的,所以非常有必要去了解在现实世界中。我们所示一个物体有哪些光。

1.1 真实世界中的光照

我们知道,在黑暗中,当我们将手电筒对准某个物体时。我们所示该物体的“亮度”有3种:

  • 物体表面发生镜面反射部分(Specular),通常是白色。
  • 物体表面发生漫反射部分(Diffuse),通常是物体表面的颜色。
  • 物体表面没有照耀到光的部分。即通过环境光(Ambient)照耀,在黑暗中环境光是黑色。

例如以下图所示(图片出自www.guidebee.info):

从上图中也能够看出,光源的位置也会影响到我们所示终于画面。

显然,我们仅仅需控制好光源位置、镜面反射颜色、漫反射颜色、环境光颜色这四个參数,就能够做到了。

1.2 Android OpenGL相关API

1.2.1 光源 GL10.GL_LIGHT0

0号光源,该光源的默认颜色为白色,即RGBA(1.0,1.0,1.0,1.0)。漫反射和镜面反射也为白色。相似的,还有其它光源如GL10.GL_LIGHT1,系统提供了0~78种光源。其它的光源默觉得黑色,即RGBA(0.0,0.0,0.0,1.0).

开启光源也非常easy:

//启用光照功能
gl.glEnable(GL10.GL_LIGHTING);
//开启0号灯
gl.glEnable(GL10.GL_LIGHT0);

1.2.2 设置各种反射光颜色

一旦开启了光照功能,就能够通过glLightfv函数来指定各种反射光的颜色了,glLightfv函数例如以下:

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能够设置从07共八个光源。
  • 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类型),数组里面含有4个值分别表示R,G,B,A。

指定光源的位置的參数为GL_POSITION,位置的值为(x,y,z,w),假设是平行光则将w 设为0,此时。(x,y,z)为平行光的方向:

1.3 代码实现

在上一篇的基础上,直接改动GLRenderer.java文件。加入一个openLight函数:


public void openLight(GL10 gl) {gl.glEnable(GL10.GL_LIGHTING);gl.glEnable(GL10.GL_LIGHT0);gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, Util.floatToBuffer(ambient));gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, Util.floatToBuffer(diffuse));gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, Util.floatToBuffer(specular));gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, Util.floatToBuffer(lightPosition));}

另外,分别加入我们设定的各种反射光的颜色:

float[] ambient = {0.9f, 0.9f, 0.9f, 1.0f,};
float[] diffuse = {0.5f, 0.5f, 0.5f, 1.0f,};
float[] specular = {1.0f, 1.0f, 1.0f, 1.0f,};
float[] lightPosition = {0.5f, 0.5f, 0.5f, 0.0f,};

最后,在onSurfaceCreated函数里面调用一下openLight(gl);函数就可以。终于效果例如以下:

2 材料属性

前面我们提到了能够为模型设置不同的材料属性,本节中。我们一起学习怎样为模型设定不同的材料属性。

我们知道,相同是一束光,照在不同颜色材料的物体上面。我们所示是不同的,反射出来的不仅仅颜色不同,光泽也是不同的。

换句话说。不同的材质对终于的渲染效果影响非常大!

材料的属性设置和光源的设置有些相似,用到的函数

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:指定反射的颜色。

跟设置光照相似,设置材料属性首先须要定义各种反射光的颜色:

float[] materialAmb = {0.4f, 0.4f, 1.0f, 1.0f};
float[] materialDiff = {0.0f, 0.0f, 1.0f, 1.0f};//漫反射设置蓝色
float[] materialSpec = {1.0f, 0.5f, 0.0f, 1.0f};

然后就是将这些颜色通过glMaterialfv函数设置进去:

public void enableMaterial(GL10 gl) {//材料对环境光的反射情况gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, Util.floatToBuffer(materialAmb));//散射光的反射情况gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, Util.floatToBuffer(materialDiff));//镜面光的反射情况gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, Util.floatToBuffer(materialSpec));}

当然了,最后也别忘记了在onSurfaceCreated函数中调用 enableMaterial(gl);,最后看看效果:

3 完整的GLRenderer类

最后项目代码就不上传了,直接參考上一篇的文章中的源代码就可以,本位值改动了GLRenderer类,把该类的完整源代码贴上:

package com.hc.opengl;import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;import java.io.IOException;import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;/*** Package com.hc.opengl* Created by HuaChao on 2016/8/9.*/
public class GLRenderer implements GLSurfaceView.Renderer {private Model model;private Point mCenterPoint;private Point eye = new Point(0, 0, -3);private Point up = new Point(0, 1, 0);private Point center = new Point(0, 0, 0);private float mScalef = 1;private float mDegree = 0;public GLRenderer(Context context) {try {model = new STLReader().parserBinStlInAssets(context, "huba.stl");} catch (IOException e) {e.printStackTrace();}}public void rotate(float degree) {mDegree = degree;}@Overridepublic void onDrawFrame(GL10 gl) {// 清除屏幕和深度缓存gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);gl.glLoadIdentity();// 重置当前的模型观察矩阵//眼睛对着原点看GLU.gluLookAt(gl, eye.x, eye.y, eye.z, center.x,center.y, center.z, up.x, up.y, up.z);//为了能有立体感觉。通过改变mDegree值,让模型不断旋转gl.glRotatef(mDegree, 0, 1, 0);//将模型放缩到View刚好装下gl.glScalef(mScalef, mScalef, mScalef);//把模型移动到原点gl.glTranslatef(-mCenterPoint.x, -mCenterPoint.y,-mCenterPoint.z);//===================begin==============================////同意给每一个顶点设置法向量gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);// 同意设置顶点gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 同意设置颜色//设置法向量数据源gl.glNormalPointer(GL10.GL_FLOAT, 0, model.getVnormBuffer());// 设置三角形顶点数据源gl.glVertexPointer(3, GL10.GL_FLOAT, 0, model.getVertBuffer());// 绘制三角形gl.glDrawArrays(GL10.GL_TRIANGLES, 0, model.getFacetCount() * 3);// 取消顶点设置gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);//取消法向量设置gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);//=====================end============================//}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 设置OpenGL场景的大小,(0,0)表示窗体内部视口的左下角,(width, height)指定了视口的大小gl.glViewport(0, 0, width, height);gl.glMatrixMode(GL10.GL_PROJECTION); // 设置投影矩阵gl.glLoadIdentity(); // 设置矩阵为单位矩阵。相当于重置矩阵GLU.gluPerspective(gl, 45.0f, ((float) width) / height, 1f, 100f);// 设置透视范围//下面两句声明,以后全部的变换都是针对模型(即我们绘制的图形)gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glLoadIdentity();}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {gl.glEnable(GL10.GL_DEPTH_TEST); // 启用深度缓存gl.glClearColor(0f, 0f, 0f, 0f);// 设置深度缓存值gl.glDepthFunc(GL10.GL_LEQUAL); // 设置深度缓存比較函数gl.glShadeModel(GL10.GL_SMOOTH);// 设置阴影模式GL_SMOOTH//开启光openLight(gl);enableMaterial(gl);float r = model.getR();//r是半径。不是直径,因此用0.5/r能够算出放缩比例mScalef = 0.5f / r;mCenterPoint = model.getCentrePoint();}float[] ambient = {0.9f, 0.9f, 0.9f, 1.0f};float[] diffuse = {0.5f, 0.5f, 0.5f, 1.0f};float[] specular = {1.0f, 1.0f, 1.0f, 1.0f};float[] lightPosition = {0.5f, 0.5f, 0.5f, 0.0f};public void openLight(GL10 gl) {gl.glEnable(GL10.GL_LIGHTING);gl.glEnable(GL10.GL_LIGHT0);gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, Util.floatToBuffer(ambient));gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, Util.floatToBuffer(diffuse));gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, Util.floatToBuffer(specular));gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, Util.floatToBuffer(lightPosition));}float[] materialAmb = {0.4f, 0.4f, 1.0f, 1.0f,};float[] materialDiff = {0.0f, 0.0f, 1.0f, 1.0f,};float[] materialSpec = {1.0f, 0.5f, 0.0f, 1.0f,};public void enableMaterial(GL10 gl) {//材料对环境光的反射情况gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, Util.floatToBuffer(materialAmb));//散射光的反射情况gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, Util.floatToBuffer(materialDiff));//镜面光的反射情况gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, Util.floatToBuffer(materialSpec));}
}

最后感谢大家的关注,欢迎关注huachao1001的博客,http://blog.csdn.net/huachao10019

Android OpenGL加入光照和材料属性相关推荐

  1. Android OpenGL添加光照和材料属性

    转载请注明出处:[huachao1001的专栏:http://blog.csdn.net/huachao1001] 在上一篇文章[ Android OpenGL显示任意3D模型文件 ]中,我们学习了如 ...

  2. openGL的光照与材料(一)

    真实感图形绘制是计算机图形学的一个重要组成部分,它综合利用数学.物理学.计算机科学和其它科学知识在计算机图形设备上生成象彩色照片那样的具有真实感的图形.一般说来,用计算机在图形设备上生成真实感图形必须 ...

  3. OpenGL超级宝典笔记——光照参数与材料属性

    2019独角兽企业重金招聘Python工程师标准>>> <h3>添加光照</h3> <p>glEnable(GL_LIGHTING);</p ...

  4. Android OpenGL射线拾取手势旋转(二)

    上回分解-_-!,Android OpenGL射线拾取&手势旋转(一). 3)Renderer:RayPickRenderer.java OpenGL渲染器,比较多的东西都在这里面了. pub ...

  5. OpenGL阴影添加学习材料及总结

    学习材料 PBR 基于物理的实时渲染 采用了更符合物理学规律的方式来模拟光线,通过模拟虚拟物体表面的粗糙程度,来计算出射该物体的光线呈现一个怎样的方式. PBR材料的三个主要参数称为:反照率.粗糙度. ...

  6. Android OpenGL ES视频渲染(一)GLSurfaceView

    相关文章:Android OpenGL ES视频渲染(二)EGL+OpenGL Android中视频渲染有几种方式,之前的文章使用的是nativewindow(包括softwareRender).今天 ...

  7. Android openGl开发详解(一)——绘制简单图形

    1. What? openGl是什么?openGl ES又是什么? 2. How? Android中的openGL 如何使用? 3. GlSurfaceView是什么? GLSurfaceView的作 ...

  8. Android OpenGl Es 学习(二):定义顶点和着色器

    概述 这是一个新的系列,学习OpengGl Es,其实是<OpenGl Es 应用开发实践指南 Android卷>的学习笔记,感兴趣的可以直接看这本书,当然这个会记录自己的理解,以下只作为 ...

  9. SurfaceView简单理解,Android混淆,Android openGl开发详解简单图形的绘制,

    SurfaceView允许你在非ui线程中去绘制. SurfaceView的帧率可以操作60FPS 在要求实时性比较高的游戏开发中,显然,view的ondraw是满足不了你的,这时候只能是用Surfa ...

  10. Android OpenGL ES 学习(十二) - MediaCodec + OpenGL 解析H264视频+滤镜

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学 ...

最新文章

  1. HTML的标签描述6
  2. Android ListView 的优化
  3. 【02】Kubernets:使用 kubeadm 部署 K8S 集群
  4. Mr.J--初识Ajax
  5. 使用cmd-命令运行Java项目
  6. 擷取 GridView 資料列的欄位值集合
  7. 饿了么风神系统手机版_数字技术带来平等工作机会 饿了么智能调度系统助力残障骑手少跑路多接单...
  8. 怎样解决DEDE织梦友情链接字数限制与链接个数限制
  9. 解决office 2016公式编辑器空白,无法正常显示公式的问题
  10. 将图片转化成RGB格式
  11. 博士毕业要发多少篇文章? 72 所高校大比较,发文最多的是……
  12. jmeter接口测试详细教程
  13. keepalived 健康检查机制说明
  14. 局域网打印机共享怎么设置_XP系统设置局域网共享打印机的操作步骤
  15. html买手机的流程图,支付流程图.html
  16. Unity ASE点光源不显示的问题
  17. SciPyCon 2018 sklearn 教程(下)
  18. RollPitchYaw傻傻分不清
  19. c++ primer plus第六版第六章编程练习
  20. 「hdu6608」Fansblog【Miller_Rabin+威尔逊定理】

热门文章

  1. golang 大数据平台_一文读懂数据平台、大数据平台、数据中台
  2. java最终类不能派生子类_最终类不能派生子类,最终方法不能被重写 (2.0分)_学小易找答案...
  3. 2021-09-02最大矩形
  4. 2021-08-31为什么随机森林能降低方差
  5. 传统梯度下降法面临的挑战
  6. Android工程项目打包成SDK(jar或aar格式)
  7. 公式推导 11-20
  8. 局域网计算机无法配置网关,在内网中,为什么不设置“默认网关”计算机也能互相通讯?...
  9. php foreach 不等于_PHP性能优化小技巧
  10. python 二维矩阵画三维图_python 二维矩阵转三维矩阵示例