/usr/share/psychtoolbox-3/PsychDemos/ContrastModulatedNoiseTheElegantStyleDemo.m is in psychtoolbox-3-common 3.0.14.20170103+git6-g605ff5c.dfsg1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | function ContrastModulatedNoiseTheElegantStyleDemo(noisesize, staticnoise)
% ContrastModulatedNoiseTheElegantStyleDemo([noisesize=512] [, staticnoise=0])
%
% This demo shows how to render contrast modulated noise efficiently on
% current state of the art graphics hardware by use of the Psychtoolbox
% imaging pipeline and high precision framebuffers.
%
% A rectangular image with random noise of size
% 'noisesize' by 'noisesize' pixels is created, then drawn to the display.
%
% We use alpha-blending tricks to modulate the contrast of the noise in
% realtime. In this demo you can move the mouse pointer to drag around a
% "modulation disk" of 50 pixels diameter. Noise inside the disk has a
% different contrast 'fgcontrast' from the rest of the image, which has a
% contrast of 'bgcontrast' (see top of code for fgcontrast and bgcontrast).
%
% You can press the cursor left and cursor right keys to decrement or
% increment the contrast inside the disk in steps of 0.01 units. Press
% cursor up key to set the inside disk contrast equal to outside disk
% contrast. Press ESCAPE key to finish the demo.
%
% The optional 'staticnoise' flag - if set to 1 - will render a static
% noise image instead of one that changes at each frame. That's faster
% because one doesn't need to recreate the noise texture each frame.
%
% How this works? Basically we use standard Screen 2D drawing commands to
% draw a "contrast values weight map" into the alpha-channel, so the
% alpha-channel encodes contrast values between 0.0 and 1.0.
% Then we draw a noise texture of fixed contrast into the framebuffer
% and the alpha-blending hardware takes care of modulating the
% contrast of the drawn noise texture with the values from the
% alpha-channel.
%
% Hardware requirements: ATI Radeon X-1000 or later, NVidia Geforce 6000 or
% later. Recommended is Radeon HD2000/3000/... or Geforce-8000/9000/...
% hardware for maximum fun!
%
% The allowable contrast values for standard 2D drawing commands are
% limited to the range 0.0 to 1.0 on MacOS/X, they are not limited on
% MS-Windows or GNU/Linux. Precision is set to 16bpc float, ie. about 3
% digits behind the decimal point or 1024 discriminable levels. On the most
% recent ATI HD-2000 and NVidia Geforce 8000 hardware one can lift this limit
% to 32bpc float -- 6.5 digits or about 8 million discriminable levels by a
% one-line code change in this script ;-)
% History:
% 5.9.2007 Written (MK).
% Running on PTB-3?
AssertOpenGL;
if nargin < 1
noisesize = [];
end
if isempty(noisesize)
noisesize = 512;
end
if nargin < 2
staticnoise = [];
end
if isempty(staticnoise)
staticnoise = 0;
end
bgcontrast = 0.2;
fgcontrast = 0.4;
% Assign control keys: Cursor Left and Right for increasing/decreasing
% contrast of the noise:
KbName('UnifyKeyNames');
leftArrow = KbName('LeftArrow');
rightArrow = KbName('RightArrow');
upArrow = KbName('UpArrow');
escape = KbName('ESCAPE');
% Open onscreen window on screen with maximum id:
screenid=max(Screen('Screens'));
try
% Open onscreen window: We request a 32 bit per color component
% floating point framebuffer if it supports alpha-blendig. Otherwise
% the system shall fall back to a 16 bit per color component
% framebuffer:
PsychImaging('PrepareConfiguration');
PsychImaging('AddTask', 'General', 'FloatingPoint32BitIfPossible');
[win, winRect] = PsychImaging('OpenWindow', screenid);
% We use a normalized color range from now on. All color values are
% specified as numbers between 0.0 and 1.0, instead of the usual 0 to
% 255 range. This is more intuitive:
Screen('ColorRange', win, 1, 0);
% Fill the whole onscreen window with a neutral 50% intensity
% background color and an alpha channel value of 'bgcontrast'.
% This becomes the clear color. After each Screen('Flip'), the
% backbuffer will be cleared to this neutral 50% intensity gray
% and a default 'bgcontrast' background noise contrast level:
Screen('FillRect', win, [0.5 0.5 0.5 bgcontrast]);
i=0;
tonset = [];
% Create first noisematrix outside loop:
noisematrix = randn(noisesize);
% Initially place the mouse cursor at the center of the window:
[x, y] = RectCenter(winRect);
SetMouse(x, y, win);
HideCursor;
% Initially sync us to retrace:
Screen('Flip', win);
% Main stimulus drawing loop:
while 1
% Increment framecounter:
i=i+1;
% If staticnoise is set to 1 then we only generate the noise
% texture once -- This way we can disentangle "noise creation
% overhead" from actual drawing overhead:
if i==1 || staticnoise == 0
% Convert Matlab 'noisematrix' to 16 bpc floating point noise texture:
noisetex = Screen('MakeTexture', win, noisematrix, [], [], 1);
end
% Disable alpha-blending, so we can just overwrite the framebuffer
% with our new pixels:
Screen('Blendfunction', win, GL_ONE, GL_ZERO);
% Now we overdraw some regions of the onscreen windows alpha-channel
% with our "modulation" image - a image that contains alpha values
% which encode a different contrast 'fgcontrast'. After this drawing op,
% the alpha-channel will contain the final "contrast modulation landscape":
Screen('DrawDots', win, [x y], 50, [0.5 0.5 0.5 fgcontrast], [], 1);
% On some graphics hardware + operating system combos, 'DrawDots'
% is not able to draw round dots when Screen('ColorRange', win, 1,
% 1); is used. In such cases, just use 'FillOval' to draw round
% dots:
% Screen('FillOval', win, [0.5 0.5 0.5 fgcontrast], OffsetRect([0 0 50 50], x-25, y-25));
% Now we draw the noise texture and use alpha-blending of
% the drawn noise color pixels with the destination alpha-channel,
% thereby multiplying the incoming color values with the stored
% alpha values -- effectively a contrast modulation. The GL_ONE
% means that we add the final contrast modulated noise pixels to
% the current content of the window == the neutral gray background.
Screen('Blendfunction', win, GL_DST_ALPHA, GL_ONE);
% The extra zero at the end forcefully disables bilinear filtering. This is
% not strictly neccessary on correctly working hardware, but an extra
% precaution to make sure that the noise values are blitted
% one-to-one into the offscreen window:
Screen('DrawTexture', win, noisetex, [], [], [], 0);
% At this point, the final image should be ready in the backbuffer
% of our onscreen window. Ready to flip it onscreen...
% Cleanup: Release our noise texture in the dynamic-noise case were
% we recreate one for each drawn frame:
if ~staticnoise
Screen('Close', noisetex);
end
% Tell PTB that all drawing commands are done now. This allows
% the graphics hardware to perform all drawing and image processing
% in parallel while we execute Matlab code for non-graphics related
% stuff, in our case random noise creation, keyboard and mouse
% queries:
Screen('DrawingFinished', win);
% Now all the non-Screen() stuff:
if ~staticnoise
% Generate a noisesize x noisesize matrix of random noise with mean zero,
% stddev 1.0 for use in the next loop iteration:
noisematrix = randn(noisesize);
end
% Keyboard queries:
[isdown secs keycode] = KbCheck;
if isdown
if keycode(escape)
break;
end
if keycode(leftArrow)
fgcontrast = max(0, fgcontrast - 0.01);
end
if keycode(rightArrow)
fgcontrast = min(1, fgcontrast + 0.01);
end
if keycode(upArrow)
fgcontrast = bgcontrast;
end
end
% Query mouse position: This will be the center of our "modulation disk":
[x, y] = GetMouse(win);
% Ready. Request stimulus onset:
tonset(i) = Screen('Flip', win);
% Ready. Next loop iteration:
end
% One final flip:
Screen('Flip', win);
% Done. Close screen and finish:
ShowCursor;
sca;
% Compute avg. computation time for redraw:
avgredrawtime = mean(diff(tonset)) * 1000
%plot(diff(tonset));
% Done.
return;
catch
% Error. Close screen, show cursor, rethrow error:
ShowCursor;
sca;
psychrethrow(psychlasterror);
end
|