-
Notifications
You must be signed in to change notification settings - Fork 0
/
drifting_gabor.html
128 lines (103 loc) · 4.66 KB
/
drifting_gabor.html
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<!DOCTYPE html>
<html>
<head>
<script src="https://pixijs.download/release/pixi.js"></script>
</head>
<body></body>
<script>
const app = new PIXI.Application({ backgroundColor: 0x309930 });
document.body.appendChild(app.view);
const gabor_width = 500;
// create a null image element
const img_element = document.createElement('img');
img_element.width = gabor_width;
img_element.height = gabor_width;
const gabor_sprite = PIXI.Sprite.from(img_element)
// center the sprite's anchor point
gabor_sprite.anchor.set(0.5);
gabor_sprite.x = app.screen.width / 2;
gabor_sprite.y = app.screen.height / 2;
// This program is based on
// (a) the vertex shader of Psychtoolbox/PsychOpenGL/PsychGLSLShaders/BasicGaborShader.vert.txt
// https://github.com/Psychtoolbox-3/Psychtoolbox-3/blob/master/Psychtoolbox/PsychOpenGL/PsychGLSLShaders/BasicGaborShader.vert.txt
// and (b) the fragment shader of Psychtoolbox/PsychOpenGL/PsychGLSLShaders/BasicGaborShader.frag.txt
// https://github.com/Psychtoolbox-3/Psychtoolbox-3/blob/master/Psychtoolbox/PsychOpenGL/PsychGLSLShaders/BasicGaborShader.frag.txt
//
// In this program, the vertex shader is embedded in the fragment shader for simplicity.
const fragmentSrc = `
precision mediump float;
uniform float Contrast;
uniform float Phase;
uniform float angle_in_degrees; // tilt
uniform float spatial_freq;
uniform float SpaceConstant;
uniform float disableNorm;
uniform float disableGauss;
uniform float modulateColor_R;
uniform float modulateColor_G;
uniform float modulateColor_B;
uniform float modulateColor_Alpha;
uniform float offset_R;
uniform float offset_G;
uniform float offset_B;
uniform float offset_Alpha;
uniform float centerX;
uniform float centerY;
uniform float contrastPreMultiplicator;
uniform float min_validModulationRange;
uniform float max_validModulationRange;
void main() {
const float twopi = 2.0 * 3.141592654;
const float sqrtof2pi = 2.5066282746;
/* Conversion factor from degrees to radians: */
const float deg2rad = 3.141592654 / 180.0;
float Angle = deg2rad * angle_in_degrees;
float FreqTwoPi = spatial_freq * twopi;
float Expmultiplier = -0.5 / (SpaceConstant * SpaceConstant);
float mc = disableNorm + (1.0 - disableNorm) * (1.0 / (sqrtof2pi * SpaceConstant));
vec3 modulateColor = vec3(modulateColor_R, modulateColor_G, modulateColor_B);
vec3 baseColor = modulateColor * mc * Contrast * contrastPreMultiplicator;
vec2 pos = gl_FragCoord.xy - vec2(centerX, centerY);
/* Compute (x,y) distance weighting coefficients, based on rotation angle: */
vec2 coeff = vec2(cos(Angle), sin(Angle)) * FreqTwoPi;
/* Evaluate sine grating at requested position, angle and phase: */
float sv = sin(dot(coeff, pos) + Phase);
/* Compute exponential hull for the gabor: */
float ev = disableGauss + (1.0 - disableGauss) * exp(dot(pos, pos) * Expmultiplier);
/* Multiply/Modulate base color and alpha with calculated sine/gauss */
/* values, add some constant color/alpha Offset, assign as final fragment */
/* output color: */
vec4 Offset = vec4(offset_R, offset_G, offset_B, offset_Alpha);
// Be careful not to change the transparency. Note that the type of the baseColor valuable is vec3 not vec4.
gl_FragColor = vec4(baseColor * clamp(ev * sv, min_validModulationRange, max_validModulationRange), modulateColor_Alpha) + Offset;
}`
const uniforms = {
Contrast: 20,
Phase: 0,
angle_in_degrees: -60,
spatial_freq: 0.05,
SpaceConstant: 30,
disableNorm: 0,
disableGauss: 0,
modulateColor_R: 1.0,
modulateColor_G: 1.0,
modulateColor_B: 1.0,
modulateColor_Alpha: 1.0,
offset_R: 0.5,
offset_G: 0.5,
offset_B: 0.5,
offset_Alpha: 0.0,
centerX: app.screen.width / 2,
centerY: app.screen.height / 2,
contrastPreMultiplicator: 1,
min_validModulationRange: -2,
max_validModulationRange: 2,
}
const myFilter = new PIXI.Filter(null, fragmentSrc, uniforms)
app.stage.addChild(gabor_sprite);
gabor_sprite.filters = [myFilter]
app.ticker.add((delta) => {
gabor_sprite.filters[0].uniforms.Phase += 0.1;
});
</script>
</html>