PDA

View Full Version : Replacing pBuffers with FBOs(glow effect)



Ehsan Kamrani
12-31-2010, 02:49 AM
Hi there
I'm currently reading an article about the glow effect from the book More OpenGL Game Programming.However I have no idea about the pBuffers. Unfortunately, this article has used pBuffers instead of FBOs.Unfortunately, asking a lot of questions is difficult.
I have many questions. Let's start them step by step.
1)First of all he has initialized the pBuffers:


// PBUFFERS INITIALIZATION
for(int i=0; i<2; i++) if(! pbuffer[i]->Initialize(256, 256, true, false)) return false;

// CREATE OUR RENDER TEXTURE OBJECT
glGenTextures(1, &amp;m_iRenderTexture);
glBindTexture(GL_TEXTURE_2D, m_iRenderTexture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//_MIPMAP_LINEAR);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// notice that we don't need to call glTexImage2D for this texture object

Does it mean the he has attached the m_iRenderTexture texture to the pBuffers? Has he shared this texture among them?

As he has explained, he has used these steps to render the glow effect:
A) Render the scene as normal to the frame buffer
B) Render the same scene to a texture while disabling the lighting and shader.

After the B step, he has applied 2 shaders to the texture. the first one blurs the texture for 5 times. The second shader adds a few contrast to the texture. finally, he has used additive blending to add the texture color to the scene.

Here's his code to render the glow effect:


void MGLApp::Render()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glLoadIdentity();
gluLookAt(10, 10, 10, 0,0,0, 0,1,0);
SetupLighting();

glRotatef( 20.f * (float)m_dElapTime, 0.f, 1.f, 0.f );
glRotatef( -90, 0.1f, 0.0f, 0.0f);

glEnable(GL_TEXTURE_2D);
RenderGeometry();

pbuffer[0]->Activate(); // make pbuffer[0] to be a render target
glPushAttrib(GL_VIEWPORT_BIT | GL_POLYGON_BIT);
// set vieport to pbuffer's size
glViewport( 0, 0, pbuffer[0]->GetWidth(), pbuffer[0]->GetHeight());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_TEXTURE_2D);
glPushMatrix();
// adding little scale to model. This will make effect to be more noticable
glScalef(1.05f, 1.05f, 1.05f);
// render geometry whithout lighting
RenderGeometry(false);
glPopMatrix();

pbuffer[0]->SwapBuffers(); // this instruction makes pbuffer content available as a texture

glPopAttrib();
pbuffer[0]->Deactivate();

// BLURRING SCREEN SPACE TEXTURE
glUseProgramObjectARB(m_iBlurShader);
glBindTexture(GL_TEXTURE_2D, m_iRenderTexture);

glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();
glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
glOrtho(0, 1, 0, 1, 0.01, 100);
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
glViewport( 0, 0, pbuffer[0]->GetWidth(), pbuffer[0]->GetHeight());
glDisable(GL_DEPTH_TEST);

int buff_index=0;


for(int i=0; i<5; i++, buff_index=!buff_index)
{
pbuffer[buff_index]->Bind(WGL_FRONT_LEFT_ARB); // binding buffer to a texture
pbuffer[!buff_index]->Activate();

glBegin(GL_QUADS);
glTexCoord2d(0, 0); glVertex3d(0, 0, -1);
glTexCoord2d(1, 0); glVertex3d(1, 0, -1);
glTexCoord2d(1, 1); glVertex3d(1, 1, -1);
glTexCoord2d(0, 1); glVertex3d(0, 1, -1);
glEnd();

pbuffer[buff_index]->Release(WGL_FRONT_LEFT_ARB);

pbuffer[!buff_index]->SwapBuffers();
pbuffer[!buff_index]->Deactivate();
}
glPopAttrib();
glMatrixMode(GL_PROJECTION); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glPopMatrix();

// RENDERING SCREEN SPACE TEXTURE TO FRAMEBUFFER

