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, &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);
[color:#FF0000] glBindTexture(GL_TEXTURE_2D, m_iRenderTexture);[/color]
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();
- 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();
- 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();
- why he have bound the “pbuffer[buff_index]->Bind(WGL_FRONT_LEFT_ARB);” in this part of code?
Note: here are the blur and glow shaders:
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);
}