Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL Framebuffer with more than one texture

I want to render n texture in my program and store them for later usage. Therefore I use the OpenGL FramebufferObject.

At first I create an array with 128 textures like this

self.textures = glGenTexture(128)

The second step is a loop with 128 iterations in which I bind the texture at position i and render into it.

    glBindTexture(GL_TEXTURE_2D, self.texture[i])
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,  GL_TEXTURE_2D, self.texture[i], 0);
    renderScene()

The last step is another loop, the MainGameLoop in which I render a plane with one texture from the texture array.

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    gluLookAt(0,0,1,0,0,0,0,1,0)
    glEnable(GL_TEXTURE_2D)

    glBindTexture(GL_TEXTURE_2D, self.texture[i])

    glBegin(GL_QUADS)

    glNormal3f(0.0, 1.0, 0.0)
    glTexCoord2f(0.0, 0.0)
    glVertex3f(-1, 1, -1)
    glTexCoord2f(1.0, 0.0)
    glVertex3f(1, 1, -1)
    glTexCoord2f(1.0, 1.0)
    glVertex3f(1, -1, -1)
    glTexCoord2f(0.0, 1.0)
    glVertex3f(-1, -1, -1)

    glEnd();

    glDisable(GL_TEXTURE_2D)

But something went wrong, the screen stays black.

like image 543
glethien Avatar asked Mar 23 '26 02:03

glethien


1 Answers

A texture must not be bound when used as a color attachment to a framebuffer object. You however are binding it before attaching which of course breaks the whole thing.

The correct code would iterate through all multitexturing units and make sure the texture is not bound in any of them.

Update due to comment:

In your code you bind a texture name and set parameters for it

glBindTexture(GL_TEXTURE_2D, self.texture[i])
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST)

Then you initialize the texture object with null data

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

and finally attach it as a framebuffer attachment.

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,  GL_TEXTURE_2D, self.texture[i], 0);

The problem is, that now the texture is still selected as a data source, because it is bound. The texture must not be bound to any texturing unit, to work as a framebuffer color attachment. Also the FBO must be bound as render target somewhere.

renderScene()

Here's a small helper function that makes sure, a given texture object is not bound in any texturing unit:

def glhelperUnbindTexture(target, name):
    max_units = max(glGetInteger(GL_MAX_TEXTURE_UNITS),
                    glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS),
                    glGetInteger(GL_MAX_TEXTURE_COORDS))
    current_unit = glGetInteger(GL_ACTIVE_TEXTURE)

    for i in range(max_units):
        glActiveTexture(GL_TEXTURE0 + i)
        binding = glGetInteger( {GL_TEXTURE_1D: GL_TEXTURE_BINDING_1D,
                                 GL_TEXTURE_2D: GL_TEXTURE_BINDING_2D,
                                 GL_TEXTURE_3D: GL_TEXTURE_BINDING_3D,
                                 GL_TEXTURE_CUBE_MAP: GL_TEXTURE_BINDING_CUBE_MAP}[target])
        if binding == name:
             glBindTexture(target, 0) # this unbinds the texture from the texturing unit

    glActiveTexture(current_unit)
like image 101
datenwolf Avatar answered Mar 24 '26 15:03

datenwolf