glUseProgramObjectARB(m_iGlowShader);

glBindTexture(GL_TEXTURE_2D, m_iRenderTexture);
pbuffer[buff_index]->Bind(WGL_FRONT_LEFT_ARB);

glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();
glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
glOrtho(0, 1, 0, 1, 0.01, 100);

glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
// additive blending setup
glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE);

glBegin(GL_QUADS);
glTexCoord2d(0, 0); glVertex3d(0, 0, -1);
glTexCoord2d(1, 0); glVertex3d(1, 0, -1);
glTexCoord2d(1, 1); glVertex3d(1, 1, -1);
glTexCoord2d(0, 1); glVertex3d(0, 1, -1);
glEnd();

glPopAttrib();
glMatrixMode(GL_PROJECTION); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glPopMatrix();

pbuffer[buff_index]->Release(WGL_FRONT_LEFT_ARB); // release pbuffer texture for further rendering


glPopMatrix();
}


Here are my questions:
2)In the following code, does it mean that he has rendered to the m_iRenderTexture using a pBuffer?


pbuffer[0]->Activate(); // make pbuffer[0] to be a render target
glPushAttrib(GL_VIEWPORT_BIT | GL_POLYGON_BIT);
// set vieport to pbuffer's size
glViewport( 0, 0, pbuffer[0]->GetWidth(), pbuffer[0]->GetHeight());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_TEXTURE_2D);
glPushMatrix();
// adding little scale to model. This will make effect to be more noticable
glScalef(1.05f, 1.05f, 1.05f);
// render geometry whithout lighting
RenderGeometry(false);
glPopMatrix();

pbuffer[0]->SwapBuffers(); // this instruction makes pbuffer content available as a texture

glPopAttrib();
pbuffer[0]->Deactivate();



3) Why he has bound the following texture while using the blur shader?
glBindTexture(GL_TEXTURE_2D, m_iRenderTexture);
( I have specified it as red color in the code )

As you see he has used 2 pBuffers to blur the texture:



int buff_index=0;


for(int i=0; i<5; i++, buff_index=!buff_index)
{
pbuffer[buff_index]->Bind(WGL_FRONT_LEFT_ARB); // binding buffer to a texture
pbuffer[!buff_index]->Activate();

glBegin(GL_QUADS);
glTexCoord2d(0, 0); glVertex3d(0, 0, -1);
glTexCoord2d(1, 0); glVertex3d(1, 0, -1);
glTexCoord2d(1, 1); glVertex3d(1, 1, -1);
glTexCoord2d(0, 1); glVertex3d(0, 1, -1);
glEnd();

pbuffer[buff_index]->Release(WGL_FRONT_LEFT_ARB);

pbuffer[!buff_index]->SwapBuffers();
pbuffer[!buff_index]->Deactivate();
}
glPopAttrib();
glMatrixMode(GL_PROJECTION); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glPopMatrix();




4) How can I replace this part of code with the FBOs?( How can I copy the contents of one FBO to another FBO? )


5)As you saw, to apply the glow shader and adding the glow effect, he has used the following code:


// RENDERING SCREEN SPACE TEXTURE TO FRAMEBUFFER

glUseProgramObjectARB(m_iGlowShader);

glBindTexture(GL_TEXTURE_2D, m_iRenderTexture);
pbuffer[buff_index]->Bind(WGL_FRONT_LEFT_ARB);

glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();
glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
glOrtho(0, 1, 0, 1, 0.01, 100);

glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
// additive blending setup
glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE);

glBegin(GL_QUADS);
glTexCoord2d(0, 0); glVertex3d(0, 0, -1);
glTexCoord2d(1, 0); glVertex3d(1, 0, -1);
glTexCoord2d(1, 1); glVertex3d(1, 1, -1);
glTexCoord2d(0, 1); glVertex3d(0, 1, -1);
glEnd();

