Hello everyone,
I am stuck with a supposedly simple application: implement a “paintbrush” tool. Basically, what I do is read the mouse coordinates and paint the respective pixel according to some colour.
As a first approach I decided to use a glsl shader that received a texture, updated it with the new coloured pixel (when painting) and finally render the final result to the same texture (using the FBO). I got into a problem where the only painted pixel was the last painted one. I think this issue has to do with reported in “GLSL Common Mistakes” with the title “Sampling and Rendering to the Same Texture”.
Then i decided to use two textures:
- GL_TEXTURE0 is associated to the FBO
- GL_TEXTURE1 is a copy of the FBO texture after the final render
The algorithm is as follows:
I send to the shader the GL_TEXTURE1, add the new coloured pixel to that texture and then I update this same texture with a copy of the fresh GL_TEXTURE0 that is associated to the FBO.
I am sure that GL_TEXTURE1 content (the one that enters the shader) carries the last image present in the FBO (I already created bitmap files for debugging purposes).
Somehow I cannot make it work: the viewport is always “clean” with no coloured pixels. Can someone help me?
Here’s part of the code:
[1ST PASS: rendering to GL_TEXTURE_0]
_framebuffer->set_active(); //INFO: GL_TEXTURE_0 is associated to this FBO
_shader->enable();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1, 1);
glViewport(0,0,(GLsizei) w, (GLsizei) h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glUniform2f(glGetUniformLocation(_shader->get_program_id(),“position”), mouse_pos.x, mouse_pos.y);
glUniform3f(glGetUniformLocation(_shader->get_program_id(),“color”),r,g,b);
glUniform1i(glGetUniformLocationARB(_shader->get_program_id(),“texture”), 1);
// here I deliver the fbo copied texture to the shader
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,_texture1);
glBegin(GL_QUADS);
glVertex3f(0,0,-1);
glVertex3f(w,0,-1);
glVertex3f(w,h,-1);
glVertex3f(0,h,-1);
glEnd();
_shader->disable();
_framebuffer->set_active(false);
[VERTEX SHADER]
varying vec4 tex_coord;
void main()
{
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
tex_coord = gl_TextureMatrix[0] * gl_Vertex;
}
[FRAG SHADER]
uniform vec2 position;
uniform vec3 color;
uniform sampler2D texture;
varying vec4 tex_coord;
void main()
{
if(tex_coord.s == position.x && tex_coord.t == position.y)
{
gl_FragColor = vec4(color.x,color.y,color.z, 1.0);
}
else
{
gl_FragColor = texture2D(texture,tex_coord.st);
}
}
[2ND PASS: final render and copy from GL_TEXTURE0 to GL_TEXTURE1]
glBindTexture(GL_TEXTURE_2D,_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
glBegin(GL_QUADS);
glTexCoord2d(0,0);glVertex3f(0,0,-1);
glTexCoord2d(1,0);glVertex3f(w,0,-1);
glTexCoord2d(1,1);glVertex3f(w,h,-1);
glTexCoord2d(0,1);glVertex3f(0,h,-1);
glEnd();
glBindTexture(GL_TEXTURE_2D,0);
CopyTextureCPU(_texture, _texture2, w, h );