-
前提
上一篇文章说到ffmpeg合成转场效果,后来发现这样的方案行不通的,一是合成时间太慢,而是需要实时的查看转场的效果,所以应该要动态查看转场的效果。所以用opengl实现转场方案最合适不过了 -
实现步骤:
图片转场:两个图片进行切换是,传入前一张和当前张图片的纹理到转场的(transitionfilter)滤镜中,在图片切换的时候,展示transitionfilter
视频转场:截取当前视频的第一帧和上一视频的最后一帧图片,同样给transitionfilter赋值,在视频切换的时候,显示transitionfilter -
搭建环境注意点
因为用到opengl,所以得要用glsurfaview去承载渲染,对于视频而言,根据相机用glsurfaview显示一个道理
SurfaceTexture surfaceTexture = mOpenglDrawer.getSurfaceTexture();
surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.
OnFrameAvailableListener() {
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
requestRender();
}
});
Surface surface = new Surface(surfaceTexture);
mMediaPlayer.setSurface(surface);
if (isCurrentVideo()) {
mMediaPlayer.prepare();
mOpenglDrawer.setInputTextureVideo();
}
对于图片,则手动去推动,按照一秒25帧默认,那么就是40ms推动一次渲染
剩下就是编写opengl的fragment片段的事情了,不过对于视频帧的转场而言,需要对纹理进行转化一下,因为最开始视频进来的fragment定义的纹理对象是uniform samplerExternalOES vTexture;
所以需要创建一层FBO:
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height,
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
然后从FBO刷新出来的纹理便是sampler2D了,在用这个纹理去做transitionfilter的转场
- 代码演示
放一个最简单的移动切换的fragment代码:
varying vec2 textureCoordinate;
uniform float progress;
uniform sampler2D vTexture;
uniform sampler2D vTexture1;
uniform vec2 direction;
void main(){
vec2 p = textureCoordinate + progress*sign(direction);
float m =step(0.0, p.y) * step(p.y, 1.0) * step(0.0, p.x) * step(p.x, 1.0);
vec4 color = mix(texture2D(vTexture, textureCoordinate),
texture2D(vTexture1, textureCoordinate), m);
gl_FragColor = vec4(color);
}
丰富的转场案例可以从这里得到:
https://gl-transitions.com/gallery
这个网站中,uv转化成自己的纹理坐标, getFromColor(uv)换成自己的纹理:比如上面的我第一张纹理是texture2D(vTexture, textureCoordinate)
getToColor(uv)换成第二张纹理:对应我自己的是texture2D(vTexture1, textureCoordinate)
下篇文章介绍带转场效果、滤镜的多视频多图片的视频合成
网友评论