~ubuntu-branches/ubuntu/trusty/psychtoolbox-3/trusty-proposed

« back to all changes in this revision

Viewing changes to Psychtoolbox/PsychDemos/BlurredMipmapDemo.m

  • Committer: Package Import Robot
  • Author(s): Yaroslav Halchenko
  • Date: 2013-11-19 23:34:50 UTC
  • mfrom: (3.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20131119233450-f7nf92vb8qavjmk8
Tags: 3.0.11.20131017.dfsg1-3
Upload to unsable since fresh glew has arrived to sid!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
function BlurredMipmapDemo(deviceIndexOrMoviename, gazeRadius, customMipmap)
 
2
% BlurredMipmapDemo - Show blurring of live video or movies via adaptive mipmapping.
 
3
%
 
4
% This demo shows how to selectively blur regions of a live video stream
 
5
% captured from an attached camera, or a live playing movie. The method
 
6
% employed here uses a GLSL shader to select an individual blur level for
 
7
% each output pixel. Pixels close to the mouse cursor (which simulates gaze
 
8
% position, e.g., as aquired by an eyetracker) will be drawn sharp, whereas
 
9
% pixels at larger radial distance will be drawn increasingly unsharp by
 
10
% low-pass filtering them.
 
11
%
 
12
% The method of blurring here is computationally efficient and fast,
 
13
% because it generates and uses a image resolution pyramid to precompute
 
14
% different versions of the video image at different resolutions. Then the
 
15
% shader just looks up color information for each individual output pixel
 
16
% from the proper "level of detail" in the pyramid of low pass filtered
 
17
% images. The resolution pyramid is auto-generated in a fast, GPU
 
18
% accelerated way for each image by use of OpenGL "mip-mapping". This
 
19
% method uses a fixed low-pass filter for downsampling, usually a box
 
20
% filter, but the exact type of filter used is system dependent and can
 
21
% vary across different graphics cards, graphics driver versions or
 
22
% operating systems.
 
23
%
 
24
% The demo requires recent graphics hardware and won't work on old graphics
 
25
% cards.
 
26
%
 
27
% Usage:
 
28
%
 
29
% BlurredMipmapDemo([deviceIndexOrMoviename=0][, gazeRadius=25][, customMipmap=0])
 
30
%
 
31
% 'gazeRadius' Some falloff radius in pixels. Controls how quickly the
 
32
% resolution degrades with increasing distance from the cursorposition.
 
33
% Smaller values give a smaller simulated "foveal area".
 
34
%
 
35
% 'deviceIndexOrMoviename' = Optional: Either the index of the video
 
36
% capture device, or the full path to a movie file. Defaults to
 
37
% auto-selected default video source.
 
38
%
 
39
% 'customMipmap' Optional: If non-zero, use a custom shader for
 
40
% downsampling during mipmap building, instead of the relatively simple
 
41
% builtin filter of the GPU.
 
42
%
 
43
% Press any key to finish the demo.
 
44
%
 
45
 
 
46
% History:
 
47
% 28.08.2012  mk  Written.
 
48
 
 
49
% Child protection:
 
50
AssertOpenGL;
 
51
 
 
52
% Select maximum display id for output:
 
53
screenId = max(Screen('Screens'));
 
54
 
 
55
if nargin < 1 || isempty(deviceIndexOrMoviename)
 
56
    deviceIndexOrMoviename = [];
 
57
end
 
58
 
 
59
if nargin < 2 || isempty(gazeRadius)
 
60
    gazeRadius = 25;
 
61
end
 
62
 
 
63
if nargin < 3 || isempty(customMipmap)
 
64
    customMipmap = 0;
 
65
end
 
66
 
 
67
% Is it a movie file name?
 
68
if ischar(deviceIndexOrMoviename)
 
69
    % Yes: Playback the movie.
 
70
    moviename = deviceIndexOrMoviename;
 
71
    ismovie = 1;
 
72
else
 
73
    % No: Nothing or a numeric video capture deviceindex. Do videocapture.
 
74
    ismovie = 0;
 
75
end
 
76
 
 
77
if customMipmap == 0
 
78
    % Use automatic mipmap generation by GPU driver builtin method:
 
79
    dontautomip = 0;
 
80
else
 
81
    % Don't generate mipmaps automatically, roll our own downsampling:
 
82
    if ismovie
 
83
        % This is the correct flag for 'GetMovieImage':
 
84
        dontautomip = 8; 
 
85
    else
 
86
        % This is the correct flag for 'GetCapturedImage':
 
87
        dontautomip = 16;
 
88
    end
 
89
end
 
90
 
 
91
try
 
92
    % Open onscreen window with black background color:
 
93
    win = Screen('OpenWindow', screenId, 0);
 
94
    [w, h] = Screen('WindowSize', win); %#ok<*ASGLU>
 
95
    
 
96
    % Load & Create a GLSL shader for adaptive mipmap lookup:
 
97
    shaderpath = fileparts(mfilename('fullpath'));
 
98
    shader = LoadGLSLProgramFromFiles([shaderpath filesep 'BlurredMipmapDemoShader'], 1);
 
99
    
 
100
    % Bind texture unit 0 to shader as input source for the mip-mapped video image:
 
101
    glUseProgram(shader);
 
102
    glUniform1i(glGetUniformLocation(shader, 'Image'), 0);
 
103
    glUseProgram(0);
 
104
 
 
105
    % Load & Create a GLSL shader for downsampling during MipMap pyramid
 
106
    % creation. This specific example shader uses a 3-by-3 gaussian filter
 
107
    % kernel with a standard deviation of 1.0:
 
108
    mipmapshader = LoadGLSLProgramFromFiles([shaderpath filesep 'MipMapDownsamplingShader.frag.txt'], 1);
 
109
    
 
110
    if ismovie
 
111
        % Open movie and start its playback:
 
112
        movie = Screen('OpenMovie', win, moviename);
 
113
        Screen('PlayMovie', movie, 1, 1, 1);
 
114
    else
 
115
        % Open video capture device 'deviceIndex':
 
116
        grabber = Screen('OpenVideoCapture', win, deviceIndexOrMoviename);
 
117
        
 
118
        % Start video capture:
 
119
        Screen('StartVideoCapture', grabber, realmax, 1);
 
120
    end
 
121
    
 
122
    % Change cursor to a cross-hair:
 
123
    ShowCursor('CrossHair');
 
124
    
 
125
    tex = [];
 
126
    count = 0;
 
127
    t=GetSecs;
 
128
    
 
129
    % Repeat until keypress or timeout of 10 minutes:
 
130
    while ((GetSecs - t) < 600) && ~KbCheck
 
131
        % Wait for next video image or movie frame. The first '1' asks to
 
132
        % wait blocking for the next image, instead of polling. 'tex' is
 
133
        % returned for recycling to increase efficiency. The specialMode
 
134
        % flag '1' asks Screen() to return the texture as a GL_TEXTURE_2D
 
135
        % texture. This is needed for the automatic mip-mapping for
 
136
        % low-pass filtering to work:
 
137
        if ismovie
 
138
            % Get next movie frame:
 
139
            tex = Screen('GetMovieImage', win, movie, 1, [], 1 + dontautomip);
 
140
        else
 
141
            % Get next video frame:
 
142
            tex = Screen('GetCapturedImage', win, grabber, 1, tex, 1 + dontautomip);
 
143
        end
 
144
        
 
145
        % Valid 'tex'ture with new videoframe returned?
 
146
        if tex > 0
 
147
            % Yes. Get current "center of gaze" as simulated by the current
 
148
            % mouse cursor position:
 
149
            [gazeX, gazeY] = GetMouse(win);
 
150
            
 
151
            % Flip y-axis direction -- Shader has origin bottom-left, not
 
152
            % top-left as GetMouse():
 
153
            gazeY = h - gazeY;
 
154
            
 
155
            % Need to create mipmaps ourselves?
 
156
            if dontautomip
 
157
                % Yes: Use PTB's utility function for shader-based mipmap
 
158
                % generation with more control, but less performance. We
 
159
                % use 'mipmapshader' as downsampling shader, and '1' enable
 
160
                % bilinear filtering for the shader:
 
161
                CreateResolutionPyramid(tex, mipmapshader, 1);
 
162
            end
 
163
            
 
164
            % Draw new video texture from framegrabber. Apply GLSL 'shader'
 
165
            % during drawing. Use filterMode 3: This will automatically
 
166
            % generate the mipmap image resolution pyramid, then use the
 
167
            % 'shader' to adaptively lookup lowpass filtered pixels from
 
168
            % the different blur-levels of the image pyramid to simulate
 
169
            % typical foveation effect of decreasing resolution with
 
170
            % increasing distance to center of fixation. We pass gaze
 
171
            % center (gazeX, gazeY) and radius of foveation 'gazeRadius' as
 
172
            % auxParameters. auxParameters must always have a multiple of 4
 
173
            % components, so we add a zero value for padding to length 4:
 
174
            Screen('DrawTexture', win, tex, [], [], [], 3, [], [], shader, [], [gazeX, gazeY, gazeRadius, 0]);
 
175
            
 
176
            % Need to close texture if movie is played back:
 
177
            if ismovie
 
178
                Screen('Close', tex);
 
179
            end
 
180
            
 
181
            % Show it at next video refresh:
 
182
            Screen('Flip', win);
 
183
        end
 
184
        
 
185
        % Increase frame counter:
 
186
        count = count + 1;
 
187
    end
 
188
    
 
189
    % Display some timing stats:
 
190
    telapsed = GetSecs - t;
 
191
    avgfps = count / telapsed;
 
192
    fprintf('Average frames per second: %f.\n', avgfps);
 
193
    
 
194
    if ismovie
 
195
        % Stop and close movie:
 
196
        Screen('PlayMovie', movie, 0);
 
197
        Screen('CloseMovie', movie);
 
198
    else
 
199
        % Stop and close video source:
 
200
        Screen('StopVideoCapture', grabber);
 
201
        Screen('CloseVideoCapture', grabber);
 
202
    end
 
203
    
 
204
    % Close down everything else:
 
205
    Screen('CloseAll');
 
206
    
 
207
catch %#ok<*CTCH>
 
208
    % Error handling, emergency shutdown:
 
209
    sca;
 
210
    psychrethrow(psychlasterror);
 
211
end