File: DriftingMaskedGratingTutorial.m

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (300 lines) | stat: -rw-r--r-- 11,902 bytes parent folder | download | duplicates (3)
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
function DriftingMaskedGratingTutorial(angle, cyclespersecond, f, drawmask)
% function DriftDemo2(angle, cyclespersecond, f, drawmask)
% ___________________________________________________________________
%
% Display an animated grating using the new Screen('DrawTexture') command.
% In the OS X Psychtoolbox Screen('DrawTexture') replaces
% Screen('CopyWindow'). The demo will stop after roughly 20 seconds have
% passed or after the user hits a key.
%
% This demo illustrates how to draw an animated grating online by use of
% only one grating texture. We create one texture with a static sine
% grating. In each successive frame we only draw a rectangular subregion of
% the sine-texture onto the screen, basically showing the texture through
% an aperture. The subregion - and therefore our "aperture" is shifted each
% frame, so we create the impression of a moving grating.
%
% The demo also shows how to use alpha-blending for masking the grating
% with a gaussian transparency mask (a texture with transparency layer).
%
% And finally, we demonstrate rotated drawing, as well as how to emulate
% the old OS-9 'WaitBlanking' command with the new 'Flip' command.
%
% Parameters:
%
% angle = Angle of the grating with respect to the vertical direction.
% cyclespersecond = Speed of grating in cycles per second.
% f = Frequency of grating in cycles per pixel.
% drawmask = If set to 1, then a gaussian aperture is drawn over the grating
%
% CopyWindow vs. DrawTexture:
%
% In the OS 9 Psychtoolbox, Screen ('CopyWindow") was used for all
% time-critical display of images, in particular for display of the movie
% frames in animated stimuli. In contrast, Screen('DrawTexture') should not
% be used for display of all graphic elements,  but only for  display of
% MATLAB matrices.  For all other graphical elements, such as lines,  rectangles,
% and ovals we recommend that these be drawn directly to the  display
% window during the animation rather than rendered to offscreen  windows
% prior to the animation.
%
% _________________________________________________________________________
% 
% see also: PsychDemos, MovieDemo

% HISTORY
%  6/7/05    mk     Adapted from Allen Ingling's DriftDemoOSX.m 

if nargin<4
    % By default, we mask the grating by a gaussian transparency mask:
    drawmask=1;
end

if nargin<3
    % Grating cycles/pixel
    f=0.05;
end

if nargin<2
    % Speed of grating in cycles per second:
    cyclespersecond=1;
end

if nargin<1
    % Angle of the grating: We default to 30 degrees.
    angle=30;
end

movieDurationSecs=20;   % Abort demo after 20 seconds.
texsize=100;            % Half-Size of the grating image.

% Screen('Preference', 'SkipSyncTests', 1);

try
	% This script calls Psychtoolbox commands available only in OpenGL-based 
	% versions of the Psychtoolbox. (So far, the OS X Psychtoolbox is the
	% only OpenGL-base Psychtoolbox.)  The Psychtoolbox command AssertPsychOpenGL will issue
	% an error message if someone tries to execute this script on a computer without
	% an OpenGL Psychtoolbox
	AssertOpenGL;
	
	% Get the list of screens and choose the one with the highest screen number.
	% Screen 0 is, by definition, the display with the menu bar. Often when 
	% two monitors are connected the one without the menu bar is used as 
	% the stimulus display.  Chosing the display with the highest dislay number is 
	% a best guess about where you want the stimulus displayed.  
	screens=Screen('Screens');
	screenNumber=max(screens);
	
    % Find the color values which correspond to white and black.  Though on OS
	% X we currently only support true color and thus, for scalar color
	% arguments,
	% black is always 0 and white 255, this rule is not true on other platforms will
	% not remain true on OS X after we add other color depth modes.  
	white=WhiteIndex(screenNumber);
	black=BlackIndex(screenNumber);
	gray=(white+black)/2;
	if round(gray)==white
		gray=black;
	end
	inc=white-gray;
	
	% Open a double buffered fullscreen window and draw a gray background 
	% to front and back buffers:
	[w screenRect]=Screen('OpenWindow',screenNumber, gray);

    % Enable alpha-blending:
    Screen('BlendFunction', w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    % Show initial gray screen:
    Screen('Flip', w);

    % Calculate parameters of the grating:
    p=ceil(1/f);  % pixels/cycle    
    fr=f*2*pi;
    visiblesize=2*texsize+1;

    % Create one single static grating image:
    [x,y]=meshgrid(-2*texsize:2*texsize + p, -texsize:texsize);
    grating=gray + inc*cos(fr*x);

    % Store grating in texture:
    gratingtex=Screen('MakeTexture', w, grating);

    % Create a single gaussian transparency mask and store it to a texture:
    mask=ones(2*texsize+1, 2*texsize+1, 2) * gray;
    [x,y]=meshgrid(-1*texsize:1*texsize,-1*texsize:1*texsize);
    mask(:, :, 2)=white * (1 - exp(-((x/45).^2)-((y/45).^2)));
    masktex=Screen('MakeTexture', w, mask);
    
    % Query duration of monitor refresh interval:
    ifi=Screen('GetFlipInterval', w);
    
    waitframes = 1;
    waitduration = waitframes * ifi;
    
    % Translate requested speed of the grating (in cycles per second)
    % into a shift value in "pixels per frame", assuming given
    % waitduration: This is the amount of pixels to shift our "aperture" at
    % each redraw:
    shiftperframe= cyclespersecond * p * waitduration;
    
    Screen('TextSize', w, 24);
    
    % Slide 1: The static grating texture:
    [xp yp] = DrawFormattedText(w, 'Step 1: Generate a single static texture which shows the periodic grating pattern: The texture must contain at least two full periods of the pattern.\nPress a key to continue.\n\n', 0, 20, 0, 50);
    cmd = 'gratingtex = Screen(''MakeTexture'', w, gratingmatrix);\nScreen(''DrawTexture'', w, gratingtex);';
    [xp yp] = DrawFormattedText(w, cmd, xp, yp, 255);
    Screen('DrawTexture', w, gratingtex);
    Screen('Flip', w);

    GetClicks(w);
    
    % Slide 2: Cut out an aperture from the texture, and render it to a
    % dstRect of same size:

    autodrift = 0;
    xoffset = 0;
    angle = 0;
    i=0;

    while (1)
        [x y buttons] = GetMouse(w);

        if buttons(1) && ~autodrift
            xoffset = x - 100;
            xoffset = max(xoffset, 0);
            xoffset = min(xoffset, 2*texsize);
        end
              
        if buttons(2)
            autodrift = mod(autodrift+1, 3);
            while buttons(2)
                [x y buttons] = GetMouse(w);
            end
        end
        
        if autodrift >= 1
            % Shift the grating by "shiftperframe" pixels per frame:
            xoffset = mod(i*shiftperframe,p);
            i=i+1;
            
            if buttons(1)
                angle = x / RectWidth(screenRect) * 360.0;
            end
        end
                
        if autodrift == 0
            [xp yp] = DrawFormattedText(w, 'Step 2: Cut out a rectangular subregion ''srcRect'' from the texture and draw it to the screen area ''dstRect'' of same size. The texture is shown through an aperture.\nMoving the aperture creates apparent smooth motion. - Try it with the mouse!\nPress a key to continue.\n\n', 0, 20, 0, 50);
        else
            if autodrift >= 1
                [xp yp] = DrawFormattedText(w, 'Step 3: Horizontal shifting of the cut-out aperture region ''srcRect'' creates a nice drifting pattern. Subpixel accurate movements are possible due to hardware bilinear texture interpolation.\nPress a key to continue.\n\n', 0, 20, 0, 50);
                if angle~=0
                    [xp yp] = DrawFormattedText(w, '\nIt is also possible to rotate the ''dstRect'' destination region by some angle to create a rotated grating.\n', 0, yp, 0, 50);
                end
            end
            if autodrift == 2
                [xp yp] = DrawFormattedText(w, '\nOne can mask the ''dstRect'' destination region with a ''transparency mask'' texture by use of alpha-blending.\n', 0, yp, 0, 50);                
            end
        end
        
        cmd = 'Screen(''DrawTexture'', w, gratingtex, ';
        yp=yp+20;
        [xp] = DrawFormattedText(w, cmd, 0, yp, 255);
        cmd = 'srcRect, ';
        [xp] = DrawFormattedText(w, cmd, xp, yp, [255 0 0]);
        cmd = 'dstRect';
        [xp] = DrawFormattedText(w, cmd, xp, yp, [255 255 0]);
        if angle==0
            cmd = ');\n';
        else
            cmd = [', ' num2str(angle) ');\n'];
        end
        [xp yp] = DrawFormattedText(w, cmd, xp, yp, 255);
        
        % Draw static grating texture:
        dstRect = OffsetRect(Screen('Rect', gratingtex), 100, yp + 50);
        Screen('DrawTexture', w, gratingtex, [], dstRect);

        % Define shifted srcRect that cuts out the properly shifted rectangular
        % area from the texture:
        srcRect=[xoffset 0 xoffset + visiblesize visiblesize];
        apertRect = OffsetRect(srcRect, 100, yp + 50);
        Screen('FrameRect', w, [255 0 0], apertRect, 4);
        % Definition of the drawn rectangle on the screen:
        dstRect=[0 0 visiblesize visiblesize];
        dstRect=OffsetRect(dstRect, 600, yp + 150);
        Screen('DrawLine', w, [255 0 0 128], apertRect(1), apertRect(2), dstRect(1), dstRect(2), 4);
        Screen('DrawLine', w, [255 0 0 128], apertRect(3), apertRect(2), dstRect(3), dstRect(2), 4);
        Screen('DrawLine', w, [255 0 0 128], apertRect(1), apertRect(4), dstRect(1), dstRect(4), 4);
        Screen('DrawLine', w, [255 0 0 128], apertRect(3), apertRect(4), dstRect(3), dstRect(4), 4);
        % Draw grating texture:
        Screen('DrawTexture', w, gratingtex, srcRect, dstRect, angle);
        Screen('FrameRect', w, [255 255 0], dstRect, 4);
        
        if autodrift == 2
            maskRect = CenterRectOnPoint(dstRect, x, y);
            xp = 0;
            cmd = sprintf('Screen(''DrawTexture'', w, masktex, [], [%i %i %i %i], %f);\n', maskRect(1), maskRect(2), maskRect(3), maskRect(4), angle);
            [xp] = DrawFormattedText(w, cmd, xp, yp, 255);
            Screen('DrawTexture', w, masktex, [], maskRect, angle);
        end
        
        if KbCheck
            break;
        end
        
        Screen('Flip', w);
    end
        
    KbReleaseWait;
        
    % Perform initial Flip to sync us to the VBL and for getting an initial
    % VBL-Timestamp for our "WaitBlanking" emulation:
    vbl=Screen('Flip', w);

    i=0;
    dstRect = CenterRect(dstRect, screenRect);
    
    % Animationloop:
    while(1)
        % Shift the grating by "shiftperframe" pixels per frame:
        xoffset = mod(i*shiftperframe,p);
        i=i+1;
        
        % Define shifted srcRect that cuts out the properly shifted rectangular
        % area from the texture:
        srcRect=[xoffset 0 xoffset + visiblesize visiblesize];
        
        % Draw grating texture, rotated by "angle":
        Screen('DrawTexture', w, gratingtex, srcRect, dstRect, angle);

        if drawmask==1
            % Draw gaussian mask over grating: We need to subtract 0.5 from
            % the real size to avoid interpolation artifacts that are
            % created by the gfx-hardware due to internal numerical
            % roundoff errors when drawing rotated images:
            Screen('DrawTexture', w, masktex, [0 0 visiblesize visiblesize], dstRect, angle);
        end

        angle = angle + 0.1;
        
        % Flip 'waitframes' monitor refresh intervals after last redraw.
        vbl = Screen('Flip', w, vbl + (waitframes - 0.5) * ifi);

        % Abort demo if any key is pressed:
        if KbCheck
            break;
        end
    end

    %The same commands wich close onscreen and offscreen windows also close
	%textures.
	sca;

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;
    psychrethrow(psychlasterror);
end %try..catch..