The scenario
I'm creating a frame buffer object and binding a texture to colour attachment 0. I'm not using a depth buffer. After creating it, I unbind it.
At some point in time later, the frame buffer is bound, a triangle strip is rendered to it (some parts partially transparent), and then it's unbound again. This is repeated a number of times with different triangle strips.
Ultimately, what's drawn to the main frame buffer is a textured quad with the texture that's attached to the frame buffer object I created.
The problem
I'm finding that the partially transparent parts of the triangle strips drawn into the texture which overlap with other triangle strips aren't being blended properly. They appear to be blended with white rather than the colour that's already in the texture. Even if I fill the texture with solid green (for example), the colour being picked up while blending is still white.
Here's a few snippets of the code I'm using to do all of this:
Initialization
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &framebuffer_id);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Render To Texture (iterated on)
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// On the first render iteration, do_clear is true
if (do_clear)
{
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
}
// ... render the current triangle strip ...
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Render Texture To Main Framebuffer
// Set up the texture (making no assumptions about current state)
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Set up the vertex buffer (quad made up of triangle strip)
glBindBuffer(GL_ARRAY_BUFFER, vertices_id);
glVertexAttribPointer(VERTEX_ATTRIB_POSITION_TAG, 3, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(0));
glEnableVertexAttribArray(VERTEX_ATTRIB_POSITION_TAG);
glVertexAttribPointer(VERTEX_ATTRIB_TEXCOORD_TAG, 2, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(VERTEX_ATTRIB_TEXCOORD_TAG);
glVertexAttribPointer(VERTEX_ATTRIB_COLOR_TAG, 4, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(5 * sizeof(GLfloat)));
glEnableVertexAttribArray(VERTEX_ATTRIB_COLOR_TAG);
glVertexAttribPointer(VERTEX_ATTRIB_NORMAL_TAG, 3, GL_FLOAT, GL_FALSE, sizeof(MyRenderVertex), BUFFER_OFFSET(9 * sizeof(GLfloat)));
glEnableVertexAttribArray(VERTEX_ATTRIB_NORMAL_TAG);
// Draw the textured geometry
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Reset everything
glDisableVertexAttribArray(VERTEX_ATTRIB_POSITION_TAG);
glDisableVertexAttribArray(VERTEX_ATTRIB_TEXCOORD_TAG);
glDisableVertexAttribArray(VERTEX_ATTRIB_COLOR_TAG);
glDisableVertexAttribArray(VERTEX_ATTRIB_NORMAL_TAG);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(target, 0);
glActiveTexture(0);
An Example of What I'm Seeing
The parts where you see the white lines are where the triangle strips overlap. They should be partially transparent and blended with the black that was previously drawn.
Update
I've made a few discoveries since I posted this:
- The "white" part is actually fully transparent, so it'll just show the colour of whatever is rendered behind the texture
- I replaced the more complex triangle meshes with randomly placed squares that are made up of vertices which go from fully transparent on one side of the square to fully opaque on the other side, and I don't see the same blending problem. Here's a picture of the squares:
So it appears to be a problem with the triangle meshes I'm using and not the blending.
Actually, looking very closely at the "Good Blending" image, I can see that the fully opaque parts of a square are actually being lightened when another square is rendered over top of it. So the problem is there, it's just not quite as extreme.