Jump to content
  • Advertisement
Sign in to follow this  
kloye

OpenGL GLSL - FBO - render to texture - Image Processing

This topic is 2997 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
Advertisement
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;
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
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!!

Share this post


Link to post
Share on other sites
U propaby modify somewhere your frag color because with only this:

///////////VERT:
void main() {

gl_TexCoord[0] = gl_MultiTexCoord0;

gl_Position = ftransform();

}
//////////////FRAG
void 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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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();

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!