Чтение данных с помощью glReadPixel () с мультисэмплингом

В настоящее время я пытаюсь прочитать данные пикселей из буфера кадра, чтобы захватить экран в IOS. Команда GlreadPixels отлично работает при использовании следующего кода для настройки буфера кадра: -

//buffers
// Create a depth buffer that has the same size as the color buffer.
glGenRenderbuffersOES(1, &m_depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, width, height);

// Create the framebuffer object.

glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
                             GL_RENDERBUFFER_OES, m_colorRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES,
                             GL_RENDERBUFFER_OES, m_depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);

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

glGenFramebuffersOES(1, &sampleFramebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer);

//GLuint sampleColorRenderbuffer;
glGenRenderbuffersOES(1, &sampleColorRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleColorRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_RGBA8_OES, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, sampleColorRenderbuffer);

//glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_RGBA8_OES, width, height);
//glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, sampleColorRenderbuffer);

GLuint sampleDepthRenderbuffer;
glGenRenderbuffersOES(1, &sampleDepthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleDepthRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_DEPTH_COMPONENT24_OES, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, sampleDepthRenderbuffer);
//glBindRenderbufferOES(GL_RENDERBUFFER_OES,sampleColorRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer);

Я использую следующий код для чтения данных пикселей: -

CGRect screenBounds = [[UIScreen mainScreen] bounds];

int backingWidth = screenBounds.size.width;
int backingHeight =screenBounds.size.height;

glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
NSInteger myDataLength = backingWidth * backingHeight * 4;

buffer= (GLuint *) malloc(myDataLength);
glReadPixels(0, 0, backingWidth, backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

Есть идеи, как получить правильные пиксельные данные с помощью метода множественной выборки .... или я что-то делаю не так? Пожалуйста, веди меня в правильном направлении. Спасибо


person Tornado    schedule 29.07.2011    source источник


Ответы (1)


При использовании FBO с множественной выборкой вы не можете просто прочитать буфер выборки (поскольку он не содержит простых пикселей). Сначала вам нужно преобразовать образцы буферов в один буфер.

Вы делаете это, создавая другой FBO без мультисэмплирования (назовем его resultFramebuffer) с необходимым хранилищем рендеринга, которое вы хотите прочитать, а затем вызываете:

glBindFramebuffer(GL_READ_FRAMEBUFFER, sampleFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resultFramebuffer);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);

И затем вы читаете из буфера результатов (конечно, фактические имена констант и функций могут содержать OES или APPLE). Если вам не нужны окончательные значения глубины, буфер результатов не нуждается в буфере рендеринга глубины.

РЕДАКТИРОВАТЬ: Как вы написали в своем комментарии и в том, что я искал, есть специальная функция glResolveMultisampleFramebufferAPPLE, которую вы должны использовать вместо glBlitFramebuffer. Остальное остается прежним.

person Christian Rau    schedule 29.07.2011
comment
эй, сначала glBlitFramebuffer () отсутствует в OES ... также glreadpixels () считывает данные только из фреймбуфера ... я нашел glreadbuffer () для чтения non fbo, но он также недоступен в OES - person Tornado; 30.07.2011
comment
@Tornado Во-первых, если поддерживаются мультисэмплированные FBO, также должна быть поддержка glBlitFramebuffer, в противном случае мультисэмплированные FBO просто бесполезны, так как тогда вы не можете разрешить выборочные буферы, как сказано выше (может быть, это расширение APPLE, как мультисэмплированные FBO?). Если glReadPixels не может читать из FBO, то как работает ваш первый пример кода? Если вы не хотите читать из FBO, то в чем проблема? Вы должны объяснить, для чего нужен ваш FBO, если вы не хотите читать его данные. - person Christian Rau; 30.07.2011
comment
хммм, я снова проверю glBlitFramebuffer () на наличие яблока ... фактически я новичок в части OpenGl .... относительно glreadpixels () я говорил, что он читает только из FBO .. я был обеспокоен чтением данных пикселей из вашего resultFramebuffer ... эй, я проверю все снова, скоро поговорим ... спасибо за объяснение - person Tornado; 30.07.2011
comment
@Tornado Вам просто нужно привязать resultFramebuffer (который является стандартным FBO без мультисэмплирования, как в вашем первом примере) в качестве текущего FBO (используя glBindFramebuffer), а затем вы можете читать из него, как вы это делали в своем первом немультисэмплированном пример. Единственное, что вы делаете, это копируете мультисэмплированный FBO в другой FBO и читаете из него. - person Christian Rau; 31.07.2011
comment
обнаружил, что есть функция с именем glResolveMultisampleFramebufferAPPLE (), которая используется для блиттинга .... сейчас я создаю многосэмплированный FBO с именем sampleframebuffer, а затем привязываю его как текущий FBO, затем я использовал glBindFramebufferOES (GL_READ_FRAMEBUFFER_APPLE, sampleFramebuffer); glBindFramebufferOES (GL_DRAW_FRAMEBUFFER_APPLE, кадровый буфер); glResolveMultisampleFramebufferAPPLE (); glBindFramebufferOES (GL_FRAMEBUFFER_OES, кадровый буфер); код - person Tornado; 01.08.2011
comment
@Tornado Звучит разумно. Извините, я не знал, что в ES есть специальная функция для разрешения мультисэмплов. - person Christian Rau; 01.08.2011
comment
даже я не уверен, что это сработает или нет, но я попробую это .... но в Opengl ES нет такой функции glBlitFramebuffer () .... - person Tornado; 01.08.2011
comment
эй, это сработало, но FPS упал с 30 до 2-3 .... снижает ли glreadpixels () FPS? - person Tornado; 02.08.2011
comment
@Tornado Может быть, помните, что вы копируете большой кусок памяти из графического процессора в память процессора (хотя я не уверен в аппаратной архитектуре iDevice, я уверен, что должна быть копия). Но если бы он работал со скоростью 30 кадров в секунду в примере без мультисэмплирования WITH glReadPixels, это было бы немного большим падением производительности. - person Christian Rau; 02.08.2011
comment
Я проверил fps с кодом без мультисэмплинга с glReadPixels, он также очень меньше 3-4 fps ... я не проверял это раньше, так как меня больше интересовало получение данных пикселей с помощью метода множественной выборки ... любая идея, как Могу ли я увеличить FPS. 20 кадров в секунду было бы достаточно .. !! - person Tornado; 02.08.2011
comment
@Tornado Я не знаю, действительно ли вам нужно снимать каждый кадр. Разовое снижение производительности было бы приемлемо. В противном случае может помочь выполнение асинхронного чтения с использованием PBO, хотя я не знаю, поддерживается ли оно в ES или iHardware позволяет вам получать от этого прибыль. - person Christian Rau; 02.08.2011
comment
Нет поддержки PBO в ios (apple) .. уже проверено ... эй, синхронное чтение из фреймбуфера поможет повысить производительность? я могу попробовать это, но не знаю как ... позвольте мне поработать над этим - person Tornado; 02.08.2011