2010-07-09 64 views
2

我目前正試圖在OpenGL圖像處理算法中實現。用於過濾器的GPU-成色着色器上的圖像處理 - FBO

我想先後使用幾個着色器來執行幾個過濾器(Sobel Gaussian,...)。 我明白,要做到這一點,我不得不渲染紋理感謝FBO。我讀了很多關於這方面的知識,並編寫了一個代碼。但是我沒有得到我期望的結果。

目前,我只是想使用兩個着色器。所以,我有一個原始圖像,這是我的第一個着色器的輸入。然後,我想將着色器的輸出渲染爲紋理,然後紋理將成爲我的第二個着色器(乒乓技術)的輸入。最後,我想顯示第二個着色器的輸出。

但因此,我得到的原始圖像。

我的代碼如下:

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

是否有人有什麼是錯的想法???

+0

嗨zenna 我是openframeworks用戶,我試圖實現與你真正一樣的東西。一個簡單的乒乓着色器鏈接在fbo內。 你解決了這個問題嗎?你能指出我的解決方案嗎? 你能寫在埃洛伊電子郵件{}在telenoika [點]網,請... 我不知道如何使一個PM到您的文章... 非常感謝! – 2011-02-22 18:57:48

+0

你聽說過OpenCL和CUDA嗎?我認爲這是以可維護的方式執行這些操作的最先進的技術 – fabrizioM 2011-09-08 21:17:21

回答

1

您試圖同時使用FBO作爲渲染源和渲染目標。 Afaik你不能這麼做 - 如果你想使用綁定到FBO的紋理作爲渲染源,你需要解除綁定FBO(通過調用glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);或綁定另一個FBO)。

它看起來像你試圖通過使用你的開始紋理作爲FBO的顏色緩衝區來保存內存。我不確定這是否可能。

所以你可能想嘗試創建兩個FBO,每個都有一個顏色緩衝區,並交換整個FBO,並開始將紋理渲染到第一個FBO。另外,不要使用起始紋理作爲FBO的顏色緩衝區,而應爲每個FBO創建一個單獨的顏色緩衝區。

在將紋理附加到FBO之前,您也不需要將紋理綁定到紋理單元。