PDA

View Full Version : FBO copy as input texture



YeYe_
09-03-2010, 05:24 PM
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 );

Alfonse Reinheart
09-03-2010, 07:16 PM
Then i decided to use two textures:

I'll assume that the function you're using to combine the incoming color with the color of the texel in the output is too complicated to simply use blending for. Otherwise, you really should use blending.


- GL_TEXTURE0 is associated to the FBO
- GL_TEXTURE1 is a copy of the FBO texture after the final render

The "GL_TEXTURE0" should not be bound to the context. It should be attached to the FBO and specifically not bound with glBindTexture. Only the other texture should be bound as a texture.

Also, since you're just going to be copying this image to another texture, there's no need for the FBO at all. You could just render to the default framebuffer, copy to your texture, and you're done.


CopyTextureCPU(_texture, _texture2, w, h );

What does this function do? It should just call glCopyTexSubImage2d.

YeYe_
09-05-2010, 01:23 PM
Hi again,
Alfonse, thanks for your help.
Currently I am using a quite simple function for combining the incoming color with the current one (as you can see in the fragment shader above). But that's because I still can't make it work - my plans are to use the shader to make a beautiful spray painting effect.

After Alfonse's advices, I've changed the algorithm:
- disabled the FBO
- I am now using only 1 texture
- I am now using glCopyTexSubImage2d insted of my function "CopyTextureCPU"

Unfortunately, I am still having the same problem... Please check out the following screenshots:

[WHAT SHOULD HAPPEN]
http://www.geekconcept.com/download/what_should_happen.jpg

[WHAT IS HAPPENING]
http://www.geekconcept.com/download/what_is_happening.jpg

Does it have to do with this?

http://www.opengl.org/wiki/GLSL_:_common_mistakes#Sampling_and_Rendering_to_t he_Same_Texture

Alfonse Reinheart
09-05-2010, 06:29 PM
my plans are to use the shader to make a beautiful spray painting effect.

And what is it about this spray painting effect that makes it unworkable with blending?


[WHAT IS HAPPENING]

Is that the start point or the end point? And are you clearing the framebuffer after every pixel?


Does it have to do with this?

You disabled your FBO, so you cannot possibly be rendering to a texture.