Search code examples
opengl

How to efficiently initialize texture with zeroes?


I need to initialize an OpenGL 2D texture with zeroes.

Why? I render to this texture with OpenCL. Roughly, rendering stages are:

  1. Create RGBA texture, initialize with zeros (so it contains transparent black pixels)
  2. OpenCL: compute color of pixels where some objects are visible and write them to this texture
  3. OpenGL: add environment mapping to the transparent pixels and display final image

I therefore do not need to pass any actual texture data to glTexImage2d. But according to the spec, when I pass data=NULL, the texture memory is allocated but not initialized.

Allocating a client-side memory filled with zeroes and passing to glTexImage2D is not a very good option although only one I can think of.

EDIT: I actually want to init only alpha component (RGB will get overriden anyway), but I doubt this make the situation any easier.


Solution

  • There are several ways to do this:

    1: Given a width and a height for a texture:

    std::vector<GLubyte> emptyData(width * height * 4, 0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, &emptyData[0]);
    

    For maximum efficiency, you should leave some time between when you call this and when OpenCL starts its work.

    2: Attach it to an FBO and use glClearBuffer.

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); //Only need to do this once.
    glDrawBuffer(GL_COLOR_ATTACHMENT0); //Only need to do this once.
    GLuint clearColor[4] = {0, 0, 0, 0};
    glClearBufferuiv(GL_COLOR, 0, clearColor);
    

    This seems like it should be faster, since there is no CPU-GPU DMA going on. But the binding and unbinding of FBOs may introduce inefficiencies. Then again, it may not. Profile it to make sure.

    Note that this only works for image formats that can be used as render targets. So not compressed textures.

    3: Given sufficient drivers, you can use the new ARB_clear_texture extension:

    glClearTexImage(texture, 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
    

    Note that this only works for image formats whose data can be provided by standard pixel transfers. So not compressed formats.