I'm running into some interesting issues when using FBO and NV_fragment_program and ARB_fragment_program. Shaders seem to go absolutely nuts when used to render to an FBO. When rendering without shaders to the FBO, everything is fine. When rendering with shaders to non-FBO, everything is fine. Combine the two, and things just go terribly wrong. The fragment program is not complex at all. Is anyone else experiencing issues with this?
Framebuffer init code:
// Sets up the render targets of the render buffer for the size passed in
bool Renderer::Setup_Framebuffer(UInt Size)
{
GLenum Status; // Status variable for checking the readiness of the framebuffer
// If framebuffer exists
if(!m_Framebuffer)
return false;
// Create textures for color buffers
m_Framebuffer->Color_Buffer_A_ID = Create_Texture(Size, NULL);
m_Framebuffer->Color_Buffer_B_ID = Create_Texture(Size, NULL);
// If color buffer textures were not created
if(!m_Framebuffer->Color_Buffer_A_ID || !m_Framebuffer->Color_Buffer_B_ID)
return false; // Failed to setup framebuffer
// Bind framebuffer
Extensions.p_glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_Framebuffer->Framebuffer_ID);
// Attach color buffer textures
Extensions.p_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_Framebuffer->Color_Buffer_A_ID, 0);
Extensions.p_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, m_Framebuffer->Color_Buffer_B_ID, 0);
// Create the render buffer object for the depth buffer
Extensions.p_glGenRenderbuffers(1, &m_Framebuffer->Depth_Buffer_ID);
// If render buffer was not created
if(!m_Framebuffer->Depth_Buffer_ID)
return false; // Failed to setup framebuffer
// Bind render buffer obect for depth buffer
Extensions.p_glBindRenderbuffer(GL_RENDERBUFFER_EXT, m_Framebuffer->Depth_Buffer_ID);
// Instruct the render buffer to act as a depth buffer
Extensions.p_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, Size, Size);
// Attach render buffer to framebuffer as depth buffer
Extensions.p_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_Framebuffer->Depth_Buffer_ID);
// Check the framebuffer for setup errors
Status = Extensions.p_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
// If the framebuffer is not ready
if(Status != GL_FRAMEBUFFER_COMPLETE_EXT)
return false; // Failed to setup framebuffer
// Unbind render buffer and framebuffer
Extensions.p_glBindRenderbuffer(GL_RENDERBUFFER_EXT, NULL);
Extensions.p_glBindFramebuffer(GL_FRAMEBUFFER_EXT, NULL);
return true;
}
Draw code:
Extensions.p_glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_Framebuffer->Framebuffer_ID);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
cgGLEnableProfile(m_Cg.Profile);
cgGLBindProgram(m_Distance_Shader.Program);
if(cgGetError() != CG_NO_ERROR)
return false;
float Temp[2] = {5.0f / 255.0f, 0.0f};
cgGLSetParameter2fv(m_Distance_Shader.Paramter, Temp);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f, 1.0f, 1.0f);
Extensions.p_glActiveTexture(OGL_TEX_UNIT(1));
Extensions.p_glClientActiveTexture(OGL_TEX_UNIT(1));
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_Texture_B->IDs[0]);
Extensions.p_glActiveTexture(OGL_TEX_UNIT(0));
Extensions.p_glClientActiveTexture(OGL_TEX_UNIT(0));
glBindTexture(GL_TEXTURE_2D, m_Texture_A->IDs[0]);
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2i(0, 0);
glTexCoord2i(0, 1);
glVertex2i(0, Size);
glTexCoord2i(1, 1);
glVertex2i(Size, Size);
glTexCoord2i(1, 0);
glVertex2i(Size, 0);
glEnd();
cgGLBindProgram(NULL);
Extensions.p_glActiveTexture(OGL_TEX_UNIT(1));
Extensions.p_glClientActiveTexture(OGL_TEX_UNIT(1));
glDisable(GL_TEXTURE_2D);
Extensions.p_glActiveTexture(OGL_TEX_UNIT(0));
Extensions.p_glClientActiveTexture(OGL_TEX_UNIT(0));
Extensions.p_glBindFramebuffer(GL_FRAMEBUFFER_EXT, NULL);
glDrawBuffer(GL_BACK);
glBindTexture(GL_TEXTURE_2D, m_Framebuffer->Color_Buffer_A_ID);
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2i(0, 0);
glTexCoord2i(0, 1);
glVertex2i(0, Size);
glTexCoord2i(1, 1);
glVertex2i(Size, Size);
glTexCoord2i(1, 0);
glVertex2i(Size, 0);
glEnd();
glBindTexture(GL_TEXTURE_2D, NULL);
if(!SwapBuffers(m_hdcWindow))
return false;
Shader code (Cg):
// Determines if the distance between the current element and the reference element is at least 25
float4 main(sampler2D inTexA: TEXTURE0, sampler2D inTexB: TEXTURE1, in float2 inTexCoord: TEXCOORD0, uniform float2 inRefCoord) : COLOR
{
float Min_Distance = 0.098039215f; // (25 / 255), distance clamped to 1.0f
float4 A_Position = tex2D(inTexA, inTexCoord); // Retrieve the current element from the texture
float4 B_Position = tex2D(inTexB, inRefCoord); // Retrieve the reference element from the texture
float4 Out_Color = 0; // Color output vector
// If the distance is less than the minimum distance
if(abs(A_Position.r - B_Position.r) < Min_Distance)
Out_Color = float4(0.0f, 0.0f, 0.0f, 0.0f); // Output 0
else // Distance is greater than minimum
Out_Color = float4(1.0f, 1.0f, 1.0f, 1.0f); // Output white, max
return Out_Color;
}
The previous code should output black for pixels with red components less than 25 from the reference pixel. This works correctly when not rendering to an FBO. It renders solid white when rendering to an FBO. However, if I change the else to Out_Color = A_Position, it works. By working, I mean that instead of solid white, the pixels that are supposed to be black (less than 25) are actually black, and the pixels that would be white (25 or greater) are the color of A_Position for that pixel. Any ideas?
Thanks.