I've three images which I'm trying to render with my SpriteBatch and FrameBuffer.
These are the steps I'm doing.
- Clear the screen, depth and stencil buffers.
- Bind the FrameBuffer. See FrameBuffer.bind().
- Use my SpriteBatch to render three solid quads with different sizes and different positions.
- Unbind my FrameBuffer. See FrameBuffer.unbind().
- Bind my FrameBuffers colorTexture.
- Render my FrameBuffer with my SpriteBatch.
Here's some facts I know about the this problem
- The textures shows the right color. They are not white.
- The first texture I render is shown, while the other two isn't. If I change the order, the first texture still gets rendered.
- With three textures, I mean three separate texture ids.
- I've depth test enabled.
- No OpenGL error or FrameBuffer error is being thrown.
- When rendering using my SpriteBatch directly to the screen all three quads is shown.
- The size of my FrameBuffer is the size of my screen.
Here's how it's supposed to look like

Here's how it's looking with my framebuffer.

Here's how it's looking with my framebuffer and drawing the first texture two times. Still missing the other two textures. Position in not the problem.

Here's the code for my FrameBuffer :
// Stencil is broken currently broken, in my example. I'm not using any stencil buffers.
public FrameBuffer(int width, int height, boolean hasDepth, boolean hasStencil) {
this.width = width;
this.height = height;
frameBufferID = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);
if (hasDepth && hasStencil) {
int depthAndStencilBufferID = GL30.glGenRenderbuffers();
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthAndStencilBufferID);
GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH24_STENCIL8, width, height);
GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, depthAndStencilBufferID);
}
else if (hasDepth) {
int depthBufferID = GL30.glGenRenderbuffers();
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBufferID);
GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH_COMPONENT32F, width, height);
GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER, depthBufferID);
}
else if (hasStencil) {
int stencilBufferID = GL30.glGenRenderbuffers();
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, stencilBufferID);
GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_STENCIL_INDEX16, width, height);
GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, stencilBufferID);
}
colorTexture = new Texture(width, height);
colorTexture.bind();
GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, colorTexture.getTextureID(), 0);
int result = GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER);
//error handling
RenderUtil.unbindFrameBuffer();
}
private Texture colorTexture;
private int width, height;
private int frameBufferID, depthBufferID, stencilBufferID;
public void begin () {
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID);
GL11.glViewport(0, 0, width, height);
}
public void end () {
GL11.glViewport(0, 0, RenderingEngine.getWidth(), RenderingEngine.getHeight());
RenderUtil.unbindFrameBuffer();
RenderUtil.unbindTextures();
}
public Texture getColorTexture () {
return colorTexture;
}
public int getWidth () {
return width;
}
public int getHeight () {
return height;
}
Here's how I create a Texture if it's to any use :
private void loadTexture (ByteBuffer buffer, int textureID, int width, int height) {
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, width, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
}
There seems to be a problem in my SpriteBatch when switching texture. Here's how the switching works. I remind you, using my SpriteBatch to render to the screen gives my the wanted result. But rendering to a FrameBuffer doesn't work.
`
public void flush () {
flushes++;
buffer.flip();
MESH.setVertices(buffer);
if (lastTexture != null) {
lastTexture.bind();
}
MESH.draw();
buffer.clear();
}
/** Begins the SpriteBatch. */
public void begin () {
if (rendering) {
new IllegalStateException("You have to SpriteBatch.end() before calling begin again!").printStackTrace();
}
flushes = 0;
rendering = true;
shader.bind();
shader.setUniformMat4f("projection", camera.getCombined());
shader.setUniformVec4("color", color);
}
/** Ends the SpriteBatch, also flushes it. */
public void end () {
if (!rendering) {
new IllegalStateException("You've to SpriteBatch.begin before ending the spritebatch").printStackTrace();
}
rendering = false;
flush();
RenderUtil.unbindShaders();
RenderUtil.unbindTextures();
}
/** Switches the textures and flushes the old one.
* @param t */
private void switchTextures (Texture t) {
if (lastTexture != null) {
flush();
}
lastTexture = t;
}
` Going to create a small example. Should be up soon.
EDIT: Problem wasn't my FrameBuffer. Was my SpriteBatch.
hasStencilandhasDepthare both true? You try to bind attachments to DEPTH and STENCIL, but that will result in compatibility issues most of the time. You should add a third case that binds a packed depth+stencil attachment toGL_DEPTH_STENCIL_ATTACHMENTin that special case. An even bigger issue here is your use of a 16-bit stencil buffer, that's pretty much never going to work when you also have a depth buffer :-\ - Andon M. ColemanGL_DEPTH32F_STENCIL8. That is actually a particularly nasty format, hardware doesn't like 40-bit data, so what actually happens is you waste an additional 24-bits worth of data so that the packed depth+stencil is padded out to 64-bit total. I would honestly suggest you try a 24-bit depth buffer instead, because then you can useGL_DEPTH24_STENCIL8and not waste any memory/bandwidth. - Andon M. Colemanbegin (...), but it's not there. You need to clear your buffers while your FBO is bound, otherwise you're only clearing the color/stencil/depth buffer associated with your window. - Andon M. Coleman