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

Opengl 如何有效地用零初始化纹理?,opengl,Opengl,我需要用零初始化OpenGL 2D纹理 为什么??我用OpenCL渲染这个纹理。大致上,渲染阶段包括: 创建RGBA纹理,初始化为零(因此它包含透明的黑色像素) OpenCL:计算某些对象可见的像素的颜色,并将它们写入该纹理 OpenGL:将环境映射添加到透明像素并显示最终图像 因此,我不需要将任何实际纹理数据传递到glTexImage2d。但是根据规范,当我传递data=NULL时,纹理内存被分配但没有初始化 分配一个充满零的客户端内存并传递给glTexImage2D不是一个很好的选择,尽管我

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

为什么??我用OpenCL渲染这个纹理。大致上,渲染阶段包括:

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

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


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

    也许您可以将纹理设置为第一遍的渲染目标,并绘制一个黑色基本体。由于ram和图形卡之间没有内存传输,因此速度可能更快。

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

    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]);
    
    这似乎应该更快,因为没有CPU-GPU DMA正在进行。但固定资产运营商的绑定和解除绑定可能会导致效率低下。再说一次,可能不是。配置它以确保

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

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

    glClearTexImage(texture, 0, GL_BGRA, GL_UNSIGNED_BYTE, &clearColor);
    
    请注意,这仅适用于其数据可由提供的图像格式。所以不是压缩格式。

    只是提醒一下:新的(4.4中的核心)扩展专门解决了这个问题

  • 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;
    
  • 使用像素缓冲区从gpu复制数据,这种方法更快更好

    一,。初始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);
    
    二,

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

  • 说得好。但是我能用这种方法设置alpha=0吗?实际上我只想初始化alpha,我不想麻烦RGB组件。使用glClearColor和glClear可能更好。glClearColor接受alpha。从未听说过
    glClearBuffer
    。这是一个非常新的版本吗?与glClear相比,它有什么优势吗(或者后者甚至被弃用了)?@Christian:ClearBuffer的主要优势是可以清除特定的缓冲区。如果帧缓冲区中有多个缓冲区、多个渲染目标,则可能需要将不同的缓冲区清除为不同的颜色。或者根本不清楚。您不能使用
    glClear
    ;它将所有缓冲区清除为相同的清晰颜色
    glClear
    不是不推荐使用的,而
    glClearBuffer
    来自GL 3.0(没有扩展)。请注意,glClearTexImage仅在纹理存储之前已分配的情况下工作,使用对glTexImage*或glTexStorage*的调用。仅使用glBindTexture创建纹理是不够的。当然,这也适用于glTexSubImage2D。此外,glClearTexImage仅适用于非压缩格式。但我有一个问题。我可以看到ARB函数被映射(非零),并且定义为1。但是,即使应该使用glTexImage/glTexStorage/glTexCopy函数创建纹理存储(句柄为非零),我仍然会得到GL错误,即纹理中不存在GL错误。有什么想法吗?@StarShine:谢谢你提醒我压缩纹理清理。至于你的问题,这就是“问问题”按钮的作用。这是真的,但警告一句:你肯定想了解这一点。在我的系统上,glClearTexture比使用帧缓冲区和glClear/glClearBuffer慢得多。@Jagoly您使用GPU定时器查询正确地分析了吗?不,只是使用帧时间。不过,它不仅慢了一点;clearTexture(两次调用,rgb8+24位深度)花费的时间是clear的三倍多。我已经设置了帧缓冲区。仅深度(5x)的差异更大。
    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);