GLSL - FBO - render to texture - Image Processing

Started by
9 comments, last by furrymaster 13 years, 9 months ago
Hi all,

I'm currently trying to implement in OpenGL image processing algorithms.

I would like to successively use several shaders in order to perform several filters (Sobel Gaussian,...).
I understood that to do thius I had to render to texture thanks to a FBO. I read a lot of things about that, and wrote a code. But I'm not getting the result I expected.

For the moment, I'm just trying to use two shaders. So, I have an original image which is the input of my first shader. Then, I want to render the output of the shader to a texture which will then be the input of my second shader (pingpong technique). And finally, I want to display the output of the second shader.

But as result, I'm getting the original image.

My code is the following:



/******************** Shaders Function *******************************/
void setupShaders(char *vert, char *frag, GLuint p) {
GLuint v, f;
char *vs = NULL,*fs = NULL;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead(vert);
fs = textFileRead(frag);
const char * ff = fs;
const char * vv = vs;
glShaderSource(v, 1, &vv, NULL);
glShaderSource(f, 1, &ff, NULL);
free(vs);free(fs);
glCompileShader(v);
glCompileShader(f);
p = glCreateProgram();
glAttachShader(p,f);
glAttachShader(p,v);
glLinkProgram(p);
glUseProgram(p);
}
/******************** Texture Function ***********************************/
void setupTexture(void) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
/******************** Quad Drawing Function ******************************/
void ShaderDraw(void){
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(0.0, height, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(width, height, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(width, height, 0.0);
glEnd();
}

/******************** Initialization Function ***************************/
void init(void)
{
//Checking GLSL
glewInit();
if (glewIsSupported("GL_VERSION_2_0"))
printf("Ready for OpenGL 2.0\n");
else {
printf("OpenGL 2.0 not supported\n");
exit(1);
}

// Init
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
}
/******************** Display Function **********************************/
void display(void)
{
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-4.0, -4.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-4.0, 4.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(4.0, 4.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(4.0, -4.0, 0.0);
glEnd();

glFlush();
glDisable(GL_TEXTURE_2D);
}
/******************** Reshape Function *********************************/
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -7.0);
}
/******************** Main Function *************************************/
int main(int argc, char** argv)
{
// Glut Initialisation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
// Window Generation
glutInitWindowSize(1000,800);
glutInitWindowPosition(100, 100);
glutCreateWindow("Night Vision");

// Initialisation Function
init();

// Downloading Image
data = cLoadBitmap("lena.bmp", &height, &width);
checkGLErrors ("Downloading Image");

int read_tex = 0;
int write_tex = 1;

// Generating Texture
glEnable(GL_TEXTURE_2D);
glGenTextures(2, texImg);
// Init Texture0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texImg[read_tex]);
setupTexture();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
checkGLErrors ("InitTexture0");
// Init Texture1
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texImg[write_tex]);
setupTexture();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
checkGLErrors ("InitTexture1");

// Setup Framebuffer Object
GLuint fb;
glGenFramebuffersEXT(1, &fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
checkGLErrors ("Framebuffer->fb");

GLenum att_point[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
glBindTexture(GL_TEXTURE_2D, texImg[read_tex]);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, att_point[read_tex], GL_TEXTURE_2D, texImg[read_tex], 0);
glBindTexture(GL_TEXTURE_2D, texImg[write_tex]);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, att_point[write_tex], GL_TEXTURE_2D, texImg[write_tex], 0);
checkFramebufferStatus();

//set the write texture as output buffer for the shader
glDrawBuffer(att_point[write_tex]);

// create, init and enable the shader
setupShaders("filter.vert", "sobel_filter_3.frag", p1);
checkGLErrors ("Shaders 1");
// attach the input texture(read texture) to the first texture unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texImg[read_tex]);
GLuint texLoc;
texLoc = glGetUniformLocation(p1,"tex");
glUniform1i(texLoc, 0);
// draw a square with the texture on it so to perform the computation
ShaderDraw();

// swap the buffers
read_tex = 1;
write_tex = 0;

// Delete program 1
glDeleteProgram(p1);

// set the write texture as output buffer for the shader
glDrawBuffer(att_point[write_tex]);
// create, init and enable the shaders
setupShaders("filter.vert", "gaussian7.frag", p2);
checkGLErrors ("Shaders 2");
// attach the input texture(read texture) to the first texture unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texImg[read_tex]);
texLoc = glGetUniformLocation(p2,"tex");
glUniform1i(texLoc, 0);
// draw a square with the texture on it so to perform the computation
ShaderDraw();

// Delete program 2 & disable the FBO
glDeleteProgram(p2);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glUseProgram(0);

// Bind the texture to display
glBindTexture(GL_TEXTURE_2D,texImg[0]);

// Glut Functions: Display, Reshape, Keyboard
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
// Calling Main
glutMainLoop();
return 0;
}


