I have an game which uses FBOs to do 2d rendering to compose multiple layers. This works fine on the windows machines I’ve tested it on (all nVidia cards) but on a friends laptop it produces corrupt output. It’s a Mac with an ATi Radeon 9600 XT.
I’ve distilled this down to a minimum reproduction case, which does something like:
- Create single FBO
- Create two empty textures to use with FBO
- Render:
– Bind FBO
– Attach texture 1 to FBO
– Draw into texture 1
– Attach texture 2 into FBO
– Draw into texture 2
– Detach FBO
– Draw texture 1 to screen
– Draw texture 2 to screen
Code:
public FboTest5() throws Exception
{
final boolean fboCapable = GLContext.getCapabilities().GL_EXT_framebuffer_object;
if (!fboCapable)
throw new RuntimeException("FBOs not supported
");
sprite = new Sprite("Textures/Tails.png");
x = 200;
y = 200;
// Gen FBO
IntBuffer buffer = BufferUtils.createIntBuffer(1);
EXTFramebufferObject.glGenFramebuffersEXT(buffer);
fboId = buffer.get();
if (fboId == 0)
throw new RuntimeException("Couldn't create FBO");
// Gen textures
shadowTex = createBlankTexture(256, 256);
fullbrightTex = createBlankTexture(256, 256);
Util.checkGLError();
}
public void render()
{
Util.checkGLError();
setDefaultState();
// Shadow RTT
// Bind fbo
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, fboId);
// Attach our target texture
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
EXTFramebufferObject.glFramebufferTexture2DEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
GL11.GL_TEXTURE_2D, shadowTex, 0);
checkCompleteness(fboId);
{
GL11.glViewport(0, 0, 256, 256);
setOrtho(Testbed.SCREEN_WIDTH, Testbed.SCREEN_HEIGHT);
GL11.glClearColor(1f, 1f, 1f, 0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glColor4f(0f, 0f, 0f, 1f);
sprite.draw(x-20, y+40);
sprite.draw(x+20, y+40);
}
// Fullbright RTT
// Attach our target texture
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
EXTFramebufferObject.glFramebufferTexture2DEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
GL11.GL_TEXTURE_2D, fullbrightTex, 0);
checkCompleteness(fboId);
{
GL11.glViewport(0, 0, Testbed.SCREEN_WIDTH, Testbed.SCREEN_HEIGHT);
setOrtho(Testbed.SCREEN_WIDTH, Testbed.SCREEN_HEIGHT);
GL11.glClearColor(0.4f, 0.4f, 0.8f, 0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
// Normal, full colour sprite
GL11.glColor4f(1f, 1f, 1f, 1f);
sprite.draw(x, y);
sprite.draw(x-20, y);
sprite.draw(x+20, y);
}
// Release fbo
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
// Final framebuffer render
GL11.glViewport(0, 0, Testbed.SCREEN_WIDTH, Testbed.SCREEN_HEIGHT);
GL11.glClearColor(0.4f, 0.4f, 0.8f, 0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
{
setOrtho(Testbed.SCREEN_WIDTH, Testbed.SCREEN_HEIGHT);
// Fullbright RTT
// draw RTT result as whole screen quad
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, fullbrightTex);
float width = Testbed.SCREEN_WIDTH;
float height = Testbed.SCREEN_HEIGHT;
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glColor4f(1, 1, 1, 0.5f);
GL11.glTexCoord2f(0f, 0f);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1, 0f);
GL11.glVertex2f(width, 0);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(width, height);
GL11.glTexCoord2f(0f, 1);
GL11.glVertex2f(0, height);
}
GL11.glEnd();
}
// Shadow RTT
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, shadowTex);
float width = Testbed.SCREEN_WIDTH;
float height = Testbed.SCREEN_HEIGHT;
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glColor4f(1, 1, 1, 0.5f);
GL11.glTexCoord2f(0f, 0f);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1, 0f);
GL11.glVertex2f(width, 0);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(width, height);
GL11.glTexCoord2f(0f, 1);
GL11.glVertex2f(0, height);
}
GL11.glEnd();
}
}
}
The full code is here: http://www.triangularpixels.com/Junk/FboTest5.java
I’m a bit of a n00b with FBOs but as far as I can tell this is correct usage of an fbo. My only hint so far is that it seems to be related to having two render-to-texture passes - if I have only a single pass (and a single target texture) then it works as expected.
Any hints would be greatly appreciated, thanks.