Problem: Draw Framebuffer on Framebuffer

I am new to OpenGL but I have some knowledge already about it.
My problem:
I created two FBOs with the same size. The first FBO was rendered to the second FBO and the second FBO was rendered to the screen. It seemed like there was no problem but when I changed the size of the first FBO to half size the drawn content on the first FBO was scaled by the value 0.5.

To better understand this I have some screenshots:
Without problems:

With scaling problem:

red: second FBO
gray: first FBO
black: background

You forgot to call glViewport() to update to the new resolutions?

Probably theagentd has the answer, however, more than thinking in terms or FBO, you should think in terms of attachments, that is, you set the size of the color attachment 0, you render the color att 0 of FBO a to the color att 1 of FBO b

theagentd I checked the code again and I was using glViewport before rendering to foreign FBO so that’s not the problem.

elect what exactly do you mean? Can you show me the lines of code so I can recheck?

I created two FBOs with the same size. The first FBO was rendered to the second FBO and the second FBO was rendered to the screen.

The FBO has no size, its attachments have. You don’t render one FBO to another, you render/splash/blit one of its attachment to another attachment (that may belong to another FBO or not).

I guess it is better if you show us some of your code :wink:

Sure I can.

First of all this is how I set up my Display:

Display.setDisplayMode(new DisplayMode(960, 640));
Display.create();
glViewport(0, 0, this.gameWindow.getWidth(), this.gameWindow.getHeight());

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, this.gameWindow.getFrameBufferSize().width, this.gameWindow.getFrameBufferSize().height, 0, -1, glMatrixMode(GL_MODELVIEW);

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glDisable(GL_DEPTH_TEST);

Here is the code how I create/load a texture:

int ID = glGenTextures();
glBindTexture(GL_TEXTURE_2D, ID);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

Texture texture = new Texture();
texture.width = image.getWidth();
texture.height = image.getHeight();
texture.ID = ID;
texture.bufferImage = image2;

To create a FBO and attach texture to it I do this:

public SpriteBatch(Texture texture) {
	this.texture = texture;

	if (!GLContext.getCapabilities().GL_EXT_framebuffer_object) {
		System.exit(0);
	}
	// create frame buffer
	this.FBO = glGenFramebuffersEXT();
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this.FBO);

	// depth buffer
	this.depthBuffer = glGenRenderbuffersEXT();
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this.depthBuffer);

	// allocate space for the renderBuffer
	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, texture.getWidth(), texture.getHeight());

	// attach depth buffer to FBO
	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
		this.depthBuffer);

	// attach texture to the FBO
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture.getID(), 0);
}

To render a FBO(the texture which is attached to it) to another FBO I handle it like everey other texture:

public void draw(Texture texture, Rectangle dstRect, Color color) {
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this.FBO);
	glPushAttrib(GL_VIEWPORT_BIT);
	glViewport(0, 0, this.frameBuffer.getWidth(), this.frameBuffer.getHeight());

	texture.bind();
	glTranslatef(position.x, position.y, 0);
	glBegin(GL_QUADS);
	glColor4f((float) color.r / 255F, (float) color.g / 255F, (float) color.b / 255F, (float) color.a / 255F);

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

	glTexCoord2f(0, 1);
	glVertex2f(0, texture.getHeight());

	glTexCoord2f(1, 1);
	glVertex2f(texture.getWidth(), texture.getHeight());

	glTexCoord2f(1, 0);
	glVertex2f(texture.getWidth(), 0);

	glEnd();
	glLoadIdentity();
	texture.unbind();

	glPopAttrib();
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

And finally render to Display:

glViewport(0, 0, Display.getWidth(), Display.getHeight());

// I use translate and scale because otherwise it would be rendered mirrored (maybe you have a solution for that)
this.frameBuffer.bind();
glTranslatef(0, this.frameBuffer.getHeight(), 0);
glScalef(1, -1, 0);
glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);

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

glTexCoord2f(0, 1);
glVertex2f(0, this.frameBuffer.getHeight());

glTexCoord2f(1, 1);
glVertex2f(this.frameBuffer.getWidth(), this.frameBuffer.getHeight());

glTexCoord2f(1, 0);
glVertex2f(this.frameBuffer.getWidth(), 0);

glEnd();
glLoadIdentity();

I think that should be all of what you need. If you still need something then let me know. :wink:

If your framebuffer setup is correct, then it’s probably your texture coordinates. I’m guessing that the texture you’re rendering to is still full resolution.

This is my new guess:

  1. You have a window-sized texture.
  2. You set the viewport to only cover a small portion of the entire texture you draw to and render to it.
  3. When reading the FBO, you read the entire texture instead of just the small portion you drew to.

Thank you @theagentd and @elect for your help. Point 3 of your guesses was the problem. I fixed it and it works fine now. :wink: