如何用零有效地初始化纹理?

时间:2011-08-25 18:07:48

标签: opengl

我需要用零初始化OpenGL 2D纹理。

为什么呢?我用OpenCL渲染到这个纹理。粗略地说,渲染阶段是:

  1. 创建RGBA纹理,用零初始化(因此它包含透明的黑色像素)
  2. OpenCL:计算某些对象可见的像素颜色并将其写入此纹理
  3. OpenGL:将环境映射添加到透明像素并显示最终图像
  4. 因此,我不需要将任何实际纹理数据传递给glTexImage2d。但根据规范,当我传递data = NULL时,纹理内存已分配但未初始化。

    分配一个充满零的客户端内存并传递给glTexImage2D并不是一个很好的选择,尽管我只能想到一个。

    编辑:我实际上只想初始化alpha组件(无论如何RGB都会被覆盖),但我怀疑这会让情况变得更容易。

4 个答案:

答案 0 :(得分:36)

有几种方法可以做到这一点:

1:给定纹理的宽度和高度:

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]);

为了获得最大效率,您应该在打电话和OpenCL开始工作之间留出一些时间。

2:将其附加到FBO并使用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);

这似乎应该更快,因为没有CPU-GPU DMA正在进行。但FBO的绑定和解除绑定可能会导致效率低下。然后,它可能不会。对其进行剖析以确保。

请注意,这仅适用于可用作渲染目标的图像格式。所以不是压缩纹理。

3:如果有足够的驱动程序,您可以使用新的ARB_clear_texture扩展程序:

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

请注意,这仅适用于standard pixel transfers可提供数据的图像格式。所以不是压缩格式。

答案 1 :(得分:5)

只是提前:新的GL_ARB_clear_texture(核心4.4)扩展专门解决了这个问题。

答案 2 :(得分:1)

也许您可以将纹理设置为第一遍的渲染目标并绘制黑色基元。它可能更快,因为ram和显卡之间没有内存传输。

答案 3 :(得分:1)

  1. glTexSubImage充满整个图片:

    GLfloat* pData = new GLfloat[1024*768*4];
    memset(pData, 0x00, 1024*768*4*sizeof(GLfloat));
    glBindTexture(GL_TEXTURE_2D, m_ImageTex);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 768, GL_RGBA, GL_FLOAT, pData);
    glBindTexture(GL_TEXTURE_2D, 0);
    delete pData;
    
  2. 使用 Pixel Buffer 从gpu复制数据,这种方法更快更好

    我。 init PBO

    glGenBuffers(1, &m_PixelBuffer);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_PixelBuffer);
    glBufferData(GL_PIXEL_UNPACK_BUFFER, SCREEN_WIDTH*SCREEN_HEIGHT*4*sizeof(GLfloat), NULL, GL_STATIC_DRAW);
    GLfloat* pData = nullptr;
    pData = (GLfloat*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    memset(pData, 0x00, 1024*768*4*sizeof(GLfloat));
    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    

    II。

    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_PixelBuffer);
    glBindTexture(GL_TEXTURE_2D, m_ImageTex);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGBA, GL_FLOAT, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);