此篇文章记录下自己在android平台上使用opengl的经验,顺便记录下自己开源项目使用opengl的思路,内容会很零碎,因为只是随便整理记录下。
opengl如果要避免添加滤镜后帧数减少,要使用FBO。比如camera每秒返回30帧的数据,如果我们的opengl绘制不能在33毫秒内完成,则会导致最后显示的帧率改变,假如 GPU 遇到性能瓶颈,导致无法在一帧内更新渲染结果到帧缓存区,那么从缓存区读到的会是上一帧的内容,导致帧率降低界面卡顿。
FBO即为opengl离屏渲染的一种方式,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作. FBO的id为0时则代表是当前屏幕的。
比如滤镜的实现:
1.创建一个FBO1和FBO1对应的纹理,将纹理绑定到FBO1
2.绑定到FBO1,进行滤镜处理,渲染则会渲染到FBO绑定的纹理上
3.绑定到FBO0,再渲染到屏幕
opengl里的program 是可以复用的
但是shader一旦绑定是不能被其他program使用的,一个program绑定一个顶点shader和一个片段shader
opengl的图元只有点、线、三角形,所以要绘制其他形状只能用三角形叠加,比如圆角就是多个三角形叠加成半圆。
opengl滤镜制作
滤镜实际就是对图像的像素点色彩值进行多次加工,代码实现上就是自定义shader进行色彩处理
例如亮度,就是r,g,b分别加上亮度r+0.1 ,g+0.1,b+0.1
hsv是把rgb转hsv,再叠加
另外可以使用混合模式,减少渲染次数
https://cloud.tencent.com/developer/article/1132385 “终端图像处理系列 - OpenGL混合模式的使用”
https://blog.csdn.net/junzia/article/details/76580379 “Android OpenGLES2.0(十八)——轻松搞定Blend颜色混合”
自己的开源项目BubbleTextureview实现思路
具体是自定义绘制了一个气泡状的模型GLbubbleGeometry,另外基于GLTextureView,将TextureView的图像数据当纹理显示。
GLtextureView 是模仿根据Glsurfaceview 改过来的,新建了一个Glthread 去链接EGL, 相关知识搜索OPENGL GLtextureView相关文章。
float[] vertices = new float[verticesSize]; 保存了所有顶点,不重复
short[] indices = new short[indicesSize]; 保存了三角形绘制的点顺序具体就是0,1,2,3,2,3,4,3,4,5 .。。。 这样,绘制根据这个点顺序去绘制
topleftradius 是0-1的百分比圆角半径长度,适应opengl的0-1坐标系
求圆角的多个三角形点坐标时用
vertices[currentOffset + 5] = center[0] + radius[0] * (float) Math.cos(rads);
x坐标为 中心点 + 半径*cos角度
vertices[currentOffset + 6] = center[1] + radius[1] * (float) Math.sin(rads);
y坐标为 中心点 + 半径*sin角度
π就是逆时针180°,-π就是顺时针180°
MediaCodec 要将surface里的数据转为混合为mp4,必须要4.3以上的手机
,因为EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
这个设置surface时间的方法是必须api18的.
如果不用MediaMuxer混合视频,可以用mp4parser这个开源库,就能在4.1的手机上转码视频为mp4