OpenGL ES 入門之旅--縮放,出竅兄旬,抖動(dòng)狼犯,閃白,毛刺濾鏡

shiyuan2.jpg

這篇濾鏡效果的實(shí)現(xiàn)是在上一篇分屏濾鏡的基礎(chǔ)上來(lái)進(jìn)行實(shí)現(xiàn)的领铐,同樣的前提是可以利用GLSL加載一張正常的圖片悯森。

縮放濾鏡

縮放濾鏡實(shí)際上基本的原理是可以通過(guò)修改頂點(diǎn)坐標(biāo)和紋理坐標(biāo)的對(duì)應(yīng)關(guān)系來(lái)實(shí)現(xiàn)放大縮小效果。

這個(gè)放大縮小的實(shí)現(xiàn)其實(shí)可以在頂點(diǎn)著色器中實(shí)現(xiàn)绪撵,也可以在片元著色器中實(shí)現(xiàn)瓢姻。(注意:在運(yùn)行時(shí),著色器代碼中最好不要有中文)
頂點(diǎn)著色器代碼:

// 頂點(diǎn)坐標(biāo)
attribute vec4 Position;
// 紋理坐標(biāo)
attribute vec2 TextureCoords;
varying vec2 TextureCoordsVarying;
// 時(shí)間(通過(guò)uniform傳入一個(gè)時(shí)間Time)
uniform float Time;
const float PI = 3.1415926;

void main (void) {
   
    // 一次縮放效果時(shí)長(zhǎng)
    float duration = 0.4;
    // 最大縮放幅度
    float maxAmplitude = 0.3;
    // 表示時(shí)間周期
    float time = mod(Time, duration);
    
    // 縮放幅度 [1.0,1.3]
    float amplitude = 1.0 + maxAmplitude * abs(sin(time * (PI / duration)));

    // 頂點(diǎn)坐標(biāo)x/y 分別乘以放大系數(shù)[1.0,1.3]
    gl_Position = vec4(Position.x * amplitude, Position.y * amplitude, Position.zw);
   
    // 紋理坐標(biāo)
    TextureCoordsVarying = TextureCoords;
}

實(shí)現(xiàn)效果:

縮放.gif

出竅濾鏡

靈魂出竅濾鏡的原理: 是兩個(gè)層的疊加音诈,并且上面的那層隨著時(shí)間的推移幻碱,會(huì)逐漸放大且不透明度逐漸降低。這里也?到了放大的效果(基于縮放的原理)细溅,我們這次用片元著?器來(lái)實(shí)現(xiàn)該效果褥傍。

片元著色器代碼:

precision highp float;
// 紋理采樣器
uniform sampler2D Texture;
// 紋理坐標(biāo)
varying vec2 TextureCoordsVarying;
// 時(shí)間(通過(guò)uniform傳入一個(gè)時(shí)間Time)
uniform float Time;

void main (void) {
    // 一次靈魂出竅效果的時(shí)長(zhǎng) 1.0
    float duration = 1.0;
    // 透明度上限
    float maxAlpha = 0.5;
    // 放大圖片上限
    float maxScale = 1.8;
    
    // 進(jìn)度值[0,1]
    float progress = mod(Time, duration) / duration; // 0~1
    // 透明度范圍[0,0.5]
    float alpha = maxAlpha * (1.0 - progress);
    // 縮放比例[1.0,1.8]
    float scale = 1.0 + (maxScale - 1.0) * progress;
    
    // 放大紋理坐標(biāo)
    // 根據(jù)放大比例,得到放大紋理坐標(biāo) [0,0],[0,1],[1,1],[1,0]
    float weakX = 0.5 + (TextureCoordsVarying.x - 0.5) / scale;

    float weakY = 0.5 + (TextureCoordsVarying.y - 0.5) / scale;
    // 放大紋理坐標(biāo)
    vec2 weakTextureCoords = vec2(weakX, weakY);
    
    // 獲取對(duì)應(yīng)放大紋理坐標(biāo)下的紋素(顏色值rgba)
    vec4 weakMask = texture2D(Texture, weakTextureCoords);
   
    // 原始的紋理坐標(biāo)下的紋素(顏色值rgba)
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    
    // 顏色混合 默認(rèn)顏色混合方程式 = mask * (1.0-alpha) + weakMask * alpha;
    gl_FragColor = mask * (1.0 - alpha) + weakMask * alpha;
}

