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..
|