我的CSDN博客同步发布:Android OpenGL入门
转载请注明出处:【huachao1001的简书:http://www.jianshu.com/users/0a7e42698e4b/latest_articles】
如今VR
这么火,感觉有必要先把OpenGL
学好,为以后转VR
奠定一些基础。一年前,接触过Android
的OpenGL
,当时是实现了在Android
上显示标准的3D
文件(STL
格式)。现在打算整理一下OpenGL
相关知识,后续会有相关的系列文章。本文为后面文章铺垫,让大家对OpenGL
代码编写有个总体上的认识。
1 检测设备是否支持OpenGL
Android
中,有个专门用于显示OpenGL
的3D
图像View
:GLSurfaceView
。GLSurfaceView
会处理OpenGL
初始化过程中比较基本的操作,如配置显示设备,以及在后台线程中渲染。说的太正式了哈,其实不用太在乎它,就把它当当成是一个SurfaceView
就好,因为其实它的用法跟SurfaceView
很像(然而,它就是继承自SurfaceView
~)。
接下来开始创建GLSurfaceView
。在使用OpenGL
时,我们首先得判断当前设备是否支持OpenGL
(其实大部分手机都是支持的啦~),由于各种设备都可能支持Android
系统,其实还是有必要判断一下。因为我们现在基本上用到的是OpenGL ES 2.0
,我们要验证的是检查系统是否实际支持2.0版本。
final ActivityManager activityManager=(ActivityManager)getSystemService(ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo=activityManager.getDeviceConfigurationInfo();
boolean supportsEs2=configurationInfo.reqGlEsVersion>=0x2000;
由于这段代码不能很好的在模拟器上工作(GPU
模拟部分有缺陷),得要稍微修改一下,使之能在模拟器上正常工作
boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;
boolean isEmulator = Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
&& (Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86"));
supportsEs2 = supportsEs2 || isEmulator;
我们看看怎么使用GLSurfaceView
吧~
private boolean supportsEs2;
private GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkSupported();
if (supportsEs2) {
glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setRenderer(new GLRenderer());
setContentView(glSurfaceView);
} else {
setContentView(R.layout.activity_main);
Toast.makeText(this, "当前设备不支持OpenGL ES 2.0!", Toast.LENGTH_SHORT).show();
}
}
private void checkSupported() {
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;
boolean isEmulator = Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
&& (Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86"));
supportsEs2 = supportsEs2 || isEmulator;
}
什么?这么简单,难道这样就能显示3D
模型?可是并没有看到3D
模型图形在哪里啊!别着急,看看第9
行代码,有个setRenderer()
函数,里面需要传入一个Renderer
对象,那么什么是Renderer
呢?前面提到GLSurfaceView
是用于显示3D模型的视图,如果说GLSurfaceView
是画布,那么,光有一块白纸是没用的,得要在白纸上画图,通过什么画图呢?就是接下来要说的Renderer
。Renderer
是一个接口,它主要包含3个抽象函数:onSurfaceCreated
、onDrawFrame
、onSurfaceChanged
;从名字就可以看出,分别是在SurfaceView
创建时调用、在绘制图形时调用以及在视图大小发生改变时调用。看看我们的GLRenderer
对象是怎么定义的:
/**
* Package com.hc.opengl
* Created by HuaChao on 2016/7/27.
*/
public class GLRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
@Override
public void onDrawFrame(GL10 gl) {
}
}
这里啥也没干,所以你的屏幕上面啥都没有~但是大致框架已经搭建好了。另外,还需要注意一点,就是防止我们在切换程序时,OpenGL
还在绘制图形导致程序崩溃,因此我们还需要根据Activity
的生命周期针对GLSurfaceView
做一些处理:
@Override
protected void onPause() {
super.onPause();
if (glSurfaceView != null) {
glSurfaceView.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (glSurfaceView != null) {
glSurfaceView.onResume();
}
}
ok
,到目前为止,这个框架算是搭建好了,接下来,让我们把战场转移到Renderer
对象上去吧!
2 Renderer显示背景颜色
在绘制3D
模型时,我们首先要对画板的背景颜色绘制好,颜色可以随便选。glClearColor
函数是设置清屏的颜色,参数分别对应RGBA
,我们设置为红色就是glClearColor(1f, 0f, 0f, 0f);
,为啥红色是1
呢?而不是我们平时所熟知的255
,请注意:在使用OpenGL时,很多地方采用的参数变化范围都是从0到1,比如在贴纹理的时候选择图片区域也是[0,1]。也就是说,rgba
的取值都是从0~1
。然后是设置视角窗口大小glViewport
,其实就是决定绘制的矩形区域的大小,当然并不是这么简单,后面我会详细讲,目前就可以把它理解为绘制的区域,在GLSurfaceView
窗口大小发生变化时我们动态改变视角窗口。最后就是真正的绘制图形啦,我们先啥也不干,就针对画板“刷一次油漆”,把画板背景颜色设置为红色,glClear(GL10.GL_COLOR_BUFFER_BIT)
的意思是,使用glClearColor函数所设置的颜色进行清屏。
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(1f, 0f, 0f, 0f);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
}
运行一下吧,是不是看到满满的红色~。如果你的模拟器没有显示效果:请检查“Use Host GPU”选项已经勾选。如果已经勾选,那就在 glSurfaceView.setRenderer(new GLRenderer());
代码之前添加代码:glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
目前我们把基本框架写好了,但是还没有绘制模型图像,其实,我们在显示模型时,主要的工作就是集中在Renderer,重写里面的3个重要函数,基本上就可以把一个模型显示出来。下一篇文章中,我们一起学习如何显示简单的图形。