Проблема с отрисовкой OpenGL ES за кадром

Я использую класс PixelBuffer, описанный здесь http://www.anddev.org/android-2d-3d-graphics-opengl-tutorials-f2/possible-to-do-opengl-off-screen-rendering-in-android-t13232.html. В моем Renderer я использую GLU.lookAt для просмотра задней стороны 3D-объекта, но PixelBuffer, похоже, не возвращает буфер с задней стороной, а вместо этого по-прежнему показывает переднюю грань объекта. Что может быть причиной этого? Можно ли решить эту проблему?


person ppatidar    schedule 01.04.2014    source источник


Ответы (1)


Прежде всего, pbuffers устарели и не поддерживаются на устройствах Android с графическими процессорами Nvidia Tegra. Android имеет встроенные классы для рендеринга вне экрана с именами TextureView и SurfaceTexture, которые вы должны использовать, или вы можете использовать FBO. У меня есть коллекция статей, которые помогут:

http://montgomery1.com/opengl/

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

Задние грани — это другая концепция, которая зависит от направления намотки ваших треугольников, чтобы обеспечить отбраковку задних граней. Это не имеет ничего общего с рендерингом за кадром.

Обновление:

Добавление ссылки на пример кода, который показывает, как скопировать изображение текстуры в растровое изображение Android:

