简体   繁体   English

GPU上的图像处理-用于滤镜的连续着色器-FBO

[英]Image Processing on GPU- sucessive shaders for filters - FBO

I'm currently trying to implement in OpenGL image processing algorithms. 我目前正在尝试在OpenGL图像处理算法中实现。

I would like to successively use several shaders in order to perform several filters (Sobel Gaussian,...). 我想依次使用多个着色器以执行多个滤镜(Sobel Gaussian,...)。 I understood that to do this I had to render to texture thanks to a FBO. 我知道,要做到这一点,我必须借助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 (ping-pong 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??? 有人对什么地方有错吗???

You are trying to simultaneously use the FBO as render source and render target. 您试图同时使用FBO作为渲染源和渲染目标。 Afaik you cannot do that - if you want to use a texture bound to an FBO as render source, you need to unbind the FBO (either by calling glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); or by binding another FBO). Afaik无法做到这一点-如果要使用绑定到FBO的纹理作为渲染源,则需要取消绑定FBO(通过调用glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);或通过绑定另一个FBO)。

It looks like you are trying to save memory that way by using your start texture as the FBO's color buffer there. 看来您正在尝试通过将开始纹理用作FBO的颜色缓冲区来节省内存。 I am not sure whether this is possible as well. 我不确定这是否也可行。

So you may want try to create two FBOs, each with a single color buffer, and swap the entire FBOs, and start with rendering your texture to the first FBO. 因此,您可能希望尝试创建两个FBO,每个FBO都具有一个颜色缓冲区,并交换整个FBO,然后开始将纹理渲染到第一个FBO。 Also, don't use your start texture as a color buffer for an FBO, but create a separate color buffer for each FBO instead. 另外,请勿将起始纹理用作FBO的颜色缓冲区,而应为每个FBO创建单独的颜色缓冲区。

You also don't need to bind a texture to a texture unit before attaching it to an FBO. 您还不需要在将纹理附加到FBO之前将其绑定到纹理单元。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM