Search code examples
javaopenglglsllwjgltexturing

FBO texture is displaying completely black


I am attempting to follow ThinMatrix's water tutorial. To do this, I need to create an FBO and render it as a texture.

However as you can see, the water is completely black: enter image description here

I am using the source code provided directly from the tutorial (copied from the link).

Basically, I create a FrameBuffer:

public FrameBufferObject() {//call when loading the game
    initialiseReflectionFrameBuffer();
    initialiseRefractionFrameBuffer(); //Let's ignore refraction for now, as I only use reflection at the moment.
}
private void initialiseReflectionFrameBuffer() {
    reflectionFrameBuffer = createFrameBuffer();
    reflectionTexture = createTextureAttachment(REFLECTION_WIDTH,REFLECTION_HEIGHT);
    reflectionDepthBuffer = createDepthBufferAttachment(REFLECTION_WIDTH,REFLECTION_HEIGHT);
    unbindCurrentFrameBuffer();
}

I then create a texture attachment:

private int createTextureAttachment( int width, int height) {
    int texture = GL11.glGenTextures();
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
    GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, width, height,
            0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
    GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0,
            texture, 0);
    return texture;
}

And I also create a depth buffer attachment:

private int createDepthBufferAttachment(int width, int height) {
    int depthBuffer = GL30.glGenRenderbuffers();
    GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
    GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL11.GL_DEPTH_COMPONENT, width,
            height);
    GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT,
            GL30.GL_RENDERBUFFER, depthBuffer);
    return depthBuffer;
}

Then, I am rendering the objects to the frame buffer object:

Main.TerrainDemo.shader.start();
    fbos.bindReflectionFrameBuffer();
    for (Grass g : Main.TerrainDemo.toDraw){
        g.render();
    }
    fbos.unbindCurrentFrameBuffer();

I bind the frame buffer like this:

private void bindFrameBuffer(int frameBuffer, int width, int height){
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);//To make sure the texture isn't bound
    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
    GL11.glViewport(0, 0, width, height);
    System.out.println("Bound");
    if(GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER) == GL30.GL_FRAMEBUFFER_COMPLETE) {
        System.out.println("Frame buffer setup is complete: " + GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER));
    }
    System.out.println("Error: " + GL11.glGetError());
}

The "error" when I print out glGetError() is a normal 0. The "frame buffer setup" message does print out.

After which, I expect that calling fbos.getReflectionTexture() would return a texture ID... And it does! It successfully returns texture ID 12. However, the texture when I bind it is completely black.

public int getReflectionTexture() {//get the resulting texture
    return reflectionTexture; //Remember, this was our original texture attachment.
}
 reflectionTexture = createTextureAttachment(REFLECTION_WIDTH,REFLECTION_HEIGHT);

I am unable to work out what is wrong, and why the texture is not displaying anything rendered to it.

Things I know are not wrong:

I am definitely drawing and texturing the water itself correctly. I can use any pre-loaded texture and texture the water just fine: enter image description here

Also, Objects being rendered to the FBO have the correct translations, rotations, etc. If I don't bind any framebuffer, the foliage intended for the FBO is drawn (and seen) on my screen correctly.


Solution

  • So i realise this is a super old question that probably nobody cares about anymore, but i recently found myself here after doing the same tutorial and having similar problems.

    After exercising a bit of google foo, i realised i had made a very basic error in my code that could be the same solution.

    I simply wasn't doing;

    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    

    while is was the frame buffer object being used, before filling it up again:

    I just went ahead and put it at the end of the bind frame buffer function and i worked!

     private void bindFrameBuffer(int frameBuffer, int width, int height){
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);//To make sure the texture isn't bound
            GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
            GL11.glViewport(0, 0, width, height);
            System.out.println("Bound");
            if(GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER) == GL30.GL_FRAMEBUFFER_COMPLETE) {
                System.out.println("Frame buffer setup is complete: " + GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER));
            }
            System.out.println("Error: " + GL11.glGetError());
        }
    

    Might not be the same problem as my error was particularly basic, but worth a try.

    Does anyone know if this solution is correct, or is it a band aid over a larger problem?