I need to draw an animated texture with many parameters. All of these parameters (matrix 10x200) will be changed in each frame.
I try to send them to fragment shader as uniforms with glUniform*fv
but it seems it is too much. If I try to use fewer (let's say just 2 circles) everything works:
Matlab/Psychtoolbox-3 code:
%%
circ1pos = [100 100]; circ2pos = [200 200]; % circle positions
circ1color = [1 0 0]; circ2color = [0 1 0]; % circle colors
%%
global GL
PsychDefaultSetup(2);
Screen('Preference', 'SkipSyncTests', 1);
screenid = max(Screen('Screens'));
win=PsychImaging('OpenWindow', screenid, 0.5);
texShader = LoadGLSLProgramFromFiles('./circle.frag', 1);
glUseProgram(texShader);
glUniform2fv( glGetUniformLocation(texShader, 'circ1pos'),...
1, single(circ1pos));
glUniform3fv( glGetUniformLocation(texShader, 'circ1color'),...
1, single(circ1color));
glUniform2fv( glGetUniformLocation(texShader, 'circ2pos'),...
1, single(circ2pos));
glUniform3fv( glGetUniformLocation(texShader, 'circ2color'),...
1, single(circ2color));
glUseProgram(0);
tex=Screen('SetOpenGLTexture', win, [], 0, GL.TEXTURE_RECTANGLE_EXT, 1000, 1000, 1, texShader);
Screen('DrawTexture',win,tex);
Screen('Flip', win);
Fragment shader:
#version 120
uniform vec3 circ1color;
uniform vec3 circ2color;
uniform vec2 circ1pos;
uniform vec2 circ2pos;
void main()
{
vec4 out_color = vec4(0,0,0,0);
vec2 pos = gl_TexCoord[0].xy;
// plot first circle
float x0 = circ1pos.x;
float y0 = circ1pos.y;
float is_inside = (pos.x-x0)*(pos.x-x0)+(pos.y-y0)*(pos.y-y0)-1600;
out_color=vec4(-circ1color*is_inside,1);
// plot second circle
x0 = circ2pos.x;
y0 = circ2pos.y;
is_inside = (pos.x-x0)*(pos.x-x0)+(pos.y-y0)*(pos.y-y0)-1600;
out_color= out_color + vec4(-circ2color*is_inside,1);
gl_FragColor= out_color;
}
I thought about using the sampler2d
class to send the whole matrix, but I could not find any good explanation for Matlab/Psychtoolbox-3 and GLSL version 120.
If terms of my example - my problem is to send parameters of the large number of circles into fragment shader.
Update:
In this related question there is some discussion about passing the arrays to fragment shader. It seems I may use only 1D textures, as I need to use OpenGL2.1.
But the problem is that I could not find a normal explanation for glCopyTexSubImage2D()
usage in Matlab/Psychtoolbox-3.
I tried the following:
arrXY = [100 200 200 100];
texture = glGenTextures(1);
glBindTexture(GL.TEXTURE_1D_ARRAY, texture);
glTexImage1D(GL.TEXTURE_1D, 0, GL.R32F, 4, 0, GL.RED, GL.FLOAT, single(arrXY));
But now I could not understand how to use these data in my fragment shader.
glTexImage2D variant:
I try to use glTexImage2D
:
data = [1,0.5,0.4];
%%
global GL
PsychDefaultSetup(2);
Screen('Preference', 'SkipSyncTests', 1);
screenid = max(Screen('Screens'));
win=PsychImaging('OpenWindow', screenid, 0.5);
texShader = LoadGLSLProgramFromFiles('./circle2.frag', 1);
glUseProgram(texShader);
texture = glGenTextures(1);
glBindTexture(GL.TEXTURE_1D_ARRAY, texture);
glTexImage2D(GL.TEXTURE_1D_ARRAY, 0, GL.R32F, 3,1, 0, GL.RED, GL.FLOAT, single(data));
glUseProgram(0);
tex=Screen('SetOpenGLTexture', win, [], 0, GL.TEXTURE_RECTANGLE_EXT, 1000, 1000, 1, texShader);
Screen('DrawTexture',win,tex);
Screen('Flip', win);
circle2.frag
#version 120
uniform sampler2D data;
void main()
{
vec3 texel = texture2D(data,vec2(0,0));
gl_FragColor= vec4(texel[0],0,0,0);
}
with this code I have 2 problems:
1) if I define texel
like anything else, not vec4
shader did not compile:Incompatible types in initialization (and no available implicit conversion)
2) I expect the red color of the screen as a result of shader, but it is black.
What am I doing wrong?