Does someone have an idea of what is wrong???
I really need some help!

Thanks
Advertisement
Can you show us the source of your Shaders?
Thanks for your interest.

My vertex shader is:

void main() {

gl_TexCoord[0] = gl_MultiTexCoord0;

gl_Position = ftransform();

}

My fragment shaders are :

Sobel_filter_3:

#define KERNEL_SIZE 9
uniform sampler2D tex;
ivec2 image_size = textureSize(tex, 0);
const float kernel_h[KERNEL_SIZE] = {
1, 0, -1,
2, 0, -2,
1, 0, -1
};
const float kernel_v[KERNEL_SIZE] = {
1, 2, 1,
0, 0, 0,
-1, -2, -1
};
const float step_w = 1.0/image_size[0];
const float step_h = 1.0/image_size[1];
const vec2 offset[KERNEL_SIZE] = {
vec2(-step_w, -step_h), vec2(0.0, -step_h), vec2(step_w, -step_h),
vec2(-step_w, 0.0), vec2(0.0, 0.0), vec2(step_w, 0.0),
vec2(-step_w, step_h), vec2(0.0, step_h), vec2(step_w, step_h)
};
void main(void)
{
int i = 0;
vec4 sum_h = vec4(0.0);
vec4 sum_v = vec4(0.0);
vec4 sum = vec4(0.0);
vec4 two = vec4(2.0);

for( i=0; i<KERNEL_SIZE; i++ )
{
vec4 tmp = texture2D(tex, gl_TexCoord[0].st + offset);
sum_h += tmp * kernel_h / 2;
sum_v += tmp * kernel_v / 2;
}
sum = sqrt(pow(sum_h,two) + pow(sum_v,two));
gl_FragColor = sum ;
}

Gaussian7:

#define KERNEL_SIZE 49
uniform sampler2D tex;
ivec2 image_size = textureSize(tex, 0);
const float kernel_h[KERNEL_SIZE] = {
1, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 2, 2, 1,
1, 2, 3, 4, 3, 2, 1,
1, 2, 4, 8, 4, 2, 1,
1, 2, 3, 4, 3, 2, 1,
1, 2, 2, 2, 2, 2, 1,
1, 1, 1, 1, 1, 1, 1
};
const float step_w = 1.0/image_size[1];
const float step_h = 1.0/image_size[0];

