2011-08-25 13 views
20

Necesito inicializar una textura OpenGL 2D con ceros.¿Cómo inicializar eficientemente la textura con ceros?

¿Por qué? Represento esta textura con OpenCL. A grandes rasgos, las etapas de generación son:

  1. Crear textura RGBA, inicializar con ceros (lo que contiene píxeles negros transparentes)
  2. OpenCL: el color de cómputo de píxeles, donde algunos objetos son visibles y escribirlos en esta textura
  3. OpenGL: agrega asignación de entorno a los píxeles transparentes y muestra la imagen final

Por lo tanto, no es necesario pasar ningún 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.

La asignación de una memoria del lado del cliente llena de ceros y que pasa a glTexImage2D no es una opción muy buena, aunque solo puedo pensar en una.

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

Respuesta

32

Hay varias maneras de hacer esto:

1: Dada una anchura 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 una máxima eficiencia, se debe dejar un poco de tiempo entre cuando se llama a esto y cuando OpenCL comienza su trabajo.

2: conéctelo a un FBO y 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); 

Esta parece que debería ser más rápido, ya que no hay CPU-GPU DMA pasando. Pero la unión y desvinculación de las OBF puede introducir ineficiencias. Por otra parte, puede que no. Perfíllo para estar seguro.

Tenga en cuenta que esto solo funciona para formatos de imagen que pueden utilizarse como objetivos de renderizado. Entonces no texturas comprimidas.

3: Teniendo en cuenta los conductores suficientes, puede utilizar la nueva ARB_clear_texture extensión:

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

Tenga en cuenta que esto sólo funciona para los formatos de imagen cuyos datos pueden ser proporcionados por standard pixel transfers. Entonces no formatos comprimidos.

+0

Nunca escuché sobre 'glClearBuffer'. ¿Es esto de una versión muy nueva? ¿Tiene alguna ventaja sobre 'glClear' (o este último incluso está en desuso) ?. –

+1

@Christian: La principal ventaja de ClearBuffer es que puedes borrar buffers específicos. Si tiene varios búferes en el búfer de fotogramas, múltiples objetivos de renderizado, entonces puede desear borrar diferentes colores diferentes. O no borrar alguno en absoluto. No puedes hacer eso con 'glClear'; borra todos los buffers al mismo color claro. 'glClear' no está en desuso, y' glClearBuffer' proviene de GL 3.0 (no hay extensión para él). –

+1

Tenga en cuenta que glClearTexImage solo funciona si el almacenamiento de textura se ha asignado previamente, utilizando una llamada a glTexImage * o glTexStorage *. Simplemente crear la textura usando glBindTexture no es suficiente. Pero esto también se aplica a glTexSubImage2D, por supuesto. – rdb

1

Quizás pueda establecer la textura como el objetivo de reproducción para la primera pasada y dibujar una primitiva negra. Puede ser más rápido ya que no hay transferencia de memoria entre el ram y la tarjeta gráfica.

+0

Buen punto. ¿Pero puedo lograr establecer alfa = 0 con este enfoque? De hecho, quiero iniciar solo alfa, no me molesto con los componentes RGB. – jirkamat

+3

El uso de glClearColor y glClear puede ser mejor. glClearColor acepta alfa. – neodelphi

5

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

+0

Esto es cierto, pero una palabra de advertencia: Definitivamente desea hacer un perfil de esto. En mi sistema, glClearTexture es MUCHO más lento que usar un framebuffer y glClear/glClearBuffer. – Jagoly

+0

@Jagoly ¿perfiló correctamente el uso de consultas de temporizador de GPU? – Ancurio

+0

No, solo usando el frametime. Sin embargo, no es solo un poco más lento; clearTexture (dos llamadas, rgb8 + profundidad de 24 bits) tardó más de tres veces más que clear. Ya tenía configurado el framebuffer. La diferencia fue aún mayor solo para la profundidad (5x). – Jagoly

0
  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. uso Pixel Buffer para copiar los 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); 
    
Cuestiones relacionadas