写几篇文章记录一下我学习OpenGL的过程,这是第一篇。本片文章通过实现一个清屏操作,先了解一些基本知识。
1.创建一个activity,作为展示页面:
/** * 视图展示页面,只实现了清屏的操作<br/> * 1.创建GLSurfaceView<br/> * 2.调用GLSurfaceView的setRenderer方法,设置Renderer<br/> * 3.实现Renderer<br/> * 4.处理Activity的生命周期事件<br/> */ public class FirstOpenGLActivity extends AppCompatActivity { private static final String TAG = FirstOpenGLActivity.class.getSimpleName(); private GLSurfaceView mGLSurfaceView; /** * is render seted */ private boolean isRendererSet = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGLSurfaceView = new GLSurfaceView(this); //检察系统是否支持OpenGL ES 2.0 ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); boolean isSupportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000; Log.d(TAG, "isSupportsEs2 =" + isSupportsEs2); if (isSupportsEs2) { //Request an OpenGL ES 2.0 compatible context mGLSurfaceView.setEGLContextClientVersion(2); //Assign our renderer //当surface创建或者发生变化的时候,以及要绘制一副新帧时,渲染器都会被GLSurfaceView调用 mGLSurfaceView.setRenderer(new FirstOpenGLRenderer()); isRendererSet = true; } else { Toast.makeText(this, "this device dose not support OpenGL ES 2.0", Toast.LENGTH_SHORT); } setContentView(mGLSurfaceView); } //页面恢复,继续后台渲染线程,续用OpenGL上下文 @Override protected void onResume() { super.onResume(); if (isRendererSet) { mGLSurfaceView.onResume(); } } //页面不可见,暂停后台渲染线程,释放OpenGL上下文 @Override protected void onPause() { super.onPause(); if (isRendererSet) { mGLSurfaceView.onPause(); } } }
2.创建一个渲染器类实现Renderer接口:
/** * 渲染器类 实现了Renderer接口 * Created by hsji on 16/1/10. */ public class FirstOpenGLRenderer implements GLSurfaceView.Renderer { /** * 当surface被创建的时候,GLSurfaceView会调用这个方法; * 这发生在应用程序第一次运行的时候,并且,当设备被唤醒或者用户从其他activity切换回来的时,这个方法也可能会被调用。 * 在实践中,这意味着当程序运行时这个方法可能会被调用多次。 * * @param gl10 * @param eglConfig */ @Override public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) { //设置清空屏幕所使用的颜色RGBA GLES20.glClearColor(1.0f, 0.0f, 0.0f, 0.0f); } /** * 在surface被创建之后,每次surface尺寸发生变化时,这个方法都会被GLSurfaceView调用到。 * 在横屏、竖屏之间来回切换的时候,Surface的尺寸会发生变化。 * * @param gl10 * @param width * @param height */ @Override public void onSurfaceChanged(GL10 gl10, int width, int height) { //set the OpenGL viewport to to fill the entire surface GLES20.glViewport(0, 0, width, height); } /** * 当绘制一帧时,这个方法会被GLSurfaceView调用。 * 在这个方法中我们一定要绘制一些东西,即使只是清空屏幕; * 因为,在这个方法返回之后,渲染缓冲区会被交换并显示在屏幕上, * 如果什么都没画,可能会看到闪烁效果 * * @param gl10 */ @Override public void onDrawFrame(GL10 gl10) { //clear the rendering surface //清空屏幕,擦出屏幕上的所有颜色,并调用之前glClearColor()定义的颜色填充整个屏幕 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); } }
一点解释:怎么会有一个未被使用的参数类型GL10呢?
* 他是OpenGL ES 1.0的API遗留下来的;* 如果要编写使用OpenGL ES 1.0的渲染器,就要使用这个参数,* 但是对于OpenGL ES 2.0,GLES20类提供了静态方法来存取。
3.渲染线程和主线程之间的交互(之后还会详细涉及,这里只是一个概要)
GLSurfaceView会在一个单独的线程中调用渲染器的方法。默认情况下,GLSurfaceView会以显示设备的刷新频率不断的渲染,当然,它也可以配置为按请求渲染,只需要用GLSurfaceView.RENDERMODE_WHEN_DIRTY作为参数调用GLSurfaceView.setRenderMode()即可。 既然android的GLSurfaceView在后台县城中执行渲染,就必须要小心,只能在这个渲染线程中调用OpenGL,在android主线程中使用UI相关的调用;两个线程之间的通信可以使用如下方法:在主线程中的GLSurfaceView实例可以调用queueEvent()方法传递一个Runnable给后台渲染线程,渲染线程就可以调用Activity的runOnUIThread()来传递事件(event)给主线程。
4.运行程序即可看到一个纯红色的屏幕。
时间: 2024-09-30 10:52:30