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
|
function [id, rect, shader] = CreateProceduralColorGrating(windowPtr, width, height, ...
color1, color2, radius)
% [id, rect, shader] = CreateProceduralColorGrating(windowPtr, width,
% height [, color1=[1 0 0]] [, color2=[0 1 0]] [, radius=0])
%
% A procedural color grating shader that can generate either sinusoidal or
% square gratings varying between two colors.
%
%
% INPUT VALUES:
%
% * width, height = "virtual size" of the GLSL shader.
% * color1, color2 = two colors for the grating peaks to vary between. When
% running (see ProceduralColorGratingDemo), you can pass baseColor parameter,
% from which color1 and color2 will be modulated via the contrast parameter.
% When contrast is 0, then color1 and color2 are the same as baseColor. As
% contrast increases each color is mixed with baseColor until at contrast 1
% the grating peaks are color1 and color2 exactly. Color mixing uses
% OpenGL's mix command.
% * radius = optional hard-edged circular mask sized in pixels.
%
%
% RETURN VALUES:
%
% * id = texture pointer.
% * rect = rect describing the size and shape of the texture.
% * shader = the GLSL shader, useful if you want to use glUniform commands to
% modify color 1, color2 or radius after texture creation.
%
%
% DRAWING MODIFIERS:
%
% When drawing this shader using Screen('DrawTexture|s'), you can pass
% additional values:
%
% * baseColor is the base color from which color1 and color2 are mixed.
% * contrast is the mixing amount from baseColor to color1 and color2.
% * sigma is a smoothing value, when sigma == -1 a sinusoidal grating is
% produced; and when sigma >= 0 a square wave grating is produced using sigma
% value of smoothing at the edge.
%
%
% TEXTURE DETAILS:
%
% Color blending (blending each color to the baseColor, and then blending
% with each other) uses GLSL mix function; mix performs a linear
% interpolation between x and y using a to weight between them. The return
% value is computed as: $x \times (1 - a) + y \times a$. See
% <http://docs.gl/sl4/mix> for more details.
%
% Smoothing uses GLSL smoothstep function that uses hermite interpolation.
% A small amount of smoothing for squarewave grating edges can reduce
% jumping artifacts when squarewave gratings are drifted. See
% <http://docs.gl/sl4/smoothstep> for more details.
%
%
% See also: CreateProceduralSineGrating, CreateProceduralSineSquareGrating
% History:
% 06/06/2014 ima created by Ian Max Andolina <http://github.com/iandol>, licenced under the MIT Licence
global GL;
AssertGLSL;
if nargin < 1 || isempty(windowPtr)
error('You must provide a PTB window pointer!');
end
if nargin < 2 || isempty(width)
width = 500;
end
if nargin < 3 || isempty(height)
height = width;
end
if nargin < 4 || isempty(color1)
color1 = [1 0 0 1];
elseif length(color1) == 3
color1 = [color1 1]; %add alpha
elseif length(color1) ~= 4
warning('color1 must be a 4 component RGBA vector [red green blue alpha], resetting color1 to red!');
color1 = [1 0 0 1];
end
if nargin < 5 || isempty(color2)
color2 = [0 1 0 1];
elseif length(color2) == 3
color2 = [color2 1]; %add alpha
elseif length(color2) ~= 4
warning('color2 must be a 4 component RGBA vector [red green blue alpha], resetting color2 to green!');
color2 = [0 1 0 1];
end
if nargin < 6 || isempty(radius)
radius = 0;
end
% Switch to windowPtr OpenGL context:
Screen('GetWindowInfo', windowPtr);
% Load shader:
shader = LoadGLSLProgramFromFiles('ColorGratingShader', 1);
% Setup shader:
glUseProgram(shader);
glUniform2f(glGetUniformLocation(shader, 'center'), width/2, height/2);
glUniform4f(glGetUniformLocation(shader, 'color1'), color1(1),color1(2),color1(3),color1(4));
glUniform4f(glGetUniformLocation(shader, 'color2'), color2(1),color2(2),color2(3),color2(4));
if radius>0
glUniform1f(glGetUniformLocation(shader, 'radius'), radius);
end
glUseProgram(0);
% Create a purely virtual procedural texture 'id' of size width x height virtual pixels.
% Attach the shader to it to define its appearance:
id = Screen('SetOpenGLTexture', windowPtr, [], 0, GL.TEXTURE_RECTANGLE_EXT, width, height, 1, shader);
% Query and return its bounding rectangle:
rect = Screen('Rect', id);
|