glPopAttrib();
glMatrixMode(GL_PROJECTION); glPopMatrix();
glMatrixMode(GL_MODELVIEW); glPopMatrix();

pbuffer[buff_index]->Release(WGL_FRONT_LEFT_ARB); // release pbuffer texture for further rendering


glPopMatrix();


5) why he have bound the "pbuffer->Bind(WGL_FRONT_LEFT_ARB);" in this part of code?

---------------------------------
Note: here are the blur and glow shaders:
[B]
blur shader:



[vertex]

uniform float radius_x, radius_y; // typycally radius_x = 1.0 / (texture resolution x)

void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0 - vec4(-radius_x, 0.0, 0.0, 0.0);
gl_TexCoord[1] = gl_MultiTexCoord0 - vec4(radius_x, 0.0, 0.0, 0.0);
gl_TexCoord[2] = gl_MultiTexCoord0 - vec4(0.0, -radius_y, 0.0, 0.0);
gl_TexCoord[3] = gl_MultiTexCoord0 - vec4(0.0, radius_y, 0.0, 0.0);

gl_Position = ftransform();
}



[fragment]
uniform sampler2D tex_unit_0; // texture from previous blurring stage

void main()
{
vec4 sample[4];

sample[0] = texture2D(tex_unit_0, gl_TexCoord[0].st);
sample[1] = texture2D(tex_unit_0, gl_TexCoord[1].st);
sample[2] = texture2D(tex_unit_0, gl_TexCoord[2].st);
sample[3] = texture2D(tex_unit_0, gl_TexCoord[3].st);

gl_FragColor = (sample[0] + sample[1] + sample[2] + sample[3]) / 4.0;
}


Glow shader:


[vertex]

void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}



[fragment]
uniform sampler2D tex_unit_0; // blurred screen space texture

void main()
{
vec3 sample = texture2D(tex_unit_0, gl_TexCoord[0].st).rgb;

sample = (pow(sample, vec3(2.0))- vec3(0.0, 0.2, 0.2) )*3.0;

gl_FragColor = vec4(sample, 1.0);
}

mobeen
12-31-2010, 04:15 AM
hi,
You first three questions are related to how we accompalish render to texture func. using PBOs when we had no FBOs.

For Q4, there are many ways, the simplest is to attach two color attachments to your FBO. Then, in your rendering code, use (assuming that your binding are to color attchmt 0 and 1)
GLenum colAttchs[2]={GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glBindFrameBuffer(GL_DRAWFRAMEBUFFER, fboID);
glDrawBuffers(2, colAttchs);
//do your rendering here

to direct rendering to the two attachments in a single pass. ANother option is to use glBlitFramebuffer func. http://www.opengl.org/sdk/docs/man3/xhtml/glBlitFramebuffer.xml


Q5 the reason for binding the front left buffer is to rebind the drawbiffer so that the rendering could continue on te display framebuffer, for your code u will use glDrawBuffer(GL_FRONT_LEFT);

Hope this helps,
Mobeen

Ehsan Kamrani
12-31-2010, 04:36 AM
Hi Mobeen
Thank you, but I didn't understand your comments at all. specially, you didn't response to my first 3 questions.It's clear that the three questions are related to how we accompalish render to texture using PBOs when we had no FBOs!

mobeen
12-31-2010, 04:58 AM
OK, I thought u would get these let me discuss them.
Q1) Yes he is setting up an offscreen render target.
Q2) Yes he is rendering to the offscreen render target but is scaling the geometry slightly to make a more pronounced glow.
Q3) Since he is not setting the shader uniform, i think the texture binding is linking the render target to the shader. In your case u would set a shader uniform and pass the FBO attachment to it as texture map.

Hope this helps,
Mobeen

Ehsan Kamrani
12-31-2010, 08:34 AM
I could understand the first and second questions. but I didn't understand the others. Can you give me an example or explain more about them?Sorry, but I have just used simple FBOs to render to textures.
And about question 3: do you mean that the texture is sent to gl_MultiTexCoord0 of the blur texture?

