/usr/share/psychtoolbox-3/PsychDemos/ExpandingRingsDemo.m is in psychtoolbox-3-common 3.0.9+svn2579.dfsg1-1.
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 | function ExpandingRingsDemo(ringtype)
% ExpandingRingsDemo([ringtype=0]) -- Generate an "expanding rings"
% stimulus by use of GLSL shaders and Psychtoolbox procedural textures.
%
% This demo illustrates the use of "procedural textures" with Psychtoolbox.
% A procedural texture is a texture that is not directly represented by an
% image matrix in memory, but the image content of the texture is generated
% on the fly during drawing of the texture by means of a small algorithm -
% a shader. The shader implements some mathematical formula or model which
% is evaluated to generate image content, or it reads content of a data
% matrix and transforms it into a picture. Psychtoolbox supports both,
% purely virtual textures of unlimited size that are purely algorithmically
% generated, and hybrid textures where an algorithm transforms the textures
% content into something to be drawn.
%
% The algorithm has to be implemented by a GLSL shader program - a vertex
% shader, geometry shader, fragment shader or any combination of them. The
% shader program is read from a file, compiled and then attached to the
% texture at texture creation time. Procedural textures only work with
% graphics hardware that has sufficiently advanced support for (at least)
% hardware fragment shaders.
%
% This demo implements a procedural texture which shows a set of rings that
% can expand and move. The shader gets attached to a purely virtual
% texture. The texture is drawn via the standard Screen('DrawTexture')
% command -- your graphics processor generates the image content of the
% stimulus on the fly during drawing of the texture via execution of the
% shader at each output pixel location.
%
% The optional 'ringtype' parameter allows to select between different ring
% shapes. Default type is zero:
%
% 0 = Hard transitions between red and yellow rings.
% 1 = Transitions are modeled as a smooth sine wave, softly fading from
% yellow to red and back.
%
% History:
% 19.05.2007 Written. (MK)
% 24.04.2011 Updated to support 'ringtype' parameter and sine-wave rings. (MK)
% 12.06.2011 Updated to use ProceduralShadingAPI for cleaner M-file code. (MK)
% Acquire a handle to OpenGL, so we can use OpenGL commands in our code:
global GL;
% Make sure this is running on OpenGL Psychtoolbox:
AssertOpenGL;
if nargin < 1 || isempty(ringtype)
ringtype = 0;
end
% Choose screen with maximum id - the secondary display:
screenid = max(Screen('Screens'));
% Open a fullscreen onscreen window on that display, choose a background
% color of 128 = gray with 50% max intensity:
win = Screen('OpenWindow', screenid, 128);
% Switch color specification to use the 0.0 - 1.0 range instead of the 0 -
% 255 range. This is more natural for these kind of stimuli:
Screen('ColorRange', win, 1);
% Query window size: Need this to define center and radius of expanding
% disk stimulus:
[tw, th] = Screen('WindowSize', win);
% Load the 'ExpandingRingsShader' fragment program from file, compile it,
% return a handle to it:
rshader = [PsychtoolboxRoot 'PsychDemos/ExpandingRingsShader.vert.txt'];
if ringtype == 0
expandingRingShader = LoadGLSLProgramFromFiles({ rshader, [PsychtoolboxRoot 'PsychDemos/ExpandingRingsShader.frag.txt'] }, 1);
% Width of a single ring (radius) in pixels:
ringwidth = 20;
else
expandingRingShader = LoadGLSLProgramFromFiles({ rshader, [PsychtoolboxRoot 'PsychDemos/ExpandingSinesShader.frag.txt'] }, 1);
% Width of a single ring (radius) / Period of a single color sine wave in pixels:
ringwidth = 200;
end
% Create a purely virtual texture 'ringtex' of size tw x th virtual pixels, i.e., the
% full size of the window. Attach the expandingRingShader to it, to define
% its "appearance":
ringtex = Screen('SetOpenGLTexture', win, [], 0, GL.TEXTURE_RECTANGLE_EXT, tw, th, 1, expandingRingShader);
% Bind the shader: After binding it, we can setup some constant parameters
% for our stimulus, so called GLSL 'uniform' variables. These are
% parameters that are constant during the whole session, or at least only
% change infrequently. They are set outside the fast stimulus rendering
% loop and potentially optimized by the graphics driver for fast execution:
glUseProgram(expandingRingShader);
% Set the 'RingCenter' parameter to the center position of the ring
% stimulus [tw/2, th/2]:
glUniform2f(glGetUniformLocation(expandingRingShader, 'RingCenter'), tw/2, th/2);
% Done with setup, disable shader. All other stimulus parameters will be
% set at each Screen('DrawTexture') invocation to allow fast dynamic change
% of the parameters during each stimulus redraw:
glUseProgram(0);
% Define first and second ring color as RGBA vector with normalized color
% component range between 0.0 and 1.0:
firstColor = [1 0 0 1];
secondColor = [1 1 0 1];
% Initial shift- and radius value is zero: We start with a point in the
% center of the screen which will then expand and scroll by one pixel at
% each redraw until it fills the whole screen, continuing to scroll
% periodically:
shiftvalue = 0;
count = 0;
% Retrieve monitor refresh duration:
ifi = Screen('GetFlipInterval', win);
% Perform initial flip to gray background and sync us to the retrace:
vbl = Screen('Flip', win);
ts = vbl;
% Animation loop: Run until keypress:
while ~KbCheck
% Increase shift and radius of stimulus:
shiftvalue = shiftvalue + 1;
radius = shiftvalue;
count = count + 1;
% Draw the stimulus with its current parameter settings. We simply draw
% the procedural texture as any other texture via 'DrawTexture'. We
% leave all draw settings to their defaults, except the base drawing
% colors, which in our case defines the colors of the rings and the
% ringWidth, Radius and Shift parameters:
% The vector with additional parameters must have a length which is a
% multiple of four. Therefore - as we only have 7 parameters here - we
% pad the vector with an additional meaningless zero value to end up
% with a total length of 8 vector components.
%
% We use 'firstColor' for the even rings, 'secondColor' for the odd
% rings.
Screen('DrawTexture', win, ringtex, [], [], [], [], [], firstColor, [], [], [secondColor(1), secondColor(2), secondColor(3), secondColor(4), shiftvalue, ringwidth, radius, 0]);
% Request stimulus onset at next video refresh:
vbl = Screen('Flip', win, vbl + ifi/2);
end
% Done. Print some fps stats:
avgfps = count / (vbl - ts);
fprintf('Average redraw rate in Hz was: %f\n', avgfps);
% Close window, release all ressources:
Screen('CloseAll');
|