-1

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.

Joehot200
  • 1,070
  • 15
  • 44
  • Try using glFramebufferTexture2D instead of glFramebufferTexture. Also try calling glGetError at some places, it might give you an idea where the problem is. – Kvaleya Nov 17 '15 at 16:30
  • @Kvaleya Could you please explain what parameters I would put for `glFramebufferTexture2D()`? I seem to find conflicting answers on the internet. – Joehot200 Nov 17 '15 at 17:01
  • Parameters should be the same as glFramebufferTexture, the only new one is the texturetarget, that should be GL_TEXTURE_2D as that is the type of texture you want to attach. – Kvaleya Nov 17 '15 at 17:09
  • @Kvaleya Thanks for the suggestion. I've done as you suggested, and have found errors. Please check my edits. – Joehot200 Nov 17 '15 at 17:25
  • I've never encountered a stack overflow in opengl, but from what I've googled it seems that the common cause is using glPushMatrix and not popping it afterwards. Another thing you could try is to use a different format for the color and depth attachment. When you're creating the renderbuffer you assign a GL_DEPTH_COMPONENT format, which is not listed as a required format for renderbuffers on [this page](https://www.opengl.org/wiki/Image_Format#Texture_and_Renderbuffer). Also try using some RGBA color format for the color attachment, although not sure whether it will have any effect. – Kvaleya Nov 17 '15 at 20:20
  • @Kvaleya Apologies for the red herring, the Stack Overflow was, after hours of de-bugging, actually a problem elsewhere in my code. glGetError() now returns a 0. There are no errors now that I can see. – Joehot200 Nov 17 '15 at 22:28
  • are you clearing your framebuffer? If not, do it (color and depth) – j-p Nov 18 '15 at 09:53

1 Answers1

1

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?

Boc Dev
  • 313
  • 2
  • 8
  • Honestly not sure, I'm not even sure if I have my OpenGL code any more! However, it certainly sounds like a reasonable solution, especially if you used the same tutorial. – Joehot200 Jun 09 '20 at 11:22