Сохранение содержимого заднего буфера после eglSwapBuffers

Я реализую в Android и собственном С++ рисование сцены для Android, используя egl 1.1. В настоящее время используется Android glSurfaceView, который позволяет мне рисовать в задний буфер, который отображается в конце «onDrawFrame», когда задний буфер и передний буфер меняются местами.

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

Другими словами, мне нужно строить сцену поэтапно. В определенный момент во время рендеринга я решаю, что пришло время, и вызываю eglSwapBuffers, который отображает нарисованное содержимое из заднего буфера, но когда я продолжаю писать, очевидно, я пишу в «бывший передний буфер», который не синхронизирован. .. (не содержащий того, что я нарисовал до сих пор).

Насколько я вижу, мой единственный вариант - скопировать задний буфер перед заменой. псевдо:

  1. Рисовать в задний буфер
  2. Копировать задний буфер во временный буфер
  3. Обмен
  4. Копировать временный буфер в (новый) задний буфер
  5. Нарисуйте больше объектов в заднем буфере
  6. И так далее...

Мой вопрос: есть ли способ выполнить шаги 2 и 4?

  • Полезен ли glCopyPixels в этом случае? пример?
  • Is glBlitFramebuffer?

Или я неправильно подхожу ко всему этому?

Вещи, которые я уже сделал:

  • Я попытался изменить EGL_SWAP_BEHAVIOR на EGL_BUFFER_PRESERVED, но это работает только на определенных устройствах (как описано в заметки Хроноса):

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

  • Перерендерить сцену в каждом кадре - невозможно. Я много раз читал, что это рекомендуется.

person Dror Fichman    schedule 29.05.2014    source источник


Ответы (1)


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

Однако я могу придумать потенциально лучший подход, по крайней мере, если OES_framebuffer_object доступен:

  1. рисовать в текстуру или пользовательский буфер рендеринга
  2. рендерить текстуру в ОБРАТНЫЙ буфер/перемещать рендербуфер в ОБРАТНЫЙ буфер
  3. обмен
  4. обновить текстуру/рендербуфер
  5. рендерить текстуру в ОБРАТНЫЙ буфер/перемещать рендербуфер в ОБРАТНЫЙ буфер
  6. обмен
  7. [... и так далее ...]

Таким образом, у вас не будет цикла копирования/обновления/копирования/подкачки с двумя копиями на кадр, а только обновление/копирование/подкачка с одной дополнительной копией.

person derhass    schedule 29.05.2014
comment
Спасибо за ответ. Не могли бы вы немного уточнить? Какой метод следует использовать для шагов 1,2? Я очень новичок в использовании gl (перенос кросс-платформенного кода на Android .. - пытаюсь найти альтернативу ios 'presentRenderbuffer') - person Dror Fichman; 01.06.2014
comment
@DrorFichman: Возможно, вам поможет эта вики-страница GL. Он объясняет основы FBO (и это также относится к GLES, там он немного более ограничен). Итак, когда ваша программа запускается, вы создаете FBO, подключаете буфер рендеринга или текстуру в качестве цветового буфера. Возможно, вам также нужен буфер глубины. На шаге 1 вы просто привязываете FBO, и весь рендеринг будет выполняться с ним. На шаге 2 вы либо используете glBlitFramebuffer, либо, если вы прикрепили текстуру, а не буфер рендеринга, вы просто визуализируете полноэкранный четырехугольник с примененной текстурой. - person derhass; 03.06.2014