Android OpenGL小结之专业名词理解
Android OpenGL小结之专业名词理解
image
出入之间,境界始大。不仅收其精微,汇其宏阔,且人情与道理兼具,生气同高致并存。入而不出,狭隘;出而不入,浮浅。故善学者,善于深思与总结。学习如此,创作如此,生活亦如此。
学习不仅仅是接受一些新知识,而且要擅于总结,把学习的新知识转化为自己的知识,才能学以致用;故把之前的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让其内部自动转换 image
大致如上图流程,最后一步View显示不一定非得是TextureView,也可以是GLSurfaceView和SurfaceView,那样的话涉及4和5步骤的处理方式不同;如果是GLSufaceView,直接从第4步开始,渲染到GLSurfaceView的渲染器Render即可;如果是SurfaceView,则需要在第5步骤,将前一步骤FBO里面的纹理数据glReadPixels拷贝出来,在绘制到SurfaceView的Canvas上去即可。
加入公众号,我们一同成长!
image