0
\$\begingroup\$

I've added functionality so that I can render to a framebuffer (for post-processing and stuff). I can successfully render to my framebuffer and then render that framebuffer, but anything with a shader does not render to my framebuffer. Rendering with the same shader worked before I added the framebuffer step.

Here's how I create my framebuffer:

// create the color texture
colorBuffer = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, colorBuffer);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

// create the depth texture
depthBuffer = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, depthBuffer);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Depth24Stencil8, width, height, 0, PixelFormat.DepthStencil, PixelType.UnsignedInt, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

// create the fbo
GL.GenFramebuffers(1, out fbo);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, colorBuffer, 0);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, TextureTarget.Texture2D, depthBuffer, 0);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);

And this is my shader code:

// VERTEX SHADER
#version 330

uniform mat4 world;
uniform mat3 worldIT;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 textureTransformation;

in vec3 rPosition;
in vec3 rNormal;
in vec2 rTexCoord;
in vec3 rColor;

out vec3 vWorldPosition;
out vec3 vNormal;
out vec2 vTexCoord;
out vec3 vColor;

void main(void)
{
    vec4 tempWorld = world * vec4(rPosition, 1.0f);
    gl_Position = projection * view * tempWorld;

    vWorldPosition = tempWorld.xyz;
    mat3 normalSpace = mat3(world);
    vNormal = normalize(normalSpace * rNormal);
    vTexCoord = (textureTransformation * vec4(rTexCoord, 0.0f, 1.0f)).xy;
    vColor = rColor;
}

// FRAGMENT SHADER
#version 330

uniform sampler2D colorMap;

in vec3 vWorldPosition;
in vec3 vNormal;
in vec2 vTexCoord;
in vec3 vColor;

out vec4 fColor;

const vec3 ambientLight = vec3(0.1f, 0.1f, 0.1f);
const vec3 lightDir = vec3(0.0f, -1.0f, 1.0f);
const vec3 lightColor = vec3(1.0f, 1.0f, 1.0f);

void main(void)
{
    vec4 texel = texture(colorMap, vTexCoord);

    vec3 n = normalize(vNormal);
    vec3 l = normalize(lightDir);
    float nDotL = max(dot(n, l), 0.0f);

    vec4 diffuse = vec4((ambientLight + nDotL * lightColor) * vColor, 1.0f) * texel;

    vec4 specular = vec4(0.0f, 0.0f, 0.0f, 0.0f);

    fColor = diffuse + specular;
}

EDIT: It seems to be that, for some odd reason, my shader stopped outputting at all when I added the framebuffer support.

\$\endgroup\$
3
  • \$\begingroup\$ Possible that you need to bind fColor to location 0 to make sure it goes to the right color attachment. Since you say you could render to the 0 framebuffer with these shaders, this might not be the problem, but it's worth checking. \$\endgroup\$ Apr 27, 2012 at 1:24
  • \$\begingroup\$ As in use GL.BindAttribLocation(shaderProgram, 0, "fColor")? Or something else? \$\endgroup\$
    – jmegaffin
    Apr 27, 2012 at 1:55
  • \$\begingroup\$ Yea, give that a shot. \$\endgroup\$ Apr 27, 2012 at 7:55

3 Answers 3

3
\$\begingroup\$

Maybe you are unbinding your framebuffer with the last call:

GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);

void glBindFramebuffer(GLenum target, GLuint id)

The first parameter, target, should be GL_FRAMEBUFFER, and the second parameter is the ID of a framebuffer object. Once a FBO is bound, all OpenGL operations affect onto the current bound framebuffer object. The object ID 0 is reserved for the default window-system provided framebuffer. Therefore, in order to unbind the current framebuffer (FBO), use ID 0 in glBindFramebuffer().

-- From the Songho OpenGL tutorials

\$\endgroup\$
1
  • \$\begingroup\$ I updated your post and added a source link for a result I think you pulled that quote from. Please update your post if it's incorrect. \$\endgroup\$ May 18, 2012 at 1:15
0
\$\begingroup\$

After fbo creation call assert

assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 

I hope this will lead you to the right answer. See code errors here.

\$\endgroup\$
1
  • \$\begingroup\$ No, the framebuffer is being initialized correctly. \$\endgroup\$
    – jmegaffin
    Apr 27, 2012 at 10:58
0
\$\begingroup\$

I had exactly this problem. To verify my operations to the framebuffer, I was drawing the framebuffer texture back to the screen using a simple GL_QUAD. But it was not giving correct output since I was not setting glUseProgram(0) before drawing that quad. So the correct sequence of operations goes something like this:

glBindFramebuffer(GL_FRAMEBUFFER, myframebuffer );
glUseProgram(program_id);
...
// function call for drawing to framebuffer
...
glUseProgram(0); // <----- This is the important step
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// draw my quad using texture that was bound to frame buffer
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_framebuffer);
glBegin(GL_QUADS);

glTexCoord2f(0,0);
glVertex2f(0,0);

glTexCoord2f(1,0);
glVertex2f(1,0);

glTexCoord2f(1, 1);
glVertex2f(1, 1);

glTexCoord2f(0, 1);
glVertex2f(0, 1);

glEnd();
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .