OpenGLES-缩放、灵魂出窍、抖动、闪白、毛刺与幻觉滤镜

856 阅读3分钟

缩放

原理

可以通过修改顶点坐标和纹理理坐标的对应关系来实现放大和缩小

代码实现 

attribute vec4 Position;
attribute vec2 TextureCoords;
varying vec2 TextureCoordsVarying;
//时间戳(及时更新)
uniform float Time;
//
const float PI = 3.1415926;

void main(){时长
    //一次缩放效果shi'chang
    float duration = 0.6;
    //最大缩放幅度
    float maxAmplitude = 0.3;
    //表示传入的时间周期,time控制在[0,0.6]范围内
    //mod(a,b)是求模运算相当于 a % b
    float time = mod(Time, duration);
    //缩放的幅度,添加sin是为了使用PI,保证缩放幅度在[1.0, 1.3]之间,并随着时间变化
    float edutilpma = 1.0 + maxAmplitude * abs(sin(time *(PI/duration)));
    //x、y缩放,zw不变
    gl_Position = vec4(Position.x * edutilpma,Position.y * edutilpma,Position.zw);
    TextureCoordsVarying = TextureCoords;
}

效果

灵魂出窍

原理

两个层的叠加,并且上面的那层随着时间的推移,会逐渐放大且 不透明度逐渐降低 。

代码实现

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
uniform float Time;

void main(){
    //一次灵魂出窍的时长
    float duration = 0.7;
    //最大透明度
    float maxAlpha = 0.3;
    //最大缩放值
    float maxScale = 1.8;
    //进度(0,1)
    float progress = mod(Time, duration) / duration;
    //缩放的透明度
    float alpha = maxAlpha * (1.0 - progress);
    //缩放的值
    float scale = (maxScale - 1.0) * progress + 1.0;
    //获得x的缩放
    float weakX = 0.5 + (TextureCoordsVarying.x - 0.5)/scale;
    //获得y的缩放
    float weakY = 0.5 + (TextureCoordsVarying.y - 0.5)/scale;
    //获得新的坐标
    vec2 weakTextureCoordsVarying = vec2(weakX, weakY);
    //读取放大后的颜色值
    vec4 maskColor = texture2D(Texture, weakTextureCoordsVarying);
    //读取原来的颜色值
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    //颜色混合,
    gl_FragColor = mask * (1.0 - alpha) + maskColor * alpha;
}

效果

抖动

原理

颜色偏移加上微弱的放大即可实现

代码实现

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
uniform float Time;

void main(){
    //一次抖动的时长
    float duration = 0.7;
    //放大的上限
    float maxScale = 1.1;
    //颜色偏移最大步长
    float offset = 0.02;

    //进度0-1
    float progress = mod(Time, duration) / duration;
    //获得偏移后的颜色(根据时间变化)
    vec2 offsetCoords = vec2(offset, offset) *progress;
    //获得缩放比例
    float scale = 1.0 + (maxScale - 1.0) * progress;
    //获得放大后的纹理
    vec2 scaleTextureCoords = vec2(TextureCoordsVarying.x / scale, TextureCoordsVarying.y / scale);
    //获取偏移后的R、G、B
    vec4 maskR = texture2D(Texture, scaleTextureCoords + offsetCoords);
    vec4 maskB = texture2D(Texture, scaleTextureCoords - offsetCoords);

    //获得原始颜色
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    gl_FragColor = vec4(maskR.r, mask.g, maskB.b, mask.a);

}

效果

闪白

原理

添加⽩白⾊色图层 ,⽩白⾊色图层的透明度随着时间变化

代码实现

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
uniform float Time;

const float PI = 3.1415926;

void main(){
    //一次闪白时长
    float duration = 0.6;
    //时间周期0.0-0.6
    float time = mod(Time,duration);
    //白色
    vec4 whiteColor = vec4(1.0, 1.0, 1.0, 1.0);
    //振幅(实际就是透明度)0.0-1.0
    float amplitude = abs(sin(time * (PI/duration)));
    //原始颜色
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    //混合颜色
    gl_FragColor = mask * (1.0 - amplitude) + whiteColor * amplitude;

}

效果

毛刺

原理

撕裂加上微弱的颜色偏移。

具体实现:就是我们让每⼀一⾏行行像素随机偏移 -1 ~ 1 的距离(这⾥里里的 -1 ~ 1 是对于纹理理坐标来说的),但是如果整个 画⾯面都偏移⽐比较⼤大的值,那我们可能都看不不出原来图像的样⼦子。所以我们的逻辑是,设定⼀一个阈值,⼩小于这个阈值才进⾏行行偏 移,超过这个阈值则乘上⼀一个缩⼩小系数。最终的结果就是 绝⼤大部分的⾏行行都会进⾏行行微⼩小的偏移,只有少量量的⾏行行会进⾏行行较⼤大偏移

代码实现

precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
uniform float Time;

const float PI = 3.1415926;

float rand(float n) {
    return fract(sin(n) * 43758.5453123);
}

void main(){
    float duration = 0.3;
    //最大抖动
    float maxJitter = 0.06;
    //
    float colorROffset = 0.01;
    //
    float colorBOffset = -0.025;
    //time范围是0.0-0.6
    float time = mod(Time, duration * 2);
    //设置振幅,将振幅控制在1.0-1.3之间并随时间变化
    float amplitude = max(sin(time * (PI / duration)), 0.0);
    //设置像素偏移-1~1
    float jitter = rand(TextureCoordsVarying.y) * 2.0 - 1.0;
    //是否需要撕裂,如果jitter小于最大抖动*振幅
    bool needOffset = abs(jitter) < maxJitter *amplitude;
    //获得纹理x的坐标,根据needOffset判断是撕裂大还是小
    float textureX = TextureCoordsVarying.x + (needOffset ? jitter : (jitter * amplitude * 0.006));
    //获得撕裂后的纹理坐标
    vec2 textureCoords = vec2(textureX, TextureCoordsVarying.y);
    //获得3组颜色
    vec4 mask = texture2D(Texture, textureCoords);
    vec4 maskR = texture2D(Texture, textureCoords + vec2(colorROffset * amplitude), 0.0);
    vec4 maskB = texture2D(Texture, textureCoords + vec2(colorBOffset * amplitude), 0.0);

    gl_FragColor = vec4(maskR.r, mask.g, maskB.b, mask.a);
}

效果