美文网首页OpenGL
OpenGLES滤镜(三)----缩放/灵魂出窍/抖动/闪白/毛

OpenGLES滤镜(三)----缩放/灵魂出窍/抖动/闪白/毛

作者: 枫紫_6174 | 来源:发表于2020-08-17 10:31 被阅读0次

一.先看看整体效果

整体效果图

二.缩放

    我们先来看看顶点着色器代码:

                attribute vec4 Position;

                attributevec2TextureCoords;

                varyingvec2TextureCoordsVarying;

                uniform float Time;

                const float PI = 3.1415926;

                voidmain (void) {

                    float duration =0.6;

                    float maxAmplitude =0.3;

                    floattime =mod(Time, duration);

                    floatamplitude =1.0+ maxAmplitude *abs(sin(time * (PI / duration)));

                    gl_Position=vec4(Position.x * amplitude, Position.y * amplitude, Position.zw);

                    TextureCoordsVarying = TextureCoords;

                }

        uniform float Time时间戳,根据时间刷新,maxAmplitude =0.3最大缩放幅度,const float PI = 3.1415926,也就是π,我们先看看三角函数:

三角函数sin

在0-π的范围,sin函数从0-1,再1-0,可以形象的描述放大又回到原来大小的过程

时间移动函数处理

        说明:把π度分成一个时间周期duration份,算出这个模在对应的幅度值,最后用最大缩放乘以sin函数,得到缩放的顶点坐标,最后提交给gl_Position;//x,y 放⼤; z和w保存不变 gl_Position = vec4(Position.x * amplitude, Position.y * amplitude, Position.zw); 

三.灵魂出窍

1.根据时间计算变换进度:floatprogress =mod(Time, duration) / duration

2.透明度跟随时间的变换而变化: floatalpha = maxAlpha * (1.0- progress);

3.计算缩放效果:floatscale =1.0+ (maxScale -1.0) * progress;

4.任意一点的纹理坐标(x,y)缩放计算:floatweakX =0.5+ (TextureCoordsVarying.x -0.5) / scale; floatweakY =0.5+ (TextureCoordsVarying.y -0.5) / scale;


任意一点纹理坐标计算

任意一点的坐标以中心点为参考点

5.混合: vec2weakTextureCoords =vec2(weakX, weakY);

             vec4weakMask =texture2D(Texture, weakTextureCoords);

              vec4mask =texture2D(Texture, TextureCoordsVarying);

              gl_FragColor= mask * (1.0- alpha) + weakMask * alpha;

灵魂出窍效果图

四.抖动

        抖动的效果实际就是放大缩小,在该效果上我们让单个的像素点产生一点偏移:floatoffset =0.02;(偏移量不应太大,否则显示的纹理不够美观,甚至变形)

    floatduration =0.7;变换周期

    floatmaxScale =1.1;最大变换

    floatoffset =0.02;偏移

    float progress =mod(Time, duration) / duration;// 0~1

    vec2  offsetCoords =vec2(offset, offset) * progress;

    float  scale =1.0+ (maxScale -1.0) * progress;

    vec2 ScaleTextureCoords =vec2(0.5,0.5) + (TextureCoordsVarying -vec2(0.5,0.5)) / scale;

    vec4 maskR =texture2D(Texture, ScaleTextureCoords + offsetCoords);

    vec4 maskB =texture2D(Texture, ScaleTextureCoords - offsetCoords);

    vec4 mask =texture2D(Texture, ScaleTextureCoords);

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

抖动效果图

五.闪白

闪白的原理就是混合白色+透明度的改变:

    floatduration =0.6;

    floattime =mod(Time, duration);

    vec4whiteMask =vec4(1.0,1.0,1.0,1.0);

    floatamplitude =abs(sin(time * (PI / duration)));

    vec4mask =texture2D(Texture, TextureCoordsVarying);

   gl_FragColor= mask * (1.0- amplitude) + whiteMask * amplitude;


闪白效果图

六.毛刺

mod函数计算时间周期:floattime =mod(Time, duration *2.0);

计算振幅,范围是「0, 1]:floatamplitude =max(sin(time * (PI / duration)),0.0);

获取像素点随机偏移值,范围是[-1,1]:floatjitter = rand(TextureCoordsVarying.y) *2.0-1.0;// -1~1

判断是否需要偏移 & 计算纹理的x坐标

需要偏移,撕裂较大,即x的颜色偏移较大

不需要,撕裂较小,即x的颜色偏移值很微小

获取撕裂后的纹理坐标

计算撕裂后的3组纹素,并获取不同组中的RGBA值

片元着色器代码:

precision highp float;

uniform sampler2D Texture;

varyingvec2TextureCoordsVarying;

uniform float Time;

const float PI = 3.1415926;

floatrand(floatn) {

    returnfract(sin(n) *43758.5453123);

}

