Android OpenGL小结之专业名词理解

Android OpenGL小结之专业名词理解



出入之间,境界始大。不仅收其精微,汇其宏阔,且人情与道理兼具,生气同高致并存。入而不出,狭隘;出而不入,浮浅。故善学者,善于深思与总结。学习如此,创作如此,生活亦如此。

学习不仅仅是接受一些新知识,而且要擅于总结,把学习的新知识转化为自己的知识,才能学以致用;故把之前的OpenGL学习遇到的名词总结一番。

OpenGL ES库


OpenGL ES库是针对于嵌入式设备而裁剪的版本库,在Android端是以NDK形式存在,此库可用于GPU的图像开发,数据到图像的过程

EGL


不同产商底层驱动实现不同,为了是OpenGL在不同产商设备上能成功执行,EGL作为中间的桥梁搭建,为OpenGL提供渲染环境;EGL提供抽象显示display、渲染上下文Context以及创建3中不同的window surface;OpenGL的渲染操作必须要EGL为其提供渲染环境,Android里面常见的GLSurfaceView不用,因为其内部已经显示了EGL环境,但是如其他的SurfaceView、TextureView则需要自己去实现EGL环境

GLSL


用于指导GPU可编程管线的编程语言,与C语言类似;主要用于指导GPU管线如何去绘制图元、颜色;编写好程序后需要提交给OpenGL进行编译、链接才能使用;这里主要编写顶点着色器和片元着色器

纹理


纹理主要是用于图像数据的展示,创建纹理后,绑定图像数据textImage2D(),最后在渲染时,首先激活纹理,然后片元着色器的采样器Sampler会根据传入的纹理坐标来这个纹理数据里面取色渲染

FBO


Frame Buffer Object帧缓冲对象,在屏幕上显示的最后一步,就是将所有的任务提交给FBO,由FBO输出到屏幕上;日常开发中没有使用FBO而屏幕上却显示了,那是因为默认激活的FBO ID为0,这个ID为0的就是屏幕的FBO;所以我们可以创建ID非0的FBO,这样我们输出到FBO的图像就不会显示到屏幕;

那FBO有什么用?

  • 可以对图像预处理,如图像美颜,处理完成后再通过其他收发输出到屏幕
  • FBO突破屏幕尺寸,不在受默认FBO屏幕尺寸的限制

如何使用FBO?
详情可以点击这里,FBO提供颜色附着和深度附着,我们可以使用纹理以及renderBuffer附着到FBO上,当我们激活FBO后,正常渲染操作都会输出到FBO,然后可以通过预先附着的纹理和renderBuffer提取图像

Android与OpenGL相关的组件


SurfaceView


复杂的2D图像绘制显示,不阻塞主线程
必须在子线程中使用,并且在回调SurfaceHolder的surfaceCreated和surfaceDestroyed方法之间才能绘制
双缓冲机制,绘制完成后显示,lockCanvas获取画布进行绘制,unlockCanvasAndPost提交更新
伪代码例子:

public class MyView extends SurfaceView 
					implements SurfaceHolder.Callback
					,Runnable {
	@Override
    public void surfaceCreated(SurfaceHolder holder) {
        running=true;
        new Thread(this).start();
 
    }
 
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
 
    }
 
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
 		running=false;
    }
	@Override
    public void run() {
        while(shouldDrawing){
                Canvas=surfaceHolder.lockCanvas();
                //drawing
                surfaceHolder.unlockCanvasAndPost(mCanvas);
        }
    }

}

GLSurfaceView


GLSurfaceView集成与SurfaceView,集成了SurfaceView的特性,不同的是它使用了OpenGL环境来渲染,其内部已实现了EGL环境,使用方法主要是:

  • 设置Render渲染器
  • 设置渲染方式
glSurfaceView.setRenderer(renderer);
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

RENDERMODE_WHEN_DIRTY 触发式手动刷新 RENDERMODE_CONTINUOUSLY 持续刷新 固定周期刷新

  • Render渲染器,渲染具体流程
public class GLRender implements GLSurfaceView.Renderer {
	//surfaceView创建时调用
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
    }

    //surfaceView绘制时回调
    @Override
    public void onDrawFrame(GL10 gl) {
    }
}

TextureView


TextureView可用于显示图像流,来自相机或者OpenGL渲染的图像;主要是通过TexttureView方法onSurfaceTextureAvailable的参数SurfaceTexture表面纹理来实现的

TextureView与相机Camera搭配


public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
          mCamera = Camera.open();
          try {
              mCamera.setPreviewTexture(surface);
              mCamera.startPreview();
          } catch (IOException ioe) {
              // Something bad happened
          }
      }

TextureView与OpenGL搭配


  • EGL创建windowSurface以及OpenGL的渲染环境
  • 与TextureView的SurfaceTexture绑定makecurrent
  • OpenGL正常的渲染绘制
  • swapBuffer进行显示

SurfaceTexture


表面纹理SurfaceTexture,实质也是一个纹理的封装类,其内部纹理可以作为图像流的输出对象,来自相机或者解码的视频流均可以;

小测验


你理解了上面的名词解释了吗?或者你自学OpenGL觉得OK了吗?那咱们来个小测验吧!
相机美颜过程如何实现的?只需要一个大概的理解就可以,无需太详细,先不要看后面的答案!


问题分析:
首先,我们要拿到相机的预览数据,而且不能马上显示到屏幕,这就需要FBO;
然后,对拿到的相机数据进行美颜处理,这里处理就需要glsl的美颜算法;
最后,在将修改的数据渲染的默认的屏幕FBO上去,显示即可;
还需要注意的一点是:相机预览数据一般均是YUV格式,而OpenGL只能显示RGB图像,这里需要设置SurfaceTexture纹理特定的格式OES让其内部自动转换

在这里插入图片描述
大致如上图流程,最后一步View显示不一定非得是TextureView,也可以是GLSurfaceView和SurfaceView,那样的话涉及4和5步骤的处理方式不同;如果是GLSufaceView,直接从第4步开始,渲染到GLSurfaceView的渲染器Render即可;如果是SurfaceView,则需要在第5步骤,将前一步骤FBO里面的纹理数据glReadPixels拷贝出来,在绘制到SurfaceView的Canvas上去即可。

我的项目地址

加入公众号,我们一同成长!

在这里插入图片描述

发布了148 篇原创文章 · 获赞 41 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/jackzhouyu/article/details/103401902