
案例demo
1、縮放效果
實(shí)現(xiàn)原理:通過修改頂點(diǎn)坐標(biāo)和紋理坐標(biāo)的對應(yīng)關(guān)系來實(shí)現(xiàn)。
實(shí)現(xiàn)步驟

-
設(shè)定縮放的時(shí)間周期。float duration = 0.6
由于傳入的時(shí)間參數(shù)是時(shí)間戳,一直增長。通過mod求余函數(shù),對duration求余??梢詫r(shí)間限制在0.6以內(nèi)不斷循環(huán)的時(shí)間周期時(shí)間周期圖1。
時(shí)間周期圖1 -
設(shè)定縮放的振幅(最大放大多少,最小縮小多少)
這里使用正弦函數(shù)sin的值域在[-1,1]范圍內(nèi)周期變化的特性。來設(shè)置紋理振幅的周期性變化
振幅
- 紋理坐標(biāo)乘以設(shè)置的振幅,實(shí)現(xiàn)紋理坐標(biāo)的放大和縮小
頂點(diǎn)著色器代碼實(shí)現(xiàn)
attribute vec4 position;
attribute vec2 textureCoord;
varying lowp vec2 textureCoordVarying;
uniform float Time;//時(shí)間參數(shù)
const float PI = 3.1415926;
void main(){
float duration = 0.6;//時(shí)間周期(一次縮放效果的時(shí)長)
float maxAmplitude = 0.3;最大縮放幅度(振幅)
//mod 求余函數(shù) 將時(shí)間對duration取余。
//將時(shí)間變換成0.6以內(nèi)循環(huán)的時(shí)間周期[0,0.6)
float time = mod(Time,duration);
//amplitude振幅
// 引入sin函數(shù)為了得到[0,1]循環(huán)變化的值域。將的到循環(huán)變化的振幅值
// sin函數(shù)值域[-1,1],abs 取絕對值將值域變成[0,1]
//振幅范圍[1, 1+ maxAmplitude];
float amplitude = maxAmplitude * abs(sin(time * (PI / duration))) + 1.0;
textureCoordVarying = textureCoord;
// 將頂點(diǎn)坐標(biāo)xy乘以放大系數(shù)(振幅),在紋理坐標(biāo)不變的情況。就達(dá)到了縮放效果
//將頂點(diǎn)坐標(biāo)x,y進(jìn)行縮放變化,zw保持不變
gl_Position = vec4(position.x * amplitude,position.y * amplitude,position.zw);
}
2、靈魂出竅
實(shí)現(xiàn)原理:兩個(gè)層疊加。并且上面一層隨時(shí)間逐漸放大、透明度逐漸降低。

實(shí)現(xiàn)步驟
- 設(shè)置時(shí)間周期
duration,mod求余將時(shí)間戳變換值duration內(nèi)的循環(huán)的時(shí)間周期time = mod(Time,duration)。 - 獲取當(dāng)前時(shí)間時(shí)時(shí)間周期內(nèi)進(jìn)度(占比)。
progress =time/duration - 透明度歲進(jìn)度降低
alpha = 1 - progress,可以設(shè)置透明度變換的上限值alpha = (1 - progress) * maxAlpha - 紋理坐標(biāo)的放大
設(shè)置圖片放大的上限maxScale = 1.8
設(shè)置縮放比例scale = 1.0 +(maxScale - 1) * progress - 獲取放大后的紋理坐標(biāo)、放大后紋理坐標(biāo)的紋素
- 原紋理和放大后的紋理進(jìn)行顏色混合,賦值gl_FragColor
放大后的紋理weakMask(在mask的基礎(chǔ)上做了放大處理) ,原紋理mask
GLSL顏色混合方程式=mask * (1- alpha) + weakMask * alpha


片元著色器中實(shí)現(xiàn)
precision highp float;
varying lowp vec2 textureCoordVarying;
uniform sampler2D Texture;
uniform float Time;
void main(){
float duration = 0.7;//時(shí)間周期
float maxAlpha = 0.4;//透明度上限
float maxScale = 1.8;//放大倍數(shù)上限
//時(shí)間周期內(nèi)的進(jìn)度
float progress = mod(Time, duration) / duration; // 0~1
//該時(shí)間進(jìn)度下的透明度
float alpha = maxAlpha * (1.0 - progress);
//該時(shí)間進(jìn)度下的縮放比例
float scale = 1.0 + (maxScale - 1.0) * progress;
//紋理縮放變換后的紋理坐標(biāo)
// 將像素點(diǎn)的紋理坐標(biāo)x、y到紋理中點(diǎn)的距離進(jìn)行縮放(放大),保持頂點(diǎn)坐標(biāo)不變,達(dá)到向四周拉伸的效果
float weakX = 0.5 + (textureCoordVarying.x - 0.5) / scale;
float weakY = 0.5 + (textureCoordVarying.y - 0.5) / scale;
vec2 weakTextureCoords = vec2(weakX, weakY);
//紋理縮放變換的紋素
vec4 weakMask = texture2D(Texture, weakTextureCoords);
//原紋理的紋素
vec4 mask = texture2D(Texture, textureCoordVarying);
//顏色混合
gl_FragColor = mask * (1.0 - alpha) + weakMask * alpha;
}
3、抖動(dòng)濾鏡
實(shí)現(xiàn)原理:顏色偏移 + 微弱的放大效果

