OpenGL水波紋效果
glsl水波紋效果,可使用shadertoy直接運行。sin和iTime配合得到水波紋mask,通過mask流動變化得到水波紋效果。
腳本1
#iChannel0 "file://./bg0.jpg"
// 水波紋中心點
const vec2 center = vec2(0.5, 0.5);
// 水波紋速度
const float speed = 2.5;
// 水波紋強度
const float intensity = 36.0;
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// 計算uv
vec2 uv = fragCoord.xy / iResolution.xy;
// 計算center到各個uv的值
float dst = distance(uv, center);
// fragColor = vec4(vec3(dst), 1.0);
// 計算水波紋
// sin將對這個範圍限制到[-1, 1]
// dst範圍是[0, sqrt(2)]
// intensity可以理解爲波紋數
// iTime的引入讓一個點可以從[-1, 1]的變化
// speed是速度
// 可以理解爲dst*intensity是初始波紋, iTime的引入讓波紋動了起來
float wave = sin(sqrt(dst)*intensity-iTime*speed);
// fragColor = vec4(vec3(wave), 1.0);
// 接下來使用da和偏移的db來mix, 也就是水波紋白色區域取db, 黑色區域取da
vec3 da = texture2D(iChannel0, uv).rgb;
vec3 db = texture2D(iChannel0, uv-vec2(0.01)).rgb;
vec3 res = mix(da, db, wave*wave); // wave*wave範圍爲[0, 1]
fragColor = vec4(res, 1.0);
}
腳本2
#iChannel1 "file://./bg0.jpg"
#iChannel2 "file://./mask.png"
const float intensity = 0.02;
const float speed = 10.0;
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv1 = fragCoord.xy / iResolution.xy;
// mask的uv流動
vec2 uv2 = uv1 + vec2(0.0, iTime * speed / 100.0);
// 由於vs中不能對iChannel2進行repeat, 所以進行一個求餘操作
uv2 = mod(uv2, 1.0);
// 得到mask的流動
vec2 wave = texture2D(iChannel2, uv2).xy;
// wave範圍是[0, 1], intensity限制了範圍, 錯位得取像素
uv1 = uv1 + wave*intensity;
fragColor = texture(iChannel1, uv1);
}
腳本3
#iChannel0 "file://./bg0.jpg"
const float speed = 1.0;
const float intensity = 6.0;
float wave(vec2 pos, float t, float freq, float numWaves, vec2 center) {
float d = length(pos - center);
d = log(1.0 + exp(d));
return 1.0/(1.0+20.0*d*d) * sin(2.0*3.1415*(-numWaves*d + t*freq));
}
float height(vec2 pos, float t) {
float w;
w = wave(pos, t, speed, intensity, vec2(0.5, -0.5));
w += wave(pos, t, speed, intensity, -vec2(0.5, -0.5));
return w;
}
vec2 normal(vec2 pos, float t) {
return vec2(height(pos - vec2(0.01, 0), t) - height(pos, t),
height(pos - vec2(0, 0.01), t) - height(pos, t));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord.xy / iResolution.xy;
vec2 uvn = 2.0*uv - vec2(1.0);
uv += normal(uvn, iTime);
fragColor = texture2D(iChannel0, uv);
}