2010-07-09 25 views
2

J'essaie actuellement de mettre en œuvre des algorithmes de traitement d'image OpenGL.Traitement d'image sur les shaders successifs GPU pour les filtres - FBO

Je souhaiterais utiliser successivement plusieurs shaders pour réaliser plusieurs filtres (Sobel Gaussian, ...). J'ai compris que pour cela je devais rendre à la texture grâce à un FBO. J'ai lu beaucoup de choses à ce sujet et j'ai écrit un code. Mais je n'obtiens pas le résultat que je m'attendais.

Pour l'instant, j'essaie juste d'utiliser deux shaders. J'ai donc une image originale qui est l'entrée de mon premier shader. Ensuite, je veux rendre la sortie du shader à une texture qui sera alors l'entrée de mon second shader (technique de ping-pong). Et enfin, je veux afficher la sortie du second shader. Mais en conséquence, je reçois l'image originale.

Mon code est le suivant:

/******************** 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; 
} 

ce que quelqu'un a une idée de ce qui ne va pas ???

+0

salut zenna je suis utilisateur de openFrameworks et je suis en train de réaliser quelque chose de vraiment la même chose que vous. un simple shader ping-pong enchaînant à l'intérieur d'un fbo. avez-vous résolu ce problème? pourriez-vous me signaler une solution? pourrait vous écrire un courriel à eloi {at} telenoika [dot] net s'il vous plaît ... je ne sais pas comment faire un PM à votre message ... merci beaucoup! –

+0

Avez-vous entendu parler d'OpenCL et de CUDA? Je pense que c'est l'état de l'art pour effectuer ces opérations d'une manière maintenable – fabrizioM

Répondre

1

Vous essayez d'utiliser simultanément le FBO comme source de rendu et comme cible de rendu. Afaik vous ne pouvez pas faire cela - si vous voulez utiliser une texture liée à un FBO comme source de rendu, vous devez dissocier le FBO (soit en appelant glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); ou en liant un autre FBO).

Il semble que vous essayez d'économiser de la mémoire de cette façon en utilisant votre texture de départ comme tampon de couleur FBO là-bas. Je ne suis pas sûr que cela soit possible aussi.

Vous voudrez peut-être essayer de créer deux FBO, chacune avec un tampon de couleur unique, et inverser l'ensemble des FBO, et commencer par rendre votre texture au premier FBO. En outre, n'utilisez pas votre texture de départ comme tampon de couleur pour un FBO, mais créez un tampon de couleur séparé pour chaque FBO à la place.

Vous n'avez pas non plus besoin de lier une texture à une unité de texture avant de l'attacher à un FBO.