Подтвердить что ты не робот

Как эффективно инициализировать текстуру с нулями?

Мне нужно инициализировать 2D-текстуру OpenGL с нулями.

Почему? Я обрабатываю эту текстуру с помощью OpenCL. Примерно, этапы рендеринга:

  • Создайте текстуру RGBA, инициализируйте нулями (поэтому она содержит прозрачные черные пиксели).
  • OpenCL: вычисляет цвет пикселей, где некоторые объекты видны и записывают их в эту текстуру
  • OpenGL: добавить отображение среды в прозрачные пиксели и отобразить окончательное изображение

Поэтому мне не нужно передавать какие-либо фактические данные текстуры на glTexImage2d. Но согласно спецификации, когда я передаю данные = NULL, память текстуры выделяется, но не инициализируется.

Выделение памяти на стороне клиента, заполненной нулями и переходящей в glTexImage2d, не очень хороший вариант, хотя я могу только подумать.

EDIT: я действительно хочу инициализировать только альфа-компонент (RGB все равно будет перевыполнен), но я сомневаюсь, что это облегчит ситуацию.

4b9b3361

Ответ 1

Существует несколько способов сделать это:

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

Кажется, что это должно быть быстрее, поскольку отсутствует процессор DMA CPU-GPU. Но привязка и развязывание ФБО может привести к неэффективности. Опять же, это не так. Профилируйте это, чтобы убедиться.

Обратите внимание, что это работает только для форматов изображений, которые могут использоваться в качестве целей рендеринга. Так что не сжатые текстуры.

3: При наличии достаточных драйверов вы можете использовать расширение ARB_clear_texture:

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

Обратите внимание, что это работает только для форматов изображений, данные которых могут быть предоставлены стандартными передачами пикселей. Так что не сжатые форматы.

Ответ 2

Просто голова: новое расширение GL_ARB_clear_texture (ядро в 4.4) специально решает эту проблему.

Ответ 3

Возможно, вы можете установить текстуру как цель рендеринга для первого прохода и нарисовать черный примитив. Это может быть быстрее, так как между RAM и графической картой нет обмена данными.

Ответ 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;
    
  • используйте 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);