android studio上第一个opengl es程序
阅读本文前如果是初次接触opengl可以先阅读前文:
openGL 3D图形和openGL简介:
http://blog.csdn.net/pangrui201/article/details/75091501
android上opengl es基础知识
Google在Android2.2 以后支持 opengl es 2.2,在Android 4.3以后引入opengl es 3.0。Android中使用openGL会用到GLSurfaceView控件, GLSurfaceView.Renderer,在Android studio的debug模式下我们可以清楚的看到Renderer的各个回调函数发生在非UI主线程,即渲染线程,具体渲染是在一块称为”surface”(在openGL里面称为ViewPort视口)的地方完成,渲染绘制完成后在将渲染结果直接在主线程显示,实际上GLSurfaceView在View Hierarchy上”穿洞”,让底层open gl surface显示出来。同时,需要考虑GLSurfaceView和Activity的各个生命周期的问题。
另一方面,在Android 4.0以后提供了一个纹理视图(TextureView)可以也可以渲染opengl,TextureView像普通view一样不在需要”穿洞”了,但是TextureView没有内置opengl的初始化操作。
第一个opengl es程序
如下代码是在Android studio上创建的第一个opengl es项目:
public class MainActivity extends AppCompatActivity { private GLSurfaceView glSurfaceView; private boolean rendererSet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); glSurfaceView = new GLSurfaceView(this); // Check if the system supports OpenGL ES 2.0. final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); /* final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000; */ // Even though the latest emulator supports OpenGL ES 2.0, // it has a bug where it doesn't set the reqGlEsVersion so // the above check doesn't work. The below will detect if the // app is running on an emulator, and assume that it supports // OpenGL ES 2.0. final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000 || (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"))); if (supportsEs2) { // Request an OpenGL ES 2.0 compatible context. glSurfaceView.setEGLContextClientVersion(2); // Assign our renderer. glSurfaceView.setRenderer(new FirstOpenGLProjectRenderer()); rendererSet = true; } else { /* * This is where you could create an OpenGL ES 1.x compatible * renderer if you wanted to support both ES 1 and ES 2. Since we're * not doing anything, the app will crash if the device doesn't * support OpenGL ES 2.0. If we publish on the market, we should * also add the following to AndroidManifest.xml: * * * * This hides our app from those devices which don't support OpenGL * ES 2.0. */ Toast.makeText(this, "This device does not support OpenGL ES 2.0.", Toast.LENGTH_LONG).show(); return; } setContentView(glSurfaceView); } @Override protected void onPause() { super.onPause(); if (rendererSet) { glSurfaceView.onPause(); } } @Override protected void onResume() { super.onResume(); if (rendererSet) { glSurfaceView.onResume(); } }}
supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;是用来判断是否支持opengl es2.0,同时在模拟器的话可能支持不是多好,所以代码进行了判断。 glSurfaceView.setEGLContextClientVersion(2);是来具体设置opengl版本,配置surface视图。同时需要注意Activity的生命周期需要回调glSurfaceView对应的生命周期,这样surface视图才能正确处理渲染线程暂停和继续,同时释放和续用opengl的上下文。
下面是FirstOpenGLProjectRenderer 的代码:
public class FirstOpenGLProjectRenderer implements Renderer { @Override public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { // Set the background clear color to red. The first component is // red, the second is green, the third is blue, and the last // component is alpha, which we don't use in this lesson. glClearColor(1.0f, 0.0f, 0.0f, 0.0f); } /** * onSurfaceChanged is called whenever the surface has changed. This is * called at least once when the surface is initialized. Keep in mind that * Android normally restarts an Activity on rotation, and in that case, the * renderer will be destroyed and a new one created. * * @param width * The new width, in pixels. * @param height * The new height, in pixels. */ @Override public void onSurfaceChanged(GL10 glUnused, int width, int height) { // Set the OpenGL viewport to fill the entire surface. glViewport(0, 0, width, height); } /** * OnDrawFrame is called whenever a new frame needs to be drawn. Normally, * this is done at the refresh rate of the screen. */ @Override public void onDrawFrame(GL10 glUnused) { // Clear the rendering surface. glClear(GL_COLOR_BUFFER_BIT); }}
主要有三个回调方法,onSurfaceCreated,onSurfaceChanged,onDrawFrame。之前已经说过了,这些方法回调发生在渲染线程。onSurfaceCreated是在surface被创建时,GLSurfaceView会回调这个方法。onSurfaceChanged是在surface被创建后每次在surface尺寸发生变化的时候GLSurfaceView会回调,比如横竖屏切换会回调这个方法。onDrawFrame是当每绘制一帧就会被GLSurfaceView回调,通常一定要在这个方法里做点事情哪怕是设置清屏颜色,因为这个方法调用之后会把渲染结果surface给屏幕显示,不能说什么都没有,这样的话可能会显示花屏。另外,通常GLSurfaceView会以显示屏的的刷新频率来回调onDrawFrame进行渲染,当然我们可以设置GLSurfaceView的渲染模式来修改,调用
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
//GLSurfaceView.RENDERMODE_CONTINUOUSLY:持续渲染(默认)
//GLSurfaceView.RENDERMODE_WHEN_DIRTY:脏渲染,命令渲染;即有两种渲染模式脏渲染和持续渲染(默认)。使用脏渲染需要和glSurfaceView.requestRender配合使用。
综上分析,在onSurfaceCreated里需要设置清屏色,本文为红色 glClearColor(1.0f, 0.0f, 0.0f, 0.0f);在onSurfaceChanged里设置视口viewport大小即通知opengl需要渲染视口大小即surface大小。注意:视口viewport是opengl里面的概念,surface是GLSurfaceView里提供给底层渲染显示的区域,故可以理解为同一个。在onDrawFrame里面 glClear(GL_COLOR_BUFFER_BIT);是清楚所有颜色缓冲器,这样就会显示清屏色即 glClearColor(1.0f, 0.0f, 0.0f, 0.0f)设置的红色。
到此,本文章结束。主要讲解基础概念,基础原理。本文代码地址:
https://github.com/pangrui201/OpenGlesProject/tree/master/OpenGlesProject_lesson1
更多相关文章
- opengl es demo(有附件)
- Android(安卓)Local Service
- Android(安卓)KeyEvent分发机制
- Android(安卓)Inflate方法
- android Launcher之获取安装的app列表的两种方法
- Android(安卓)自定义RecyclerView 实现真正的Gallery效果
- android 控制震动强度
- android studio 设置模板
- Android使用广播(BroadCast)实现强制下线的方法