generated from qq15725/starter-ts
-
Notifications
You must be signed in to change notification settings - Fork 1
/
create-kawase-blur-filter.ts
83 lines (74 loc) · 2.32 KB
/
create-kawase-blur-filter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { defineFilter } from './define-filter'
import animation from './shaders/animation.frag?raw'
import type { AnimationFilterOptions } from './types'
const fragmentShader = `
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform vec2 uOffset;
uniform float uTime;
uniform float uDuration;
uniform bool uIsOut;
uniform bool uLoop;
${ animation }
void main(void) {
float time = normalizeTime(uTime, uDuration, uLoop, uIsOut);
vec2 offset = vec2(uOffset.x - linear(time, 0.0, uOffset.x, uDuration), uOffset.y - linear(time, 0.0, uOffset.y, uDuration));
vec4 color = vec4(0.0);
color += texture2D(uSampler, vec2(vTextureCoord.x - offset.x, vTextureCoord.y + offset.y));
color += texture2D(uSampler, vec2(vTextureCoord.x + offset.x, vTextureCoord.y + offset.y));
color += texture2D(uSampler, vec2(vTextureCoord.x + offset.x, vTextureCoord.y - offset.y));
color += texture2D(uSampler, vec2(vTextureCoord.x - offset.x, vTextureCoord.y - offset.y));
color *= 0.25;
gl_FragColor = color;
}
`
export interface KawaseBlurFilterOptions extends AnimationFilterOptions {
blur?: number
quality?: number
}
export function createKawaseBlurFilter(options: KawaseBlurFilterOptions = {}) {
const {
blur = 10,
quality = 3,
mode = 'in',
duration = 1.8,
loop = false,
} = options
const kernels = [blur]
if (blur > 0) {
let k = blur
const step = blur / quality
for (let i = 1; i < quality; i++) {
k -= step
kernels.push(k)
}
}
const sharedUniforms = {
uIsOut: mode !== 'in',
uDuration: duration,
uLoop: loop,
}
return defineFilter(texture => {
const uvX = 1 / texture.width
const uvY = 1 / texture.height
const uOffset = []
let offset: number
if (quality === 1 || blur === 0) {
offset = kernels[0] + 0.5
uOffset[0] = offset * uvX
uOffset[1] = offset * uvY
} else {
const last = quality - 1
for (let i = 0; i < last; i++) {
offset = kernels[i] + 0.5
uOffset[0] = offset * uvX
uOffset[1] = offset * uvY
texture.registerProgram({ fragmentShader, uniforms: { ...sharedUniforms, uOffset } })
}
offset = kernels[last] + 0.5
uOffset[0] = offset * uvX
uOffset[1] = offset * uvY
}
texture.registerProgram({ fragmentShader, uniforms: { ...sharedUniforms, uOffset } })
})
}