pedjjj
pedjjj

Reputation: 1038

OpenGL 3.0: Cannot use framebuffer object in shader (black)

I want to draw a scene to a framebuffer object and later use the texture of that in another shader. For testing purposes I would just like to actually output the framebuffer object's textur. However, the corresponding part (a rectangle) is just completely black. So I'm wondering whether either the rendering to the fbo does not work or the access to that.

Here are the important code parts:

Called before rendering to the FBO:

void TextureRenderer::bind() {
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
    //  glPushAttrib(GL_VIEWPORT_BIT);
    glViewport(0, 0, mWidth, mHeight);
}

This is the plane on which the FBO should be displayed. The first texture "mTextureId" is another texture I've loaded from a TGA file and displaying that works just fine. However, the second "mReflectionTextureId" is the one from the VBO and this is the one which I cannot access (or it really is black because there was an error before).

void WaterPlane::render(const Transform& trans) {
    mat4 projection = trans.projection;
    mat4 view = trans.view;
    mat4 model = mat4::identitiy();

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);

    mShader->bind();

    // lets activate the textures now
    glEnable(GL_TEXTURE_2D);

    // bumpmap texture
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mTextureId);
    // set the texture
    mShader->seti("waterBumpTextureSampler", 0);

    // rendered reflection texture (has been rendered previously with the help of Framebuffer object for reflection)
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, mReflectionTextureId);
    // set reflection texture 
    mShader->seti("renderedReflection", 1);

    mShader->setMatrix("matProjection", projection, GL_TRUE);
    mShader->setMatrix("matView", view, GL_TRUE);
    mShader->setMatrix("matModel", model, GL_TRUE);
    mShader->setf("vecTextureShift", mTextureShift);

    mVboWaterPlane->render();

    mShader->release();

    glDisable(GL_TEXTURE_2D);

    glPopClientAttrib();
    glPopAttrib();
}

Finally, the water.fs shader:

#version 130
in vec4 VertPosition;
in vec4 VertNormal;
in vec4 VertColor;
in vec4 VertTexture;

uniform vec3 lightPos;
uniform sampler2D waterBumpTextureSampler;
uniform sampler2D renderedReflection; // reflection on the water

void main()
{
    // completely black
    gl_FragColor = texture( renderedReflection, VertTexture.xz); 

    // if this is actually commented in the bumpmap texture will be shown nicely
   // gl_FragColor = texture( waterBumpTextureSampler, VertTexture.xz); 
}

So in general displaying textures work, however displaying the texture from the framebuffer object does not (or the rendering to it previously to that did not work).

Screenshot:

  

EDIT:

The initialization code of the FBO:

void TextureRenderer::init() {
    glGenFramebuffers(1, &mFramebufferName);
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);

    // The texture we're going to render to
    glGenTextures(1, &mRenderedTextureId);

    // "Bind" the newly created texture : all future texture functions will modify this texture
    glBindTexture(GL_TEXTURE_2D, mRenderedTextureId);

    cout << "TextureRenderer: creating with id " << mFramebufferName << " and tex id " << mRenderedTextureId << endl;

    // Give an empty image to OpenGL ( the last "0" )
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

    // Poor filtering. Needed !
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // The depth buffer 
    // TODO this is probably not needed?!?!?!
    glGenRenderbuffers(1, &mDepthRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mWidth, mHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderBuffer);

    // Set "renderedTexture" as our colour attachement #0
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mRenderedTextureId, 0);

    // Set the list of draw buffers.
    GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
    glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers

    // Always check that our framebuffer is ok
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        cout << "Problem during creation of TextureRenderer" << endl;
        throw std::runtime_error("Something Bad happened here");
    }

    unbind();

    cout << "TextureRenderer: creating with id " << mFramebufferName << "...done" << endl;
}

The bind code (which is immediately called before rendering to the FBO):

void TextureRenderer::bind() {
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
    //  glPushAttrib(GL_VIEWPORT_BIT); // http://wiki.delphigl.com/index.php/Tutorial_Framebufferobject
    glViewport(0, 0, mWidth, mHeight);
}

Upvotes: 1

Views: 585

Answers (1)

pedjjj
pedjjj

Reputation: 1038

This is now solved. The problem simply was, that I was using wrong texture coordinates in the water.fs (fragment) shader. Below the corrected variant of water.fs. Note the difference in calculation of the coordinates that are given then to the texture(...) function.

in vec4 VertPosition; 
in vec4 VertNormal;
in vec4 VertColor;
in vec4 VertTexture; 
in vec4 VertTexturePS;

uniform vec3 lightPos;
uniform sampler2D waterBumpTextureSampler; 
uniform sampler2D texReflection; // reflection on the water

void main()
{
    vec2 originalTexCoord = VertTexturePS.xy / VertTexturePS.w * 0.5 + vec2(0.5);
    gl_FragColor = texture( texReflection, originalTexCoord.xy); 
}

VertTexturePS is just calculated in the water.vs by this:

VertTexturePS = matProjection * matView * matModel * vec4(Position.xyz, 1);

Upvotes: 2

Related Questions