Создание шейдеров OpenGL в NativeActivity

Я изменил образец NDK с нативной активностью, включив в него код OpenGL из примера hello-gl2. Я обрабатываю сообщение APP_CMD_INIT_WINDOW, а затем пытаюсь создать шейдеры. Создание шейдера завершается неудачно, и я пытаюсь получить информацию через getShaderInfoiv, но это также не удается.

Итак, мой вопрос: как я могу создать шейдер OpenGL ES 2.0 в чистом нативном приложении для Android?

P.S. Я знаю, что создание шейдера может завершиться ошибкой, если вы используете Java GLSurfaceView и не создаете их в правильном потоке, но, глядя на образец собственной активности, кажется, что он имеет только один поток!


person Mark Ingram    schedule 06.01.2012    source источник
comment
Извините за, возможно, бесполезный вопрос, но вы каким-то образом инициировали EGL? Я думаю, что движок OpenGL вообще не готов принимать ваши запросы (это может объяснить тихий сбой вызова getShaderInfoiv). В случае, загружена ли библиотека OGL 2.0?   -  person Maurizio Benedetti    schedule 07.01.2012
comment
Не имея опыта разработки нативных OpenGL, я предполагаю, что следующий пример с нативной активностью оставит вас в контексте OpenGL ES 1.0. В примере hello-gl2 выбор конфигурации OpenGL ES 2.0 выполняется в коде Java.   -  person harism    schedule 09.01.2012
comment
Да, это тоже моя забота. Я мог бы попробовать перенести код с Java на C++.   -  person Mark Ingram    schedule 09.01.2012


Ответы (2)


Конечно, можно создать шейдер OpenGL ES 2.0 в родном приложении для Android. Главное — использовать правильный контекст OpenGL ES 2.0. Я сделал что-то подобное в своем приложении, а именно инициализировал контекст EGL в нативной части, а затем создал (и использовал) шейдеры только в нативном коде. Основываясь на том, что мне удалось сделать, я предполагаю, что то, что вы хотите сделать, также вполне возможно.

Поскольку у меня была точка входа в коде Java (механизм NativeAcvity не использовался), мне также пришлось передать собственный дескриптор окна (EGLNativeWindowType) из java в C++, чтобы создать поверхность EGL в собственном коде. Однако, поскольку вы хотите просто изменить пример NativeActivity, вы можете использовать engine->app->window для создания поверхности EGL, как показано в примере NativeActivity main.c.

Хорошо, как создать правильный контекст OpenGL ES 2.0 в нативном коде? Я только что внес два изменения в файл main.c в образце NativeActivity и проверил, все ли работает.

Во-первых, использовались следующие атрибуты EGL

const EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //important 
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};

in eglChooseConfig(display, attribs, &config, 1, &numConfigs);.

Во-вторых, позже при создании контекста использовалось

const EGLint attrib_list [] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};

in context = eglCreateContext(display, config, NULL, attrib_list);

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

I/native-activity(  955): Details: [Version: OpenGL ES 2.0 1403843], [Vendor: Qualcomm], [Renderer: Adreno 205], [Extensions: GL_AMD_compressed_3DC_texture GL_AMD_compressed_ATC_texture ... ]

Надеюсь, поможет!

person youri    schedule 13.01.2012
comment
Спасибо - это звучит именно то, что я ищу. Я проверю, когда вернусь домой. - person Mark Ingram; 16.01.2012
comment
Эти 2 изменения прибили его. Спасибо! - person Mark Ingram; 18.01.2012
comment
Я рад, что смог помочь! Я только жалею, что написал ответ так поздно, что не получил награду ;) - person youri; 19.01.2012

Интересно, почему вы решили перейти на полное нативное решение, обычно вы оставляете «нативным» только ваш «тяжелый компонент», такой как ваш движок рендеринга, движок ИИ, физический движок, и вы сохраняете «уровень устройства». вплоть до части Java.

Таким образом, огромным преимуществом является портативность. Если вы строите все в NDK, то вам придется заново изобретать велосипед, если вы хотите перенести свою игру/программу на Iphone, а если вы сохраните «ядро» на C, а дополнительные слои на Java, вам придется переписать только легкая часть проблемы.

В такого рода решениях у меня большой опыт, так как мой 3D-движок (PATRIA 3D) построен на собственном коде, который можно портировать с Android NDK на Iphone Objective C (плюс Windows/Linux/Mac OSx). В конце концов, мой код представляет собой полностью совместимый C89 + OpenGL2.0, который можно скомпилировать прямо (с небольшими изменениями) на Android (с использованием android ndk-build) и Iphone (XCODE).

Следуя этому подходу, движок и фактическое рисование выполняются в одном и том же потоке, назовем его основным потоком.

Если вам нужно несколько потоков в вашем приложении:

A - Держите рисунок на основном (основном) B - Создайте новые потоки на Java, не делайте этого на C (при переносе на другую платформу вы строите многопоточность на новом слое)

Что касается шейдеров, решение таким образом очень простое, поскольку поверхность и инициализация OpenGL выполняются Java с использованием стандартной библиотеки EGL.

Поверьте мне, если вы можете написать один раз и использовать на обеих платформах, Android и Iphone, вы удвоите количество «клиентов», это то, что вы не можете игнорировать, это потенциально может удвоить ваш доход.

Я надеюсь, что это поможет в некотором роде.

person Maurizio Benedetti    schedule 11.01.2012
comment
Кажется, это очень хороший пост, но я не понимаю часть потоков, что, если бы я использовал С++ 11, который может использовать многопоточность, можно было бы использовать полное нативное решение? Поскольку я использую персональный движок С++ с java-интерфейсами (я помещаю все текстуры в Java), это не аккуратно. - person Sung; 27.02.2014