const vec2 offset[KERNEL_SIZE] = {
vec2(-3*step_w, -3*step_h), vec2(-2*step_w, -3*step_h), vec2(-step_w, -3*step_h), vec2(0.0, -3*step_h), vec2(step_w, -3*step_h), vec2(2*step_w, -3*step_h), vec2(3*step_w, -3*step_h),
vec2(-3*step_w, -2*step_h), vec2(-2*step_w, -2*step_h), vec2(-step_w, -2*step_h), vec2(0.0, -2*step_h), vec2(step_w, -2*step_h), vec2(2*step_w, -2*step_h), vec2(3*step_w, -2*step_h),
vec2(-3*step_w, -1*step_h), vec2(-2*step_w, -1*step_h), vec2(-step_w, -1*step_h), vec2(0.0, -1*step_h), vec2(step_w, -1*step_h), vec2(2*step_w, -1*step_h), vec2(3*step_w, -1*step_h),
vec2(-3*step_w, 0.0), vec2(-2*step_w, 0.0), vec2(-step_w, 0.0), vec2(0.0, 0.0), vec2(step_w, 0.0), vec2(2*step_w, 0.0), vec2(3*step_w, 0.0),
vec2(-3*step_w, 1*step_h), vec2(-2*step_w, 1*step_h), vec2(-step_w, 1*step_h), vec2(0.0, 1*step_h), vec2(step_w, 1*step_h), vec2(2*step_w, 1*step_h), vec2(3*step_w, 1*step_h),
vec2(-3*step_w, 2*step_h), vec2(-2*step_w, 2*step_h), vec2(-step_w, 2*step_h), vec2(0.0, 2*step_h), vec2(step_w, 2*step_h), vec2(2*step_w, 2*step_h), vec2(3*step_w, 2*step_h),
vec2(-3*step_w, 3*step_h), vec2(-2*step_w, 3*step_h), vec2(-step_w, 3*step_h), vec2(0.0, 3*step_h), vec2(step_w, 3*step_h), vec2(2*step_w, 3*step_h), vec2(3*step_w, 3*step_h)
};

void main(void)
{
int i = 0;
vec4 sum_h = vec4(0.0);
vec4 sum_v = vec4(0.0);
vec4 sum = vec4(0.0);
vec4 two = vec4(2.0);

for( i=0; i<KERNEL_SIZE; i++ )
{
vec4 tmp = texture2D(tex, gl_TexCoord[0].st + offset);
sum_h += tmp * kernel_h / 100;
sum_h.a = 1.0;
}
gl_FragColor = sum_h;
}

Try making things simpler by creating a basic shader program that always sets the gl_FragColor to red or something to verify that your shader programs are executing properly.
My shaders are working separately. I tried them with a code without fbo and they are working.
I also tried this code with simple shaders (glFragColor = vec4(1.0, 0.0, 0.0, 0.0)), and i'm still getting the original image.
Quote:vec4(1.0, 0.0, 0.0, 0.0)

Thats because u give invisible color(alpha==0) :)
give there more than 0.0 (maybe 0.5 or 1.0)
If I helped you rate me
With glFragColor = vec4(1.0, 0.0, 0.0, 1.0) for both shader, I'm still getting the original image as final result except in the top right corner which is red.

I have no idea of what is wrong and I really need some help!!
U propaby modify somewhere your frag color because with only this:
///////////VERT:void main() {gl_TexCoord[0] = gl_MultiTexCoord0;gl_Position = ftransform();}//////////////FRAGvoid main(){   gl_FragColor=vec4(1,0,0,1);}

You should have all quad red.

Next:
Quote:glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(0.0, height, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(width, height, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(width, height, 0.0);//<<<<MISTAKE
glEnd();

There should be 0

Another quastion: do u have cull face on CCW or CW?

Next one:
where are u setting up mipmapping?

Edit:
what GL and FBO errors do u get?

Edit2:
plz stop using glut... It`s so old
If I helped you rate me
I've noticed the mistake in the quad drawing and I've modified it. Now, I'm getting the original image except in the top right corner where I get a red rectangle. I've also noticed that if I comment the line glUseProgram(0) the whole image is processed by the first shader and the small rectangle is still red. In addition, it seems that the rectangle doesn't have the right input.

--Another question: do u have cull face on CCW or CW?
I have no idea. How can I figure it out?

--where are u setting up mipmapping?
I'm not. Should I? Why?

--what GL and FBO errors do u get?
I get an error after the setup of the second shader("shader 2").

--plz stop using glut... It`s so old
I didn't know it. What should I use instead?


I really need some help. I'm completely stuck in my project because of that.
If you have any other ideas that can allow me to read back the data to implement successive shaders, I'd appreciate to know them.

Just to let you know that I figured it out.

It was a problem with the definition of the glVertex3f in drawing the quad.

In the display function :

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-0.5, -0.5, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-0.5, 0.5, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(0.5, 0.5, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(0.5, -0.5, 0.0);
glEnd();

and for the shaderDraw function:

glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
glEnd();

This topic is closed to new replies.

Advertisement