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
|
function ProceduralSmoothedApertureSineGratingDemo(benchmark)
% ProceduralSmoothedApertureSineGratingDemo([benchmark=0])
%
% This demo demonstrates fast drawing of smooth apertured sine wave gratings
% using procedural shaders. It only works on hardware with support for the GLSL
% shading language, vertex- and fragment-shaders.
% History:
% 12-Dec-2017 modified from ProceduralGaborDemo.m (Ian Andolina).
% 08-Nov-2018 Clarify interaction of alpha-blending with useAlpha and radius=inf,
% and the sine modulation that is conditionally also applied to the
% alpha-channel for radius=inf or useAlpha=false. (MK)
% Default to mode 0 - Just a nice demo.
if nargin < 1
benchmark = 0;
end
% Setup defaults and unit color range:
PsychDefaultSetup(2);
% Disable synctests for this quick demo:
oldSyncLevel = Screen('Preference', 'SkipSyncTests', 2);
% Choose screen with maximum id - the secondary display:
screenid = max(Screen('Screens'));
% Open a window
PsychImaging('PrepareConfiguration');
win = PsychImaging('OpenWindow', screenid, 0.5);
% Initial stimulus params for the grating:
virtualSize = 600;
phase = 0;
freq = .04;
tilt = 225;
contrast = 0.5;
% radius of the disc edge
radius = virtualSize / 2;
% smoothing sigma in pixel
sigma = 55;
% use alpha channel for smoothing?
useAlpha = true;
% smoothing method: cosine (0) or smoothstep (1) or inverse smoothstep (2)
smoothMethod = 1;
% Two ways to achieve the same visual appearance for edge smoothing/fadeout,
% once via premultiplication of the hull function, once via alpha blending.
% Note: If we want consistent visual appearance for radius == inf vs. non-inf,
% then we must not enable alpha blending for the radius == inf case, as the
% 'useAlpha' flag only applies for finite radius! For infinite radius, 'useAlpha'
% would get ignored, which would mean to apply the sine wave signal to the alpha
% channel as well as the color channel, so with alpha blending enabled, the sine
% wave signal would get applied twice while forming the final stimulus!
if useAlpha && ~isinf(radius)
% Enable alpha-blending, store the sine wave signal in color, use alpha
% channel to store the hull function for fadeout and apply it via blending.
Screen('BlendFunction', win, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA');
else
% No alpha-blending: Hull function for fadeout is directly applied via
% multiplication to the sine wave signal, directly attenuating it.
% As the sine signal * hull function also applies to the alpha channel,
% you will find a edge attenuated sine wave in the alpha channel as well,
% which could be used for complex alpha blending applications iff you use
% blending and masking creatively, ie. typically with blend functions other
% than the ones used in this demo.
Screen('BlendFunction', win, 'GL_ONE', 'GL_ZERO');
end
% Build a procedural gabor texture for a grating with a RGB color offset of 0.5 -- a 50% gray.
sinetex = CreateProceduralSmoothedApertureSineGrating(win, virtualSize, virtualSize,...
[.5 .5 .5 1], radius, [], sigma, useAlpha, smoothMethod);
% Draw the grating once, just to make sure the gfx-hardware is ready for the
% benchmark run below and doesn't do one time setup work inside the
% benchmark loop:
Screen('DrawTexture', win, sinetex, [], [], tilt, [], [], [], [], [], [phase, freq, contrast, 0]);
% Perform initial flip to gray background and sync us to the retrace:
vbl = Screen('Flip', win);
tstart = vbl;
count = 0;
% Animation loop
while GetSecs < tstart + 10
count = count + 1;
% update values:
phase = phase + 5;
% Draw the grating:
Screen('DrawTexture', win, sinetex, [], [], tilt, [], [], [], [], [], [phase, freq, contrast, 0]);
if benchmark > 0
% Go as fast as you can without any sync to retrace and without
% clearing the backbuffer -- we want to measure gabor drawing speed,
% not how fast the display is going etc.
Screen('Flip', win, 0, 2, 2);
else
% Go at normal refresh rate for good looking gabors:
Screen('Flip', win);
end
end
% A final synced flip, so we can be sure all drawing is finished when we
% reach this point; print some stats
tend = Screen('Flip', win);
avgfps = count / (tend - tstart);
fprintf('\nPresented a total of %i frames at ~%.2g FPS...\n',count,avgfps);
% Close window, release all ressources:
sca
% Restore old settings for sync-tests:
Screen('Preference', 'SkipSyncTests', oldSyncLevel);
|