Android openGL ES纹理渲染接口详解

文章详细介绍了Android中使用GLSurfaceView进行OpenGL渲染的机制,包括GLSurfaceView的功能增强、Renderer接口的重要性、EGLContext和EGLSurface的角色,以及生命周期管理和手势事件处理。此外,还提到了EGLConfig的选择和EGLDisplay的作用。
摘要由CSDN通过智能技术生成

前两篇描述了渲染方面的内容,昨天有写了点3D模型贴图以及全景影像效果的代码。感觉有必要把接口记录下,不然只是单纯的熟练使用,对其背后原理理解还不够深刻。

首先明确要完成的任务:通过OpenGL机制渲染视频。至于视频是本地、网络或者摄像头采集到的视频不关心。呈现方面是通过OpenGL机制,通过native层代码或者Android SDK里的控件都可以。

之前的实现是纯java即Android SDK里的GLSurfaceView控件,本地视频播放通过MediaPlayer方式播放。因此以下总结基于GLSurfaceView记录,总体可以分为GLSurfaceView模块以及OpenGl模块。

GLSurfaceView

继承自SurfaceView,使用SurfaceView中的surface来呈现OpenGL显示的内容。区别于SurfaceView,主要有以下增强:

1. 管理surface这块特殊的内存,这块内存可以合入Android的显示系统。

2. 管理EGL 的显示, 方便OpenGL渲染内容至前面提高的surface内存中。

3. 可以提供用户自定义Renderer渲染对象来执行真正的渲染实现。(这块没试过~~)

4. 在GLSurfaceView内置的子线程中渲染,不影响UI线程。

5. 提供不同的渲染模式,可以是按需刷新渲染或者不间断持续渲染。

不同于Android其他的View通过继承方式重写绘制接口,GLSurfaceView通过setRenderer接口将

渲染相关的接口代理给接口实现类去重写。而且,GLSurfaceView的使用非常简单,调用setRenderer以后就完成了所有的初始化以及启动子线程的操作。

特殊处理:

设置背景Translucent透明。因为GLSurface默认的Surface是PixelFormat.RGB_888格式,即没有透明度通过。但是可通过getHolder().setFormat(PixelFormat.TRANSLUCENT)方式修改,之后每个像素就是32位了,因为多了alpha通道的8位。

设置EGLConfig,上面说过GLSurfaceView的Surface默认是PixelForm.RGB_888格式,可以通过GLSurfaceView的setEGLConfigChooser接口设置对应的参数,修改默认的参数设置。

生命周期。GLSurfaceView有onResume/onPause函数,在相应的函数中会开启或暂停渲染。

手势事件处理。可以通过queueEvent接口发送事件交给GLThread中的事件队列,然后在Runnable的run方法中自定义操作即可,就像Handler那样。🤣

GLWrapper

代码文档中说法是当Renderer回调函数中的gl参数被调用时,可以通过在GLSurfaceView中设置的GLWrapper实例静态代理方法调用,添加测试或者监控代码,但目前也没遇到在Renderer的回调函数中调用gl的场景。

Renderer

Renderer接口是最重要的接口类,负责调用OpenGL的方法完成每一帧的渲染。GLSurfaceView提供了setRenderer的方法供调用方设置接口的实现类。Renderer的渲染操作都是独立的线程完成,如果要处理屏幕手势事件可以通过GLSurfaceView的queueEvent接口发送。最关键的是EGL Context丢失问题,例如系统被唤醒时就容易出问题,在系统休眠时,如果EGL Context丢失,与其关联的所有资源例如纹理这些都会被删除。因此,要合理利用Renderer#onSurfaceCreated回调方法,在其中初始化OpenGL的状态。


   
   
  1. public interface Renderer {
  2. /**
  3. * Surface创建或重建成功后回调
  4. * 在渲染线程中调用。在开始渲染之前,应该在这个函数中完成资源初始化的工作。
  5. * @param gl the GL interface.可通过instance方法判断是否支持GL11以及更高版本。
  6. * @param config EGLConfig,可用于离屏渲染相关配置。
  7. */
  8. void onSurfaceCreated (GL10 gl, EGLConfig config);
  9. /**
  10. * 当surface创建成功或者尺寸变化时回调。
  11. * 可用于设置OpenGL的视口变换,同时可以计算空间坐标变换时的MVP矩阵。
  12. */
  13. void onSurfaceChanged (GL10 gl, int width, int height);
  14. /**
  15. * OpenGL渲染函数调用。用于绘制当前帧。
  16. * 常见调用方式如下
  17. * void onDrawFrame(GL10 gl) {
  18. * gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
  19. * //... other gl calls to render the scene ...
  20. * }
  21. */
  22. void onDrawFrame (GL10 gl);
  23. }

EGLContext

EGL上下文。OpenGL是状态机,在EGLContext中保存了当前状态,以及OpenGL可执行的指令函数,并且ELGContext与Display和Surface进行了绑定,OpenGL通过上下文将Surface内容渲染至Display上去。在创建上下文eglCreateContext时,在底层代码中会有申请内存空间地址赋值给结构体中的成员。创建成功后执行eglMakeCurrent调用,将EGLContext与当前线程即GLThread绑定。

参考1

EGLSurface

EGLSurface是一块内存空间,实际上就是一个FrameBuffer,用户想要绘制的内容会首先绘制到EGLSurface中。创建EGLSurface需要绑定“窗口对象”的GLSurfaceView的surface,当EGLSurface中有待绘制的帧时,会将数据添加入之前绑定的“窗口对象”中的缓冲队列中供系统渲染机制进行渲染。

​​​​​​参考1

参考2

参考3

参考4

EGLConfig

绘制目标FrameBuffer的配置,主要配置RGBA通道的位宽,以及是否有深度缓冲区(默认有)和模版缓冲区(0表示没有,默认没有)。


   
   
  1. private class SimpleEGLConfigChooser extends ComponentSizeChooser {
  2. public SimpleEGLConfigChooser (boolean withDepthBuffer) {
  3. super( 8, 8, 8, 0, withDepthBuffer ? 16 : 0, 0);
  4. }
  5. }

EGLDisplay

系统物理显示窗口的句柄。通过EGL10.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY)获取。

GLThread

绘制线程。在run方法中循环回调Renderer#onDrawFrame接口,通知OpenGL渲染画面。

大致的调用流程

完整工程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值