實(shí)現(xiàn)效果:

靈魂出竅.gif

可以看到這這個(gè)效果中谒兄,下面的那一層根本就沒(méi)有變化摔桦,只是上面的一層做了放大,以此來(lái)造成視覺(jué)上的偏差承疲。

抖動(dòng)濾鏡

抖動(dòng)的過(guò)程中也是基于縮放的原理邻耕,而且它的顏色值產(chǎn)生一定的偏差。
抖動(dòng)效果: 顏?偏移 + 微弱的放大效果

片元著色代碼:

precision highp float;
// 紋理
uniform sampler2D Texture;
// 紋理坐標(biāo)
varying vec2 TextureCoordsVarying;
// 時(shí)間(通過(guò)uniform傳入一個(gè)時(shí)間Time)
uniform float Time;

void main (void) {
    // 一次抖動(dòng)濾鏡的時(shí)長(zhǎng)
    float duration = 1.0;
    // 放大圖片上限
    float maxScale = 1.2;
    // 顏色偏移步長(zhǎng)
    float offset = 0.02;
    
    // 進(jìn)度[0,1]
    float progress = mod(Time, duration) / duration; 
    // 顏色偏移值范圍[0,0.02]
    vec2 offsetCoords = vec2(offset, offset) * progress;
    // 縮放范圍[1.0-1.2];
    float scale = 1.0 + (maxScale - 1.0) * progress;
    
    // 放大紋理坐標(biāo).
    vec2 ScaleTextureCoords = vec2(0.5, 0.5) + (TextureCoordsVarying - vec2(0.5, 0.5)) / scale;
    
    // 獲取3組顏色rgb
    // 原始顏色+offsetCoords
    vec4 maskR = texture2D(Texture, ScaleTextureCoords + offsetCoords);
    // 原始顏色-offsetCoords
    vec4 maskB = texture2D(Texture, ScaleTextureCoords - offsetCoords);
    // 原始顏色
    vec4 mask = texture2D(Texture, ScaleTextureCoords);
    
    // 從3組來(lái)獲取顏色:
    // maskR.r,mask.g,maskB.b 注意這3種顏色取值可以打亂或者隨意發(fā)揮.只是效果會(huì)有不一樣.
    // mask.a 獲取原圖的透明度
     gl_FragColor = vec4(mask.r, maskR.g, maskB.b, mask.a);

}

實(shí)現(xiàn)效果:

抖動(dòng).gif

閃白濾鏡

閃白濾鏡的原理: 在上層添加?色圖層 ,?色圖層的透明度隨著時(shí)間的變化而變化燕鸽。
片元著色器代碼:

precision highp float;
// 紋理采樣器
uniform sampler2D Texture;
// 紋理坐標(biāo)
varying vec2 TextureCoordsVarying;
// 時(shí)間(通過(guò)uniform傳入一個(gè)時(shí)間Time)
uniform float Time;

void main (void) {
    // 一次閃白濾鏡的時(shí)長(zhǎng)
    float duration = 0.5;
    // 表示時(shí)間周期[0.0,0.5]
    float time = mod(Time, duration);
    // 白色顏色遮罩層
    vec4 whiteMask = vec4(1.0, 1.0, 1.0, 1.0);
    // 振幅: (0.0,1.0)
    float amplitude = abs(sin(time * (PI / duration)));
    // 紋理坐標(biāo)對(duì)應(yīng)的紋素(RGBA)
    vec4 mask = texture2D(Texture, TextureCoordsVarying);
    
    // 利用混合方程式; 白色圖層 + 原始紋理圖片顏色 來(lái)進(jìn)行混合
    gl_FragColor = mask * (1.0 - amplitude) + whiteMask * amplitude;
}

實(shí)現(xiàn)效果:

閃白.gif

毛刺濾鏡

?刺濾鏡的原理: 撕裂 + 微弱的顏?偏移兄世。
片元著色器代碼:

precision highp float;
// 紋理
uniform sampler2D Texture;
// 紋理坐標(biāo)
varying vec2 TextureCoordsVarying;
// 時(shí)間(通過(guò)uniform傳入一個(gè)時(shí)間Time)
uniform float Time;
// 隨機(jī)數(shù)
float rand(float n) {
    //fract(x),返回x的小數(shù)部分?jǐn)?shù)據(jù)
    return fract(sin(n) * 43758.5453123);
}

