Newer
Older
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
function [ fix_duration, mouse_x, mouse_y, fix_x, fix_y] = currentTrial(img, delay, filter, w, wRect)
try
% Setup default aperture size.
ms=200;
% Fovea contains filtered image
foveaimage = filterImage(img, filter);
% Periphery contains original image
peripheryimage = img;
% Build texture for fovea
foveatex=Screen('MakeTexture', w, foveaimage);
tRect=Screen('Rect', foveatex);
% Build texture for periphery
nonfoveatex=Screen('MakeTexture', w, peripheryimage);
[ctRect, dx, dy]=CenterRect(tRect, wRect);
% Set cursor to center and hide it
[a,b] = RectCenter(wRect);
SetMouse(a,b,screenNumber);
HideCursor;
buttons = 0;
% Make this program important
%priorityLevel=MaxPriority(w);
%Priority(priorityLevel);
% Wait until all keys on keyboard are released:
KbReleaseWait;
% Init old mouse position
mxold=0;
myold=0;
% Init fixation duration
fix_duration = 0;
% We create a two layers Luminance + Alpha matrix for use as transparency
% (or mixing weights) mask: Layer 1 (Luminance) is filled with luminance
% value 1.0 aka white - the ones() function does this nicely for us, by
% first filling both layers with 1.0:
[x,y] = meshgrid(-ms:ms, -ms:ms);
maskblob = ones(2*ms+1, 2*ms+1, 2);
% Layer 2 (Transparency aka Alpha) is now filled/overwritten with a gaussian
% transparency/mixing mask.
xsd = ms / 2.2;
ysd = ms / 2.2;
maskblob(:,:,2) = 1 - exp(-((x / xsd).^2) - ((y / ysd).^2));
% Build a single transparency mask texture:
masktex = Screen('MakeTexture', w, maskblob);
% Show image
imageTexture = Screen('MakeTexture', w, img);
Screen('DrawTexture', w, imageTexture);
Screen('Flip', w);
% Init stillTime. stillTime is used to measure the time without
% movement > distance threshold
stillTime = 0;
% Init vectors for mouse coordinates
mouse_x = [];
mouse_y = [];
% Init vectors for fixation point coordinates
fix_x = [];
fix_y = [];
% Init switch. If we already have an image blurred at the fixation
% point, we only want to redraw it if there is a movement > distance
% threshold. Otherwise, we want to stay the blur in place to record
% seccadic movements
isBlur = 0;
while 1
% Query current mouse cursor position
[mx, my, buttons]=GetMouse;
% Record mouse coordinates
mouse_x(end+1) = mx;
mouse_y(end+1) = my;
% Calculate euclidean distance between old and new position
dist = eDist(mxold, myold, mx, my)
% We only want "big" movements to be considert a change of fixatoin
% point. Smaller movements will be recorded as seccadic
if dist > 15
stillTime = 0;
isBlur = 0;
else
stillTime = stillTime + 0.001;
if stillTime >= delay & isBlur == 0
isBlur = 1;
fix_x(end+1) = mx;
fix_y(end+1) = my;
myrect=[mx-ms my-ms mx+ms+1 my+ms+1];
dRect = ClipRect(myrect,ctRect);
sRect=OffsetRect(dRect, -dx, -dy);
% Valid destination rectangle?
if ~IsEmptyRect(dRect)
% Yes! Draw image for current frame:
% Step 1: Draw the alpha-mask into the backbuffer. It
% defines the aperture for foveation: The center of gaze
% has zero alpha value. Alpha values increase with distance from
% center of gaze according to a gaussian function and
% approach 1.0 at the border of the aperture...
% Actual use of masktex to define transitions/mix:
% First clear framebuffer to backgroundcolor, not using
% alpha blending (== GL_ONE, GL_ZERO), enable all channels
% for writing [1 1 1 1], so everything gets cleared to good
% starting values:
Screen('BlendFunction', w, GL_ONE, GL_ZERO, [1 1 1 1]);
Screen('FillRect', w, backgroundcolor);
% Then keep alpha blending disabled and draw the mask
% texture, but *only* into the alpha channel. Don't touch
% the RGB color channels but use the channel mask
% [R G B A] = [0 0 0 1] to only enable the alpha-channel
% for drawing into it:
Screen('BlendFunction', w, GL_ONE, GL_ZERO, [0 0 0 1]);
Screen('DrawTexture', w, masktex, [], myrect);
% Step 2: Draw peripheral image. It is only/increasingly drawn where
% the alpha-value in the backbuffer is 1.0 or close, leaving
% the foveated area (low or zero alpha values) alone:
% This is done by weighting each color value of each pixel
% with the corresponding alpha-value in the backbuffer
% (GL_DST_ALPHA). Disable alpha channel writes via [1 1 1 0], so
% alpha mask stays untouched and only RGB color channels are
% affected:
Screen('BlendFunction', w, GL_DST_ALPHA, GL_ZERO, [1 1 1 0]);
Screen('DrawTexture', w, nonfoveatex, [], ctRect);
% Step 3: Draw foveated image, but only/increasingly where the
% alpha-value in the backbuffer is zero or low: This is
% done by weighting each color value with one minus the
% corresponding alpha-value in the backbuffer
% (GL_ONE_MINUS_DST_ALPHA).
Screen('BlendFunction', w, GL_ONE_MINUS_DST_ALPHA, GL_ONE, [1 1 1 0]);
Screen('DrawTexture', w, foveatex, sRect, dRect);
Screen('Flip', w);
end
end
end
% Keep track of last gaze position:
mxold=mx;
myold=my;
% We wait 1 ms each loop-iteration so that we
% don't overload the system in realtime-priority:
WaitSecs('YieldSecs', 0.001);
% Abort demo on keypress our mouse-click:
if KbCheck | find(buttons)
break;
end
end
catch
%this "catch" section executes in case of an error in the "try" section
%above. Importantly, it closes the onscreen window if its open.
sca;
ShowCursor;
Priority(0);
psychrethrow(psychlasterror);
end %try..catch..
% The same command which closes onscreen and offscreen windows also
% closes textures.
sca;
ShowCursor;
Priority(0);
return;
end