¿Cómo inicializar eficientemente la textura con ceros?


Necesito inicializar una textura OpenGL 2D con ceros.

¿Por qué? Renderizo esta textura con OpenCL. Aproximadamente, las etapas de renderizado son:

  1. Crear textura RGBA, inicializar con ceros (por lo que contiene píxeles negros transparentes)
  2. OpenCL: calcula el color de los píxeles donde algunos objetos son visibles y escríbelos en esta textura
  3. OpenGL: agregar mapeo de entorno a los píxeles transparentes y mostrar la imagen final

Por lo tanto, no necesito pasar cualquier dato de textura real a glTexImage2d. Pero de acuerdo con la especificación, cuando paso data=NULL, la memoria de textura se asigna pero no se inicializa.

Asignar una memoria del lado del cliente llena de ceros y pasar a glTexImage2D no es una muy buena opción, aunque solo se me ocurre una.

EDIT: En realidad quiero iniciar solo el componente alfa (RGB se anulará de todos modos), pero dudo que esto facilite la situación.

 22
Author: genpfault, 2011-08-25

4 answers

Hay varias maneras de hacer esto:

1: Dado un ancho y una altura para una textura:

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

Para obtener la máxima eficiencia, debe dejar algún tiempo entre cuando llame a esto y cuando OpenCL comience su trabajo.

2: Adjúntalo a un FBO y usa 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);

Esto parece que debería ser más rápido, ya que no hay DMA CPU-GPU en marcha. Sin embargo, la vinculación y la desvinculación de las FBOS pueden introducir ineficiencias. Por otra parte, puede que no. Perfil a asegúrese.

Tenga en cuenta que esto solo funciona para formatos de imagen que se pueden usar como destinos de renderizado. Así que no texturas comprimidas.

3: Dados suficientes controladores, puede usar la nueva extensión ARB_clear_texture:

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

Tenga en cuenta que esto solo funciona para formatos de imagen cuyos datos pueden proporcionarse mediante transferencias estándar de píxeles. Así que no formatos comprimidos.

 32
Author: Nicol Bolas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-29 14:03:12

Solo un aviso: La nueva extensión GL_ARB_clear_texture (núcleo en 4.4) aborda específicamente este problema.

 5
Author: Ancurio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-11 18:46:08

Tal vez pueda establecer la textura como el destino de renderizado para la primera pasada y dibujar una primitiva negra. Puede ser más rápido ya que no hay transferencia de memoria entre la ram y la tarjeta gráfica.

 1
Author: neodelphi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-25 18:36:47
  1. glTexSubImage está lleno de toda la imagen:

    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. Use Pixel Buffer para copiar datos de la gpu, este método es más rápido y mejor

    I. 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);
    
 1
Author: freehyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-25 22:33:50