void main (void) {
    // 最大抖動(dòng)
    float maxJitter = 0.06;
    // 一次毛刺濾鏡的時(shí)長(zhǎng)
    float duration = 0.5;
    // 紅色顏色偏移量
    float colorROffset = 0.01;
    //綠色顏色偏移量
    float colorGOffset = -0.02;
    // 藍(lán)色顏色偏移量
    float colorBOffset = -0.035;
    
    // 時(shí)間周期[0.0,1.0];
    float time = mod(Time, duration * 2.0);
    // 振幅:[0,1];
    float amplitude = max(sin(time * (PI / duration)), 0.0);
    
    // 像素隨機(jī)偏移[-1,1]
    float jitter = rand(TextureCoordsVarying.y) * 2.0 - 1.0; // -1~1
    
    // 是否要做偏移.
    bool needOffset = abs(jitter) < maxJitter * amplitude;
    
    // 獲取紋理X值.根據(jù)needOffset,來(lái)計(jì)算它X撕裂.
    // needOffset = YES啊研,撕裂較大;
    // needOffset = NO御滩,撕裂較小.
    float textureX = TextureCoordsVarying.x + (needOffset ? jitter : (jitter * amplitude * 0.006));
    
    // 撕裂后的紋理坐標(biāo)x,y
    vec2 textureCoords = vec2(textureX, TextureCoordsVarying.y);
    
    // 顏色偏移3組顏色
    // 根據(jù)撕裂后獲取的紋理顏色值
    vec4 mask = texture2D(Texture, textureCoords);
    // 撕裂后的紋理顏色偏移
    vec4 maskR = texture2D(Texture, textureCoords + vec2(colorROffset * amplitude, 0.0));
    vec4 maskG = texture2D(Texture, textureCoords + vec2(colorGOffset * amplitude, 0.0));
    vec4 maskB = texture2D(Texture, textureCoords + vec2(colorBOffset * amplitude, 0.0));
    
    // 顏色部分發(fā)生撕裂.
    gl_FragColor = vec4(maskR.r, maskG.g, maskB.b, mask.a);
}

實(shí)現(xiàn)效果:

毛刺.gif

毛刺效果具體的思路是:我們讓每一行像素隨機(jī)偏移 -1 ~ 1 的距離(這里的 -1 ~ 1 是對(duì)于紋理坐標(biāo)來(lái)說(shuō)的)鸥拧,但是如果整個(gè) 畫面都偏移?較大的值,那我們可能都看不出原來(lái)圖像的樣子削解。所以富弦,設(shè)定?個(gè)閾值,?于這個(gè)閾值才進(jìn)行偏移氛驮,超過(guò)這個(gè)閾值則乘上?個(gè)縮小系數(shù)腕柜。
則最終呈現(xiàn)的效果是:絕?部分的行都會(huì)進(jìn)行微小的偏移,只有少量的行會(huì)進(jìn)行較?偏移矫废。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盏缤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蓖扑,更是在濱河造成了極大的恐慌唉铜,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件律杠,死亡現(xiàn)場(chǎng)離奇詭異潭流,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)俩功,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門幻枉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人诡蜓,你說(shuō)我怎么就攤上這事熬甫。” “怎么了蔓罚?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵椿肩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我豺谈,道長(zhǎng)郑象,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任茬末,我火速辦了婚禮厂榛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丽惭。我一直安慰自己击奶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布责掏。 她就那樣靜靜地躺著柜砾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪换衬。 梳的紋絲不亂的頭發(fā)上痰驱,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天证芭,我揣著相機(jī)與錄音,去河邊找鬼担映。 笑死废士,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的另萤。 我是一名探鬼主播湃密,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼四敞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拔妥,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤忿危,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后没龙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铺厨,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年硬纤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了解滓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡筝家,死狀恐怖洼裤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溪王,我是刑警寧澤腮鞍,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站莹菱,受9級(jí)特大地震影響移国,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜道伟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一迹缀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜜徽,春花似錦祝懂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至掐禁,卻和暖如春怜械,著一層夾襖步出監(jiān)牢的瞬間颅和,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工缕允, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峡扩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓障本,卻偏偏與公主長(zhǎng)得像教届,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驾霜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容