Matrix.scaleM(mMvpMatrix, 0, scale, scale, 1.0f);
glUniformMatrix4fv(mMvpMatrixLocation, 1, false, mMvpMatrix, 0);
//设置色值偏移的量
float textureCoordOffset = 0.01f * mProgress;
glUniform1f(mTextureCoordOffsetLocation, textureCoordOffset);
super.onDraw(textureId, texMatrix);
}
4.『毛刺』
抖音效果图:
毛刺
我的实现效果图:
毛刺
『毛刺』的效果还原的不是很完整,动画的参数没有调整好。
代码实现
看到这个效果,我们先分析一下,将视频逐帧分析,可以看到以下的截图:
毛刺截图
仔细观察这个图片,我们可以发现,其实毛刺效果就是某一行像素值偏移了一段距离,看着就像是图片被撕裂了,并且这个偏移是随着y轴随机变化的,这样看起来效果更自然,并且观察gif图可以看到,除了撕裂,还有个色值偏移的效果。色值偏移在介绍 “抖动” 效果时已经讲过了,那么这里只要解决撕裂效果就可以了。
4.1 顶点着色器
uniform mat4 uTexMatrix;
attribute vec2 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord;
uniform mat4 uMvpMatrix;
void main(){
gl_Position = uMvpMatrix * vec4(aPosition,0.1,1.0);
vTextureCoord = (uTexMatrix * aTextureCoord).xy;
}
4.2 片元着色器
#extension GL_OES_EGL_image_external : require
precision highp float;
varying vec2 vTextureCoord;
uniform samplerExternalOES uTexture;
//这是个二阶向量,x是横向偏移的值,y是阈值
uniform vec2 uScanLineJitter;
//颜色偏移的值
uniform float uColorDrift;
//随机函数
float nrand(in float x, in float y){
return fract(sin(dot(vec2(x, y), vec2(12.9898, 78.233))) * 43758.5453);
}
void main(){
float u = vTextureCoord.x;
float v = vTextureCoord.y;
float jitter = nrand(v,0.0) * 2.0 - 1.0;
float drift = uColorDrift;
float offsetParam = step(uScanLineJitter.y,abs(jitter));
jitter = jitter * offsetParam * uScanLineJitter.x;
vec4 color1 = texture2D(uTexture,fract(vec2( u + jitter,v)));
vec4 color2 = texture2D(uTexture,fract(vec2(u + jitter + v*drift ,v)));
gl_FragColor = vec4(color1.r,color2.g,color1.b,1.0);
}
这里重点讲解下片元着色器的代码,随机函数就是代码中的nrand函数
fract、dot和sin是opengl自带的函数,意思是取某个数的小数部分,即fract(x) = x - floor(x); dot是向量点乘,sin就是正弦函数
如上代码所示,我们首先取出当前像素的x、y的值,然后用y去计算随机数
float jitter = nrand(v,0.0) * 2.0 - 1.0;//这里得到一个-1到1的数
然后接下来,我们计算当前这一行的像素要往左偏,还是往右偏
float offsetParam = step(uScanLineJitter.y,abs(jitter));//step是gl自带函数,意思是,如果第一个参数大于第二个参数,那么返回0,否则返回1
所以这句话的意思就是,判断当前的随机数是否大于某个阈值,如果大于这个阈值,那么就偏移,否则就不偏移。通过控制这个阈值,我们可以改变当前视频的混乱度(越混乱,撕裂的像素就越多)
接着是计算某行像素的偏移值
jitter = jitter * offsetParam * uScanLineJitter.x;//offsetParam如果是0,就不便宜了,如果是1,就偏移jitteruScanLineJitter.x的距离,其中uScanLineJitter.x是最大偏移值
//这里计算最终的像素值,纹理坐标是0到1之间的数,如果小于0,那么图像就捅到屏幕右边去,如果超过1,那么就捅到屏幕左边去。
vec4 color1 = texture2D(uTexture,fract(vec2( u + jitter,v)));
vec4 color2 = texture2D(uTexture,fract(vec2(u + jitter + vdrift ,v)));
4.3 动画代码
动画代码这里就不贴了,大概就是根据当前帧数控制
//这是个二阶向量,x是横向偏移的值,y是阈值
uniform vec2 uScanLineJitter;
//颜色偏移的值
uniform float uColorDrift;
这两个参数的值,uScanLineJitter.x越大,横向撕裂的距离就越大;uScanLineJitter.y越大,屏幕上被撕裂的像素就越多
5.『缩放』
抖音效果图:
缩放
我的实现效果图:
缩放
代码实现
这个效果比较简单,就是放大然后缩小 不停地循环