openGL Post-Processing Effects

openGL Post-Processing Effects Tutorial

by gbuzogany on 3/06/2011

It was hard to find out how it works, so I thought it would be great to share that!

I assume that you already know what shaders (vertex and fragment) are and that you are a little experienced with OpenGL.

Basically, what you do is:

-> Render the scene to a texture
-> Create a quad, map that texture in that quad, and place the quad fullscreen (just filling the window, not literally).
-> Enable your desired shader
-> Render it! But now, your shaders can get any information of that texture!
-> If you want to use more than one post-processing effect, just repeat the process!

I will assume that you know how to use google’s amazing search engine, and will have no doubts about what function does what.

Now, some snippets:

 

1 // Used variables and types
2 GLuint fbo; // frame buffer object
3 GLuint depthbuffer; // depth buffer object
4 GLuint img; // FBO "texture"
5 GLuint rbo; // render buffer object

-> How to create a framebuffer to render the scene?

01 glGenFramebuffersEXT(1, &fbo);
02 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
03 glGenRenderbuffersEXT(1, &rbo);
04 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo);
05 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, WIDTH, HEIGHT); // one nice place to put multisampling!
06 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
07  
08 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);
09  
10 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo);
11  
12 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
13 if(status == GL_FRAMEBUFFER_COMPLETE_EXT)
14 {
15     printf("FBO Setup complete!\n");
16 }
17 else
18 {
19     printf("FBO Error!\n");
20 }
21  
22 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

-> How to setup the framebuffer to be used as a texture?

01 glGenTextures(1, &img);
02 glBindTexture(GL_TEXTURE_2D, img);
03 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
04 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
05 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
06 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
07 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
08 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
09 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
10 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // place multisampling here too!
11 glBindTexture(GL_TEXTURE_2D, 0);

-> How to render to the framebuffer created previously?

01     glViewport(0, 0, WIDTH*msaa, HEIGHT*msaa);
02     glMatrixMode(GL_PROJECTION);
03     glLoadIdentity();
04     gluPerspective(60.0f, (float)(WIDTH)/(HEIGHT), 0.01f, 10000.0f);
05     glMatrixMode(GL_MODELVIEW);
06     glLoadIdentity();
07  
08     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
09  
10 // render here!!!!

-> Ok, I rendered it, now I want to do some post-processing magic!

-> Switch to 2D rendering mode. It will setup the screen to the post-processing magic.

1 glMatrixMode(GL_PROJECTION);
2 glLoadIdentity();
3 glOrtho(0, WIDTH , HEIGHT , 0, -1, 1);
4 glMatrixMode(GL_MODELVIEW);
5 glLoadIdentity();

It’s now that the magic happens, the steps are:

-> Enable the post-processing shader that you want:

1 // you should now how to do that, if not, i will publish one tutorial soon, but there is a lot of it on the internet (as everything else)
2 glUseProgram(program);

-> Render one fullscreen-quad using the framebuffer’s texture:

1 glBindTexture(GL_TEXTURE_2D, img);
2 glBegin(GL_QUADS);
3     glTexCoord2f(0,1);   glVertex2f(0,0);
4     glTexCoord2f(0,0);   glVertex2f(0,HEIGHT);
5     glTexCoord2f(1,0);   glVertex2f(WIDTH,HEIGHT);
6     glTexCoord2f(1,1);   glVertex2f(WIDTH,0);
7 glEnd();

-> To use more than one post-processing effect, just render the output of the two last steps to the framebuffer again, and again, and again. On the last time, unbind the framebuffer, and render to the screen.

To unbind the framebuffer to render to the screen:

1 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // unbind
2 glBindTexture(GL_TEXTURE_2D, img);
3 glGenerateMipmapEXT(GL_TEXTURE_2D);
4 glBindTexture(GL_TEXTURE_2D, 0);
5 glViewport(0, 0, WIDTH, HEIGHT);

Done!

This snippets should help someone :)

gbuzogany@gmail.com
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值