實(shí)現(xiàn)步驟
- 設(shè)置時(shí)間周期、進(jìn)度、縮放比例
- 計(jì)算當(dāng)前進(jìn)度下顏色偏移、縮放比例
- 獲取放大后的紋理坐標(biāo)的紋素、放大后的紋理顏色偏移后的紋素
- 從放大的紋素、偏移的紋素獲取RGBA,賦值gl_FragColor
precision highp float;
varying lowp vec2 textureCoordVarying;
uniform sampler2D Texture;
uniform float Time;
void main(){
float duration = 0.7;
float maxScale = 1.1;
//顏色偏移步長
float offset = 0.02;
float progress = mod(Time, duration) / duration; // 0~1
//顏色偏移值(0,0.02)
vec2 offsetCoords = vec2(offset, offset) * progress;
float scale = 1.0 + (maxScale - 1.0) * progress;
//放大后的紋理坐標(biāo)
vec2 ScaleTextureCoords = vec2(0.5, 0.5) + (textureCoordVarying - vec2(0.5, 0.5)) / scale;
//放大后的紋理紋素進(jìn)行顏色偏移 + offsetCoords
vec4 maskR = texture2D(Texture, ScaleTextureCoords + offsetCoords);
//放大后的紋理紋素進(jìn)行顏色偏移 - offsetCoords
vec4 maskB = texture2D(Texture, ScaleTextureCoords - offsetCoords);
// 放大后紋理坐標(biāo)的紋素
vec4 mask = texture2D(Texture, ScaleTextureCoords);
// 從3組顏色中取出RGBA顏色值,賦值gl_FragColor
// 也可以值取一個(gè)紋素偏移值和不發(fā)生偏移的紋素。方便觀察紋素偏移現(xiàn)象。
// gl_FragColor = vec4(maskR.r, mask.g, maskR.b, mask.a);
// gl_FragColor = vec4(maskB.r, mask.g, maskB.b, mask.a);
gl_FragColor = vec4(maskR.r, mask.g, maskB.b, mask.a);
}
4、閃白濾鏡
實(shí)現(xiàn)原理:添加白色圖層,白色圖層隨時(shí)間透明度進(jìn)行變化。
precision highp float;
varying lowp vec2 textureCoordVarying;
uniform sampler2D Texture;
uniform float Time;
const float PI = 3.1415926;
void main(){
//時(shí)間周期
float duration = 0.6;
float time = mod(Time, duration);
//定義白色顏色遮照
vec4 whiteMask = vec4(1.0, 1.0, 1.0, 1.0);
//振幅(縮放濾鏡相同)
float amplitude = abs(sin(time * (PI / duration)));
//紋理坐標(biāo)紋素
vec4 mask = texture2D(Texture, textureCoordVarying);
//顏色混合。白色遮照的透明度時(shí)間變化
gl_FragColor = mask * (1.0 - amplitude) + whiteMask * amplitude;
}
5、毛刺濾鏡
實(shí)現(xiàn)原理:撕裂 + 微弱的顏色偏移。讓每一行像素隨機(jī)偏移-1~1的距離(相對紋理坐標(biāo)而言)。但是如果正畫面都偏移比較大的值,可能看不出原圖片的樣子。所以設(shè)定一個(gè)閥值,小于閥值的進(jìn)行偏移,大于的乘上一個(gè)縮小系數(shù)。最終絕大部分行都會(huì)進(jìn)行微小偏移,只有少量的行進(jìn)行較大偏移。

片元著色器
precision highp float;
varying lowp vec2 textureCoordVarying;
uniform sampler2D Texture;
uniform float Time;
const float PI = 3.1415926;
float rand(float n) {
//fract(x)返回x的小數(shù)部分
//返回 sin(n) * 43758.5453123
return fract(sin(n) * 43758.5453123);
}
void main(){
float maxJitter = 0.06;//最大抖動(dòng)
float duration = 0.3;//時(shí)間周期(一次毛刺濾鏡的時(shí)長)
float colorROffset = 0.01;//紅色顏色偏移
float colorBOffset = -0.025;//綠色顏色偏移
//將傳入的時(shí)間轉(zhuǎn)換成周期
float time = mod(Time, duration * 2.0);
//amplitude 振幅。引入PI是為了使用sin函數(shù)。將amplitude 限制在1.0 ~1.3之間,隨時(shí)間變化
float amplitude = max(sin(time * (PI / duration)), 0.0);
//像素隨機(jī)偏移范圍(-1,1)
float jitter = rand(textureCoordVarying.y) * 2.0 - 1.0; // -1~1
//判斷是否需要偏移,如果jitter范圍< 最大抖動(dòng) *振幅
bool needOffset = abs(jitter) < maxJitter * amplitude;
//獲取紋理坐標(biāo)x,根據(jù)needOffset 計(jì)算x的撕裂,yes,撕裂大,no撕裂小
float textureX = textureCoordVarying.x + (needOffset ? jitter : (jitter * amplitude * 0.006));
//獲取撕裂后的紋理坐標(biāo)
vec2 textureCoords = vec2(textureX, textureCoordVarying.y);
//顏色偏移
//撕裂后紋素
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));
//顏色主要撕裂,紅色和藍(lán)色部分,所以只調(diào)整紅色
gl_FragColor = vec4(maskR.r, mask.g, maskB.b, mask.a);
}
6、幻覺濾鏡
實(shí)現(xiàn)原理:殘影效果 + 顏色偏移
殘影效果:在移動(dòng)過程中,每經(jīng)過一段時(shí)間間隔,根據(jù)當(dāng)前的位置去創(chuàng)建一個(gè)新層,并且的不透明度隨時(shí)間逐漸減弱。在一個(gè)移動(dòng)周期內(nèi)??梢钥吹胶芏嗤该鞫炔煌膶盈B加在一起,從而形成殘影的效果,殘影,讓圖片時(shí)間做圓周運(yùn)動(dòng)。
顏色偏移:物體移動(dòng)的過程是藍(lán)色在前面,紅色在后面。搜一整個(gè)過程可以理解成:在移動(dòng)的過程中,每隔一段時(shí)間,遺失了一部分紅色通道的值在原來的位置。并且這部分紅色通道的值,隨著時(shí)間偏移,會(huì)逐漸恢復(fù)。

片元著色器
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
uniform float Time;
const float PI = 3.1415926;
const float duration = 2.0;
//計(jì)算某時(shí)刻圖片的具體位置,每經(jīng)過一段時(shí)間,生成新的圖層
vec4 getMask(float time, vec2 textureCoords, float padding) {
//圓周坐標(biāo)
vec2 translation = vec2(sin(time * (PI * 2.0 / duration)),
cos(time * (PI * 2.0 / duration)));
//紋理坐標(biāo) = 紋理坐標(biāo) + 圓周坐標(biāo) * 偏移量
vec2 translationTextureCoords = textureCoords + padding * translation;
//獲取新圖層的坐標(biāo)
vec4 mask = texture2D(Texture, translationTextureCoords);
return mask;
}
//計(jì)算某時(shí)刻創(chuàng)建的圖層、當(dāng)前時(shí)刻的透明度
float maskAlphaProgress(float currentTime, float hideTime, float startTime) {
float time = mod(duration + currentTime - startTime, duration);
return min(time, hideTime);
}
void main (void) {
//獲取時(shí)間周期
float time = mod(Time, duration);
//放大倍數(shù)
float scale = 1.2;
//偏移量
float padding = 0.5 * (1.0 - 1.0 / scale);
//放大后的紋理坐標(biāo)
vec2 textureCoords = vec2(0.5, 0.5) + (TextureCoordsVarying - vec2(0.5, 0.5)) / scale;
//隱藏時(shí)間
float hideTime = 0.9;
//時(shí)間間隔
float timeGap = 0.2;
//注意:只保留了紅色的透明的通道值?;糜X效果殘留紅色
//新圖層 -- R色透明度
float maxAlphaR = 0.5; // max R
//新圖層 -- G色透明度
float maxAlphaG = 0.05; // max G
//新圖層 -- B色透明度
float maxAlphaB = 0.05; // max B
//獲取新的圖層坐標(biāo)
vec4 mask = getMask(time, textureCoords, padding);
float alphaR = 1.0; // R
float alphaG = 1.0; // G
float alphaB = 1.0; // B
//最終圖層顏色
vec4 resultMask = vec4(0, 0, 0, 0);
for (float f = 0.0; f < duration; f += timeGap) {
float tmpTime = f;
//獲取0~2s內(nèi)所獲取的運(yùn)動(dòng)后的紋理坐標(biāo)
vec4 tmpMask = getMask(tmpTime, textureCoords, padding);
//某時(shí)刻創(chuàng)建的層。在當(dāng)前時(shí)刻紅綠藍(lán)的透明度
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;
//累計(jì)每一層每個(gè)通道乘以透明度顏色通道
resultMask += vec4(tmpMask.r * tmpAlphaR,
tmpMask.g * tmpAlphaG,
tmpMask.b * tmpAlphaB,
1.0);
//透明度遞減
alphaR -= tmpAlphaR;
alphaG -= tmpAlphaG;
alphaB -= tmpAlphaB;
}
//最終的顏色+=紅綠藍(lán) * 透明度
resultMask += vec4(mask.r * alphaR, mask.g * alphaG, mask.b * alphaB, 1.0);
gl_FragColor = resultMask;
}

