Android显示系统(03)- OpenGL ES - GLSurfaceView的使用

Source

一、前言:

我们应用层和Native层其实都可以直接调用EGL接口或者OpenGL ES的接口,但是,可能比较复杂一些,Android提供了更加方便的GLSurfaceView类供应用开发者使用,GLSurfaceView会在自己的渲染线程GLThread启动之后创建OpenGL ES环境。

二、类关系图:

在这里插入图片描述

  • GLSurfaceView继承自SurfaceView
  • GLSurfaceView在构造函数中:
    • 创建surface;
    • 创建EGL环境:
      • EGLDisplay:加载OpenGL ES库;
      • EGLContext:上下文环境,可以理解成一个状态机,在不同状态下做不同的事情;
      • EGLSurface:抽象的Surface类,里面绑定具体的Surface;
  • SurfaceHolderSurfaceView的操作类;
  • GLSurfaceView有个成员Renderer,里面又有三个重要成员;一般Renderer需要用户自己实现,实现好之后通过setRenderer设置到GLSurfaceView当中;
    • onSurfaceCreatedonSurfaceCreated不是在Surface创建成功就去回调,而是稍微晚一点,等待EGLContext创建之后回调,因为app切换到后台,EGLContext有可能丢失;
    • onSurfaceChanged:Surface刚创建或者大小变化等时候被回调;在这里面可以改变视口大小;
    • onDrawFrame:不断刷新Surface中的内容;比如60fps的系统,这个函数1s会被回调60次,每次被回调它都可以调用EGL的接口,最终通过EGL调用GPU,将渲染结果输出到Surface当中;
  • GLSurfaceView还有一个重要成员GLThread,专门负责渲染的线程,在其内部会通过循环,不停调用EGL API,然后回调Renderer里面的三大方法;

三、实战:

1、工程搭建:

在这里插入图片描述

工程名GLSurfaceViewDemo,我选择的Java,你们也可以选择Kotlin,如果熟悉的话。我手机是Android 10.0。

在这里插入图片描述

2、框架代码实现:

使用GLSurfaceView主要需要按照以下步骤:

  • 实现自己的GLSurfaceView子类;
  • 实现自己的Renderer类;
  • 将自己的Renderer对象设置给GLSurfaceView子类;
  • GLSurfaceView对象设置给MainActivity

实现GLSurfaceView的子类:

// 路径:com/example/glsurfaceviewdemo/GLSurfaceViewTest.java
public class GLSurfaceViewTest extends GLSurfaceView {
    
      
    public GLSurfaceViewTest(Context context) {
    
      
        super(context);
    }
}

实现自己的Renderer类;

// 路径:com/example/glsurfaceviewdemo/GLRenderTest.java
public class GLRenderTest 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) {
    
      

    }
}

GLSurfaceView设置我们自己实现的渲染器:

public class GLSurfaceViewTest extends GLSurfaceView {
    
      
    public GLSurfaceViewTest(Context context) {
    
      
        super(context);

        // 设置OpenGL ES版本(由于3.0兼容2.0,我们使用3.0)
        setEGLContextClientVersion(3);

        // 设置渲染器Renderer,函数调用后,里面会启动一个新线程构造EGL环境
        setRenderer(new GLRenderTest());
    }
}

GLSurfaceView对象设置给MainActivity

public class MainActivity extends AppCompatActivity {
    
      
    private GLSurfaceViewTest mGlSurfaceViewTest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
      
        super.onCreate(savedInstanceState);

        mGlSurfaceViewTest = new GLSurfaceViewTest(this);
        setContentView(mGlSurfaceViewTest);
    }
}

至此,工程框架代码搭建完成;

3、测试:

视口设置为整个手机显示屏,渲染纯色:

public class GLRenderTest implements GLSurfaceView.Renderer {
    
      
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    
      
        GLES30.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
    
      
        GLES30.glViewport(0, 0,  width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
    
      
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
    }
}

运行:

在这里插入图片描述

四、小结:

本文搭建了OpenGL ES渲染环境,为后续开发做好准备。