Переход с bitmap на OpenGL

#android #opengl-es #bitmap

#Android #opengl-es #bitmap

Вопрос:

Хорошо, пришло время использовать OpenGL (gulp!) Для рендеринга спрайтов в моих приложениях (играх) и забыть Bitmap.draw и т.д.

После просмотра сотен сайтов / блогов (ну, может быть), «объясняющих», как кодировать с использованием OpenGL, я уперся в кирпичную стену.

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

Очевидный путь — переход на OpenGL. Все обучающие сайты ориентированы на разработку с нуля. Это отлично подходит для всех, кто начинает новый проект, но мне нужна «доработка» моих приложений. Я не хочу переписывать с нуля!

У кого-нибудь был опыт в этом? Любые мысли были бы чрезвычайно признательны.

Ответ №1:

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

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

К счастью, есть несколько хороших сторон. Поскольку ваше приложение уже работает только в 2d, вы можете избежать самых сложных этапов изучения OpenGL, связанных с 3D-измерением! Я бы начал с настройки gl.Просмотр поверхности. Используйте glOrtho для настройки границ вашего GL world, если ваша игра уже не зависела от разрешения, это должно каким-то «независимым» образом определять ширину экрана. Просто настройте glOrtho на использование тех же экстентов.

Я создал простой класс sprite, который я использовал для всего моего рендеринга. У спрайта был простой буфер вершин в качестве элемента, я просто заставил его сделать прямоугольник размером 1 на 1, а затем использовал используемый масштаб для настройки размера. (Так что, если бы это было действительно 30×30, я бы установил масштаб в scaleX = 30 scaleY = 30).

Это выглядело примерно так

         ByteBuffer vbb = ByteBuffer.allocateDirect( mNumVerts * 2 * 4 );
        vbb.order( ByteOrder.nativeOrder() );
        mVtxBuf = vbb.asIntBuffer();

        vbb = ByteBuffer.allocateDirect( mNumVerts * 2 * 4 );
        vbb.order( ByteOrder.nativeOrder() );
        mTexBuf = vbb.asIntBuffer();

        mVtxBuf.put( -Fixed32.HALF ); mVtxBuf.put( -Fixed32.HALF ); mTexBuf.put( 0 ); mTexBuf.put( Fixed32.ONE );
        mVtxBuf.put(  Fixed32.HALF ); mVtxBuf.put( -Fixed32.HALF ); mTexBuf.put( Fixed32.ONE ); mTexBuf.put( Fixed32.ONE );
        mVtxBuf.put(  Fixed32.HALF ); mVtxBuf.put(  Fixed32.HALF ); mTexBuf.put( Fixed32.ONE ); mTexBuf.put( 0 );

        mVtxBuf.put( -Fixed32.HALF ); mVtxBuf.put( -Fixed32.HALF ); mTexBuf.put( 0 ); mTexBuf.put( Fixed32.ONE );
        mVtxBuf.put(  Fixed32.HALF ); mVtxBuf.put(  Fixed32.HALF ); mTexBuf.put( Fixed32.ONE ); mTexBuf.put( 0 );        
        mVtxBuf.put( -Fixed32.HALF ); mVtxBuf.put(  Fixed32.HALF ); mTexBuf.put( 0 ); mTexBuf.put( 0 );

        mVtxBuf.position( 0 );        
        mTexBuf.position( 0 );
  

(Fixed32.HALF равен всего 0,5 в фиксированной точке, вы можете просто использовать 0,5 и изменить вызовы Draw на FLOAT вместо FIXED)

С помощью кода для рисования…

         gl.glMatrixMode( GL10.GL_MODELVIEW );
        gl.glLoadIdentity();
        gl.glEnableClientState( GL10.GL_VERTEX_ARRAY );                 
        gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY );

        gl.glColor4f( 1.0f * thing.getAlpha() , 1.0f * thing.getAlpha() , 1.0f * thing.getAlpha() , thing.getAlpha() );  

        gl.glTranslatef( thing.getX(), thing.getY(), thing.getZ() );
        gl.glScalef( thing.getXScale(), thing.getYScale(), thing.getZScale() );

        gl.glFrontFace( GL10.GL_CW );
        gl.glVertexPointer( 2, GL10.GL_FIXED, 0, mdl.getVtxBuf() );

        gl.glTexCoordPointer( 2, GL10.GL_FIXED, 0, mdl.getTexBuf() );
        // gl.glColorPointer( 4, GL10.GL_FLOAT, 0, mColorBuffer );
        gl.glDrawArrays( GL10.GL_TRIANGLES, 0, mdl.getVtxCount() ); 
  

Ответ №2:

Что ж, я бы посоветовал вам заменять столько, сколько вам нужно, пока вы не закончите (= достаточно быстро).

Следовательно, очень важно, чтобы вы точно знали, где ваша производительность неприемлема. Профиль, профиль, профиль.

Конечно, есть некоторые вещи, которые вам всегда нужно будет реализовать, даже если вы просто хотите использовать Opengl для небольшой части игры. Создание контекста, загрузка текстуры и т.д…