Как эффективно инициализировать текстуру с нулями? - PullRequest
25 голосов
/ 25 августа 2011

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

Почему? Я рендеринг этой текстуры с OpenCL. Примерно этапы рендеринга:

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

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

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

РЕДАКТИРОВАТЬ: Я на самом деле хочу инициировать только альфа-компонент (RGB будет переопределен в любом случае), но я сомневаюсь, что это облегчает ситуацию.

Ответы [ 4 ]

37 голосов
/ 25 августа 2011

Есть несколько способов сделать это:

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.Но связывание и открепление FBO может привести к неэффективности.Опять же, это не может.Профилируйте его, чтобы убедиться.

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

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

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

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

5 голосов
/ 23 июля 2013

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

2 голосов
/ 29 июля 2016
  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 для копирования данных из графического процессора, этометод быстрее и лучше

    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 голос
/ 25 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...