Войти
Мобильные платформыФорумОбщее

[Android] Загрузка и отрисовка OpenGL текстур

Страницы: 1 2 Следующая »
#0
17:50, 12 апр. 2010

Приветсвую...

* Disclaimer - перепост, может тут чего ответят.

Хочу обсудить кто как грузить и рисовать OpenGL текстуры ( в том числе и не кратные 2-ум) и их выводить. Платформа Android. Сразу оговорюсь - речь идет о 2d over opengl, т.е. наша задача наиболее быстро и с меньшими мемори ликами отрисовть 2d картинку в плоскости экрана.

Я вижу несколько способов. Я их внизу перечислю. Что используете вы? Почему?
Какие есть еще варианты? Велком для беседы :)

Способ 1, который я сейчас использую.

* Берем оригинальный Bitmap, если он не не кратный степени два, то через createScaledBitmap создаем битмап подходящего размера маштабируя оригинальный битмап

  • Создаем текстуру через texImage2D
  • Создаем один раз общий статичный ByteBuffer для вершин и текстурных координат созданный через ByteBuffer.allocateDirect(4 * 2 * 4) "единичного" размера {0, 0, 0, 1, 1, 0, 1, 1}
  • Выводим используя для задания координат glTranslatef(left, top, 0) и плюс glScalef(m_width, m_height, 0) задавая glTexCoordPointer(2, GL10.GL_BYTE, 0, m_buffer) и glVertexPointer(2, GL10.GL_BYTE, 0, m_buffer) в качестве m_buffer используем наш "единичный" буффер.
  • Ну и в конце glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4)
  • Минусы

    * Теряем в качестве изображения из-за маштабирования

  • Теряем в скорости загрузки из-за матабирования
  • Плюсы

    * Использование GL_BYTE и ByteBuffer - быстрее вывод, меньше мемори ликов, чем при GL_FLOAT и FloatBuffer

  • Можем вызывать glTexCoordPointer и glVertexPointer один раз на вывод множества (всех) текстур, что повышает скорость отрисовки
  • Вариант 2.

    * Берем оригинальный Bitmap, если он не не кратный степени два, то через Bitmap.createBitmap(w2, h2, bitmap.hasAlpha() ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565) создаем битмап подходящего размера и отрисовываем туда оригинальный битмап по координатам 0,0

  • Создаем текстуру через texImage2D
  • Создаем один раз общий статичный ByteBuffer для вершин созданный через ByteBuffer.allocateDirect(4 * 2 * 4) "единичного" размера {0, 0, 0, 1, 1, 0, 1, 1} и для каждой текстуры еще свой индивидульный FloatBuffer, в котором задаем пропорции {0, 0, 0, ratioHeight, ratioWidth, 0, ratioHeight, ratioWidth}, где ratioHeight - это отношение реального размера, к новому размеру
  • * Выводим используя glTranslatef(left, top, 0) и glScalef(m_width, m_height, 0) задавая glTexCoordPointer(2, GL10.GL_FLOAT, 0, m_bufferFloat) и glVertexPointer(2, GL10.GL_BYTE, 0, m_buffer) в качестве m_buffer используем наш общий "единичный" буффер, а в качестве m_bufferFloat на индивидуальный буффер.

    * Ну и в конце опять glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4)

    Минусы

    * Дополнительная память на "индивидуальный" FloatBuffer

  • Больше мемори ликов из-за использования FloatBuffer
  • glTexCoordPointer работает медленне из-за FloatBuffer (???)
  • Необходимо при отрисовки каждой текстуры вызвать ей glTexCoordPointer
  • Плюсы

    * Не теряем качество и время при загрузки на маштабирование

  • ????
  • Вариант 3.

    Если в кратце то, не используем glTranslatef , а каждый раз заполняем вертексный буффер нужными координатами (тоже самое можем делать и с glScalef)

    Минусы

    * Медленно

    Плюсы

    * ????


    #1
    14:37, 15 апр. 2010

    Young
    И ВСЁ это НЕ устраивает?
    Имеется в виду, что как только начинаем выводить 2д то всё становится плохо?

    #2
    22:45, 16 апр. 2010

    Ну не то что бы совсем все плохо. Скажем так везде есть свои недостатки. Сейчас я сделал метод, совместивший пункт 1 и 2, но без FloatBuffer. Да и не в 2д дело. Скажем так речь идет о выводе полигона вооще.
    Я скорее хотел подискутировать кто как делает. Можно же еще NDK использовать, и весь рендер вынести в нативный код. Можно чисто рендер полигона вынести в NDK.  Можно еще не GL_TRIANGLE_STRIP использовать, а что-то еще - я не пробовал.
    Плюс еще множество мелких вещей есть - атласы создавать например, чтобы меньше переключать текстуры. Вдруг кто чего пробовал. Сам все варианты не проверишь.

    Но что-то людей которые делают opengl игры под андроид не наблюдается :)

    Прошло более 1 года
    #3
    12:34, 12 фев. 2012

    О, удачно наткнулся на эту тему. Интересует как можно вывести картинку сохранив оригинальные пропорции и чтоб картинки с прозрачностью/полупрозрачностью правельно отображалась. Вот мой код

    package com.test;
    
    import android.content.Context;
    import android.content.res.Resources;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.opengl.GLSurfaceView;
    import android.opengl.GLU;
    import android.opengl.GLUtils;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    
    public class GLRender implements GLSurfaceView.Renderer {
    
        private Context mContext;
        private static FloatBuffer mTexCoordsBuffer;
        private final static float[] TEXTURES_COORDS = {
                0, 1,
                0, 0,
                1, 1,
                1, 0
        };
        private static int[] mTextures = new int[1];
    
        public GLRender(Context context) {
            mContext = context;
            ByteBuffer bb = ByteBuffer.allocateDirect(4 * 3 * 4);
            bb.order(ByteOrder.nativeOrder());
            mTexCoordsBuffer = bb.asFloatBuffer();
            mTexCoordsBuffer.put(TEXTURES_COORDS);
            mTexCoordsBuffer.position(0);
        }
    
        public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
            gl.glEnable(GL10.GL_TEXTURE_2D);
    
            gl.glGenTextures(1, mTextures, 0);
            gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[0]);
            Resources res = mContext.getResources();
            Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.pic);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                    GL10.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                    GL10.GL_NEAREST);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
    
            gl.glClearColor(1, 1, 1, 1);
        }
    
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            // avoid division by zero
            if (height == 0) height = 1;
            // draw on the entire screen
            gl.glViewport(0, 0, width, height);
            // setup projection matrix
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 1.0f, 100.0f);
        }
    
        public void onDrawFrame(GL10 gl) {
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
    
            gl.glTranslatef(-0.5f, -0.5f, -3);
    
            //gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[0]);
    
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    
            gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mTexCoordsBuffer);
            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexCoordsBuffer);
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    
            gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        }
    }
    если картинка с полупрозрачностью, то на месте прозрачности чернота, ну и пропорции здесь не сохранены.

    #4
    16:05, 12 фев. 2012

    G@sh!sh

    Касаемо прозрачности подскажу: смотри glBlend итд.  У тебя прозрачность просто не включена.
    И непонятно зачем для 2d  использовать gluPerspective. Надо юзать glOrtho.

    #5
    17:05, 12 фев. 2012

    FUNNY FACE
    спасибо за помощь, просто я только недавно начал изучать огл

    #6
    19:52, 13 фев. 2012

    YgriK
    > * Теряем в качестве изображения из-за маштабирования
    "маштабирования" пишется через С, вот так: "масштабирования"

    #7
    21:24, 13 фев. 2012

    igagis
    это всё, что вы смогли сделать за ДВА!!! года существования топика?

    #8
    22:58, 13 фев. 2012

    YgriK
    так а я же и не делал ничего, а что я должен был сделать?

    #9
    22:16, 15 фев. 2012

    в onSurfaceCreated добавил

            gl.glEnable(GL10.GL_BLEND);
            gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
    теперь картинка не рисуется. почему так??

    и если

    GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 1.0f, 100.0f);
    заменить на
    GLU.gluOrtho2D(gl, 0, width, 0, height);
    то тоже картика не рисуется.

    #10
    15:27, 19 фев. 2012

    с предыдущими проблемами вроде справился, но возник еще вопрос.
    как в нативной части загрузить текстуру из argb массива (int'ов), знаю о существовании glTexImage2D, но какое значение  нужно применить для предпоследнего параметра?

    #11
    19:34, 19 фев. 2012

    > какое значение нужно применить для предпоследнего параметра?
    help is here!

    Подставляешь нужное тебе

    Вот пример из cocos2d-iphone (лишнее не чистил)

    - (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size
    {
      if((self = [super init])) {
        glPixelStorei(GL_UNPACK_ALIGNMENT,1);
        glGenTextures(1, &name_);
        glBindTexture(GL_TEXTURE_2D, name_);
    
        [self setAntiAliasTexParameters];
        
        // Specify OpenGL texture image
        
        switch(pixelFormat)
        {
          case kCCTexture2DPixelFormat_RGBA8888:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
            break;
          case kCCTexture2DPixelFormat_RGBA4444:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
            break;
          case kCCTexture2DPixelFormat_RGB5A1:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data);
            break;
          case kCCTexture2DPixelFormat_RGB565:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei) width, (GLsizei) height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
            break;
          case kCCTexture2DPixelFormat_AI88:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
            break;
          case kCCTexture2DPixelFormat_A8:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
            break;
          default:
            [NSException raise:NSInternalInconsistencyException format:@""];
            
        }
    
        size_ = size;
        width_ = width;
        height_ = height;
        format_ = pixelFormat;
        maxS_ = size.width / (float)width;
        maxT_ = size.height / (float)height;
    
        hasPremultipliedAlpha_ = NO;
    
    #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
        resolutionType_ = kCCResolutionUnknown;
    #endif
      }
      return self;
    }

    #12
    0:25, 20 фев. 2012

    >gl.glTranslatef(-0.5f, -0.5f, -3);

    *_*

    какой сегодня год?

    #13
    22:13, 20 фев. 2012

    ALTAIR
    а конкретней можно узнать, что вам не нравится? делал все по примерам, как там так и у меня)

    #14
    19:05, 26 фев. 2012

    еще вопрос. если сдвигать картинку через glTranslatef по координате z от себя, то она становится меньше, меньше, а потом резко исчезает. почему? и как это исправить?

    Страницы: 1 2 Следующая »
    Мобильные платформыФорумОбщее

    Тема в архиве.