voidmain (void) {

    floatmaxJitter =0.06;

    floatduration =0.3;

    floatcolorROffset =0.01;

    floatcolorBOffset =-0.025;

    floattime =mod(Time, duration *2.0);

    floatamplitude =max(sin(time * (PI / duration)),0.0);

    floatjitter = rand(TextureCoordsVarying.y) *2.0-1.0;// -1~1

    boolneedOffset =abs(jitter) < maxJitter * amplitude;

    floattextureX = TextureCoordsVarying.x + (needOffset ? jitter : (jitter * amplitude *0.006));

    vec2textureCoords =vec2(textureX, TextureCoordsVarying.y);

    vec4mask =texture2D(Texture, textureCoords);

    vec4maskR =texture2D(Texture, textureCoords +vec2(colorROffset * amplitude,0.0));

    vec4maskB =texture2D(Texture, textureCoords +vec2(colorBOffset * amplitude,0.0));

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

}

毛刺效果图

七。幻觉滤镜

顶点着色器代码:

precision highp float;

uniform sampler2D Texture;//一次幻觉效果的时长,即周期

varyingvec2TextureCoordsVarying;

uniform float Time;

const float PI = 3.1415926;

constfloatduration =2.0;

//这个函数可以计算出,在某个时刻图片的具体位置,通过它可以每经过一段时间,去生成一个新的mask//转圈产生幻影的单个像素点的颜色值

vec4 getMask(floattime,vec2textureCoords,floatpadding) {

//圆心

    vec2translation =vec2(sin(time * (PI *2.0/ duration)),

                            cos(time * (PI *2.0/ duration)));

//新的纹理坐标 = 原始纹理坐标 + 偏移量 * 圆周坐标(新的图层与图层之间是有间距的,所以需要偏移)

    vec2 translationTextureCoords = textureCoords + padding * translation;

//根据新的纹理坐标获取新图层的纹素

    vec4 mask =texture2D(Texture, translationTextureCoords);

    return mask;

}

//这个函数可以计算出,某个时刻创建的层,在当前时刻的透明度//进度:

float maskAlphaProgress(floatcurrentTime,floathideTime,floatstartTime) {

//mod(时长+持续时间 - 开始时间,时长)得到一个周期内的time

    float time =mod(duration + currentTime - startTime, duration);

//如果小于0.9,返回time,反之,返回0.9

    return min(time, hideTime);

}

voidmain (void) {

//将传入的时间戳转换到一个周期内,time的范围是【0,2】//获得时间周期

    float time =mod(Time, duration);

//放大后的倍数

    float scale =1.2;

//偏移量 = 0.083

    float padding =0.5* (1.0-1.0/ scale);

//放大后的纹理坐标

    vec2 textureCoords =vec2(0.5,0.5) + (TextureCoordsVarying -vec2(0.5,0.5)) / scale;

//新建层的隐藏时间 即新建层什么时候隐藏

    float hideTime =0.9;

//时间间隔:隔0.2s创建一个新层

    float timeGap =0.2;

//注意:只保留了红色的透明的通道值,因为幻觉效果残留红色//幻影残留数据//max RGB alpha//新图层的 R透明度

    float maxAlphaR =0.5;// max R

    float maxAlphaG =0.05;// max G

    float maxAlphaB =0.05;// max B

    vec4 mask = getMask(time, textureCoords, padding);

//获取新的图层的坐标,需要传入时间、纹理坐标、偏移量

    float alphaR =1.0;// R

    float alphaG =1.0;// G

    float alphaB =1.0;// B

//最终图层颜色:初始化

    vec4resultMask =vec4(0,0,0,0);

//循环:每一层循环都会得到新的图层的颜色,即幻影颜色//一次循环只是计算一个像素点的纹素,需要在真机运行。模拟器会卡,主要是模拟器上是CPU模拟GPU的

    for(float f =0.0; f < duration; f += timeGap) {

        float tmpTime = f;

        vec4 tmpMask = getMask(tmpTime, textureCoords, padding);

        //某个时刻创建的层,在当前时刻的红绿蓝的透明度//临时的透明度 = 根据时间推移RGB的透明度发生变化//获得临时的红绿蓝透明度

        float tmpAlphaR = maxAlphaR - maxAlphaR * maskAlphaProgress(time, hideTime, tmpTime) / hideTime;

        float tmpAlphaG = maxAlphaG - maxAlphaG * maskAlphaProgress(time, hideTime, tmpTime) / hideTime;

        float tmpAlphaB = maxAlphaB - maxAlphaB * maskAlphaProgress(time, hideTime, tmpTime) / hideTime;

//累计每一层临时RGB * RGB的临时透明度//结果 += 临时颜色 * 透明度,即刚产生的图层的颜色

        result Mask +=vec4(tmpMask.r * tmpAlphaR,

                           tmpMask.g * tmpAlphaG,

                           tmpMask.b * tmpAlphaB,

                           1.0);

        alpha R -= tmpAlphaR;

        alpha G -= tmpAlphaG;

        alpha B -= tmpAlphaB;

    }

    result Mask +=vec4(mask.r * alphaR, mask.g * alphaG, mask.b * alphaB,1.0);

    gl_FragColor= resultMask;

}

相关文章

网友评论

    本文标题:OpenGLES滤镜(三)----缩放/灵魂出窍/抖动/闪白/毛

    本文链接:https://www.haomeiwen.com/subject/ncdbdktx.html