严以律己,宽以待人
- Android OpenGLES开发:EGL环境搭建
- Android OpenGLES2.0开发(一):艰难的开始
- Android OpenGLES2.0开发(二):环境搭建
- Android OpenGLES2.0开发(三):绘制一个三角形
- Android OpenGLES2.0开发(四):矩阵变换和相机投影
- Android OpenGLES2.0开发(五):绘制正方形和圆形
- Android OpenGLES2.0开发(六):着色器语言GLSL
- Android OpenGLES2.0开发(七):纹理贴图之显示图片
- Android OpenGLES2.0开发(八):Camera预览
- Android OpenGLES2.0开发(九):图片滤镜
- Android OpenGLES2.0开发(十):FBO离屏渲染
- Android OpenGLES2.0开发(十一):渲染YUV
引言
终于到该章节了,还记得Android OpenGLES2.0开发(一):艰难的开始章节说的吗?写这个系列的初衷就是因为每次用到GLSurfaceView
+Camera
预览时,总是Ctrl+C、Ctrl+V从来没有研究过里面的代码,也不知道如何修改。经过前面章节的铺垫,现在可以自信的说Camera
+OpenGL ES
轻松拿捏。
外部纹理
上一篇中我们已经讲过如何显示一张图片,而Camera预览其实也是显示一张一张的图片。我们将Camera的预览帧数据转化为Bitmap传给OpenGL ES
就可以了。但是这种方式就失去了使用OpenGL ES
效率高的优势,NV21转Bitmap是CPU操作极其耗性能。
那么有没有更好的方式?答案是有的,我们可以将NV21数据直接传给OpenGL ES进行处理预览,这样操作就快了很多。我们知道OpenGL ES
显示的是RGBA的数据,相当于OpenGL ES要将NV21转为RGBA,效率肯定比上面的情况好很多,但是操作略微复杂,这也不是最终方案,有没有更简单的方式呢?
Android的Camera及Camera2都可以使用SurfaceTexture作为预览载体,但是它们所使用的SurfaceTexture传入的OpenGL ES texture object name必须为GLES11Ext.GL_TEXTURE_EXTERNAL_OES
。GL_TEXTURE_EXTERNAL_OES
是一种特殊的纹理类型,只用于处理外部图像或视频数据,如从摄像头捕捉的实时图像和外部视频流。
GL_TEXTURE_EXTERNAL_OES的特点:
- 需采用特殊的采样器类型和纹理着色器扩展
- 使用二维纹理坐标进行操作,与GL_TEXTURE_2D相似
- 专门用于
处理外部图像或视频数据
,可直接从BufferQueue中接收的数据渲染纹理多边形
,从而提供更高效的视频处理和渲染性能
纹理渲染
Android Camera系列(三):GLSurfaceView+Camera这篇文章我们详细介绍了Camera使用GLSurfaceView进行预览操作,但唯独缺失了使用OpenGL ES
绘制部分,而本篇是时候填坑了。
开始编写代码前,我们需要将上一篇的
Image
类拷贝一份命名为CameraFilter
1. 修改纹理着色器
首先,我们需要修改我们的着色器,将顶点着色器修改为:
// 顶点着色器代码
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;\n" +
// 顶点坐标
"attribute vec4 vPosition;\n" +
"uniform mat4 uTexPMatrix;\n" +
// 纹理坐标
"attribute vec4 vTexCoordinate;\n" +
"varying vec2 aTexCoordinate;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * vPosition;\n" +
" aTexCoordinate = (uTexPMatrix * vTexCoordinate).xy;\n" +
"}";
顶点着色器中的代码和渲染图片顶点着色器代码基本一致,增加了一个uTexPMatrix
变量,这个是用来对纹理坐标进行变换的矩阵
uTexPMatrix
纹理顶点变换的矩阵其实可以不用,我们只用顶点变换矩阵也是可以的,但是我们就需要对Camera前后置旋转变换要做一个处理。而SurfaceTexture中会自带一个变换矩阵,我们拿来直接用就不用处理Camera的前后置及旋转方向的问题了。
// 片段着色器代码
private final String fragmentShaderCode =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" +