http://stackoverflow.com/questions/22683572/creating-a-bitmap-of-a-drawn-square-in-android-opengl-es-2-0/22693766#22693766
person ClayMontgomery    schedule 01.04.2014
comment
Извиняюсь за плохую терминологию. Я использую Android с поддержкой OpenGL ES1.1. У меня есть текстурированный куб, и под передней гранью я подразумевал грань куба по направлению к зрителю, а обратная грань - противоположная грань от зрителя, не видная ему. Я рисую это с помощью рендерера, и я устанавливаю рендерер на PixelBuffer. Причина для всего этого заключается в том, что я должен показывать геометрию в виджетах приложений, а виджеты приложений не поддерживают GLSurfaceView. Есть ли способ добиться этого? - person ppatidar; 02.04.2014
comment
Я делаю GLU.gluLookAt, чтобы показать другие лица зрителю, но pbuffer всегда возвращает растровое изображение, как будто вызов gluLookAt игнорируется. Когда я использую тот же рендерер в GLSurfaceView, он работает нормально, но тот же рендерер для PixelBuffer не работает. - person ppatidar; 02.04.2014
comment
Даже с OpenGL ES 1.1 лучше использовать расширение FBO, чем pbuffers. Задние поверхности определяются направлением намотки, а не тем, в какую сторону указывает gluLookAt(). Отсечение задней грани также должно быть включено. - person ClayMontgomery; 02.04.2014
comment
Спасибо. Ваше предложение об отсечении лица несколько сработало для меня, и теперь я вижу лицо объекта, который хочу. Я использовал мысль, что отсечение лица позволит мне видеть внутреннюю поверхность лица, а не внешнюю поверхность лица вдали от зрителя. Использование pbuffer также вызвало другую проблему, когда я изменил направление света на 180 градусов. Выделение лица не решило эту проблему. Нужно работать над этим и использовать FBO. Предоставлю информацию, если у меня получится. В прошлый раз, когда я проверял, FBO были доступны на iOS, но не на Android. - person ppatidar; 03.04.2014
comment
Клэй, проблема с освещением возникла из-за ошибки в моей программе. Я смотрел на реализацию FBO и прочитал следующее. Различные устройства Android поддерживают расширения OpenGL ES, поэтому, если вам нужно использовать приложения, создайте объекты FrameBuffer, необходимо проверить, поддерживает ли телефон расширение Framebuffer. Если даже FBO не поддерживается на всех телефонах, чем он отличается от использования PixelBuffer? - person ppatidar; 08.04.2014
comment
FBO необходимы для OpenGL ES 2.0, и они есть на 99% телефонов. Только расширение FBO для 1.1 может быть не реализовано, но я не видел ни одного, у которого его нет. - person ClayMontgomery; 08.04.2014
comment
Извинения. Я не программист графики. просто учусь из интереса. Я решил использовать FrameBufferObjects и поэтому читал об этом, но не получил большого прогресса. Вот у меня конкретные вопросы. 1) Можно ли использовать FBO без использования GLSurfaceView.Renderer? Если да, как я могу получить объект GL11. 2) После того, как моя сцена нарисована на FBO, как я могу прочитать ее как растровое изображение. Можно ли использовать glReadPixel? - person ppatidar; 13.04.2014
comment
Да, это возможно. Класс Android SurfaceTexture — это абстрактный FBO для версии 2.0. Я добавил ссылку выше к примеру кода для использования glReadPixels(). Чтобы создать поверхность EGL, которая находится за пределами экрана на Android, создайте SurfaceTexture и передайте ее в eglCreateWindowSurface(). Вам также следует обратить внимание на использование расширения изображения EGL и EGL_NATIVE_BUFFER_ANDROID. - person ClayMontgomery; 14.04.2014
comment
Я попытался реализовать FBO без использования SurfaceTexure, так как этот класс был добавлен в уровень API 11, и я также хочу поддерживать минимальный уровень API 7. Я использовал eglCreatePbufferSurface, а затем получил объект GL из eglContext.getGL. Затем я получил объект GLExtentionPack и использовал FrameBuffer. Это работает на уровне API 7 и 8, но когда я меняю уровень API 14, я получаю GLError 0x500. Эквивалентно ли использование eglCreatePbufferSurface использованию PBuffers? - person ppatidar; 22.06.2014
comment
Да, именно так вы создаете pbuffer. Менее 1% всех устройств Android работают с API 8 или ниже. developer.android.com/about/dashboards/index.html#OpenGL - person ClayMontgomery; 22.06.2014
comment
Спасибо. Поскольку GLExtentionPack также доступен на уровне API ниже 8, должен быть способ получить объект GL без использования SurfaceTexture или PBuffer? Ниже приводится то, что я делаю прямо сейчас. Но я думаю, вы говорите, что это PBuffer [код] eglSurface = egl.eglCreatePbufferSurface(eglDisplay, eglConfig, attribList); egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); gl10 = (GL11) eglContext.getGL(); логическое значение ctxSupportsExt = checkIfContextSupportsFrameBufferObject(gl10);[/code] - person ppatidar; 23.06.2014
comment
Pbuffer может быть лучшим вариантом для таких старых API. - person ClayMontgomery; 23.06.2014
comment
Я преобразовал свою программу Opengl ES 1.x в программу Opengl ES2.0. Он отлично работает как активность. Затем я попробовал SurfaceTexture для рисования за кадром. API SurfaceTexture предписывает использовать цель привязки GL_TEXTURE_EXTERNAL_OES в glBindTexture вместо GL_TEXTURE_2D, поэтому замените GL_TEXTURE_2D на GL_TEXTURE_EXTERNAL_OES, но теперь я получаю сообщение об ошибке GL_INVALID_ENUM в вызове glBindTexture, поскольку у него есть цель GL_TEXTURE_EXTERNAL_OES. В документации Khronos для glBindTexture нет ссылки на GL_TEXTURE_EXTERNAL_OES. Будем признательны за вашу помощь в этом. Я мог бы снова сделать OPENGLES 2 с PixelBuffer, но не с SurdaceTextur - person ppatidar; 18.08.2014
comment
Не используйте GL_TEXTURE_EXTERNAL_OES, потому что это для внешних текстур, таких как цветовое пространство YCrCb, как с камеры. Класс SurfaceTexture отлично работает с GL_TEXTURE_2D. Документация Google полна дыр и очень вводит в заблуждение. - person ClayMontgomery; 18.08.2014
comment
Спасибо. Я использовал GL_TEXTURE_2D. Сейчас он работает только в эмуляторе, а не на устройстве. Также это не работает в эмуляторе, если я использую действие конфигурации для своего виджета. Просто вылетает эмулятор. Я также использовал код, предложенный вами в другом сообщении здесь .com/questions/22776290/. Правильна ли инициализация с жестко запрограммированным идентификатором текстуры 1 (как вы использовали в посте)? Имеет ли вообще какое-либо значение этот идентификатор текстуры? мой код работает в эмуляторе, даже если я передаю 0 в качестве идентификатора текстуры в конструктор SurfaceTexture. - person ppatidar; 25.08.2014
comment
Устройства Samsung известны глючными драйверами OpenGL ES. Этот идентификатор текстуры действительно должен быть сгенерирован с помощью glGenTextures(). - person ClayMontgomery; 25.08.2014