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

一.先看看整体效果

整体效果图

二.缩放

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

                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;

}


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342