Assuming that I have 2 color buffers, how can I apply its textures to this code?
for example, here's my FBO with 2 textures:


glGenTextures(1, &amp;color_tex);
glBindTexture(GL_TEXTURE_2D, color_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//NULL means reserve texture memory, but texels are undefined
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
//-------------------------

glGenTextures(1, &amp;color_tex2);
glBindTexture(GL_TEXTURE_2D, color_tex2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//NULL means reserve texture memory, but texels are undefined
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
//----------------------------
glGenFramebuffersEXT(1, &amp;fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
//Attach 2D texture to this FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, color_tex, 0);

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, color_tex2, 0);
//-------------------------
glGenRenderbuffersEXT(1, &amp;depth_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 256, 256);
//-------------------------
//Attach depth buffer to FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);


( Is this code a correct way to create and attach 2 texture to the color buffers of the FBO? )

mobeen
12-31-2010, 10:14 AM
And about question 3: do you mean that the texture is sent to gl_MultiTexCoord0 of the blur texture?

gl_MultiTexCoord0 is the texture coordinate for multitexturing. Since I have not seen the pbuffer class code, I suspect that the author is attaching the texture to the currently active texture unit 0 i.e. (GL_TEXTURE0 which is the default active texture unit) and referencing it in the shader. If I see the pbuffer class I cud tell u more about this.


Assuming that I have 2 color buffers, how can I apply its textures to this code?
for example, here's my FBO with 2 textures:
[code omitted for space concerns]
( Is this code a correct way to create and attach 2 texture to the color buffers of the FBO? )
Yes this looks ok.
Now for sending the texture to the blur and glow shader, you can send it as a shader uniform using something like this (assuming that you program is progID and the sampler name in the shader is textureMap),


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, color_tex);
glUniform1i(glGetUniformLocation(progID, "textureMap"), 0);
//0 is the texture unit where our texture is bound


Hope this helps,
Mobeen

Ehsan Kamrani
12-31-2010, 11:14 AM
Thanks
I uploaded the source code here:
http://www.speedyshare.com/files/25992399/Glow_Earth.rar
Please download glowEarth.rar.
Locate "void MGLApp::Render()" and you'll see the rendering code. Actually, I have rendered the scene to the FBO, but I don't understand how to use the FBO to render and blur the texture for N times. I have asked this question in the beginners forum. I'm new to post processing effects. So I need some extra information about processing the texture for N times.
someone has asked this question at gamedev.net:
http://www.gamedev.net/community/forums/topic.asp?topic_id=519459

Ehsan Kamrani
01-04-2011, 07:28 PM
I could finally implement the bloom effect with FBOs. Here are 3 screenshots:
http://upwqcw.blu.livefilestore.com/y1pl...oom5.jpg?psid=1 (http://upwqcw.blu.livefilestore.com/y1plXDMTeTnHHVUHqMip4713zuY01zycLOjRcSp7K8jORiKrLx kgdy94cz46koVYYypEEZxqYMJQ6npIjbbBCttAEIXTiQv20Kk/bloom5.jpg?psid=1)
http://upwqcw.blu.livefilestore.com/y1p7...oom6.jpg?psid=1 (http://upwqcw.blu.livefilestore.com/y1p7_oOC-9TPfSCboeURyjlsdU5NVeghcLVSnY6SF5xrt2uLkpIQ-pOA5xOl9JqgUmNXTnWWWYJYgA8YnFOPIl03fdWB6jnEO7c/bloom6.jpg?psid=1)
http://upwqcw.blu.livefilestore.com/y1pL...lFog.jpg?psid=1 (http://upwqcw.blu.livefilestore.com/y1pLk380azKt_ag5G2fCLz_VRC4YbmgtZ0k3nSW82u1JbMuula RhXrcfr6i5usv9xttCRlp3CvhUZh4_DnWFC8TecB91xdYrzPE/perPixelFog.jpg?psid=1)