Ограничения размера текстур OpenGL. Предоставление альтернативных ресурсов для конкретных устройств Android

В моем приложении для Android, которое представляет собой игру OpenGL ES 2.0, я включил 4 набора графических ресурсов, например:

  • ldpi
  • mdpi
  • hdpi
  • xhdpi

Теперь в моей папке xhdpi самый большой актив, который у меня есть, - 2560 x 1838, поскольку я нацелен здесь на большие экраны (например, планшет Google Nexus 10, который получает свои ресурсы из папки XHDPI). До сих пор все работало на устройствах, на которых я тестировал (Google Nexus 10, Samsung Galaxy S3, S4 и S5, Nexus 4 и 5 и т. Д. И т. Д.).

Недавно я получил известие от пользователя, который столкнулся с проблемами при запуске этого на телефоне HTC One X + (я считаю, что для этого есть и другие причины, помимо той, о которой я говорю здесь, поэтому у меня есть отдельный вопрос, открытый для других проблем) .

Дело в том, согласно: this, максимальный размер текстуры для этого телефона составляет 2048x2048, но согласно this этот телефон получает свои ресурсы из папки XHDPI.

Таким образом, он не будет отображать текстуры из этого атласа (это атлас фонов, содержащий 6 отдельных фонов размером 1280 * 612.

Теперь у меня есть два известных мне способа исправить это:

  • Уменьшите размер фона. Исключено, так как это снизит качество на устройствах с большим экраном (например, Nexus 10)

  • Разделить на 2 атласа предпочел бы не делать этого, поскольку хотел бы сохранить все фоны в 1 атласе для оптимизации скорости загрузки (и просто для того, чтобы все было в порядке)

Есть ли другие варианты? Могу ли я предоставить в подпапке xhdpi другую папку, которая соответствует лимитам 1X +? И если да, то как мне заставить устройство брать оттуда ресурсы?

Я делаю это вслепую, так как у меня нет 1X +, на котором можно это проверить, но из того, что я читал, я считаю, что наличие ресурсов размером более 2048 x 2048 вызовет проблемы на этом устройстве.

Это мой код для наложения текстур:

public static int LoadTexture(GLSurfaceView view, Bitmap imgTex){

    //Array for texture
    int textures[] = new int[1];
    try {
        //texture name
        GLES20.glGenTextures(1, textures, 0);
        //Bind textures
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        //Set parameters for texture
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);

        //Apply texture
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, imgTex, 0);

        //clamp texture
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE);

    } catch (Exception e){

    }
    //Increase texture count
    textureCount++;
    //Return texture
    return textures[0];
}

person Zippy    schedule 11.09.2014    source источник


Ответы (1)


Если вы не знаете, сработает ли загрузка текстуры, вы можете выполнить все те же операции, за исключением использования GL_PROXY_TEXTURE_2D (или 1D, 3D и т. д.) вместо GL_TEXTURE_2D, чтобы проверить, будет ли загрузка работать для данного размера текстуры и параметров. OpenGL пытается выполнить загрузку и устанавливает для всех состояний текстуры значение 0, если оно не работает или есть другая проблема в параметре текстуры. Затем, если загрузка текстуры не удалась (в вашем случае из-за слишком большого изображения), пусть ваша программа загрузит текстуру с меньшим масштабом.

РЕДАКТИРОВАТЬ: я использую iOS, и мой gl.h не включает GL_PROXY_TEXTURE_ *, и я не могу найти ссылку в Спецификация OpenGL ES3, поэтому я не уверен, что это сработает для вас с OpenGL.

В качестве альтернативы получите максимальный размер текстуры (для каждого измерения, например, ширину, высоту или глубину) и загрузите изображение подходящего размера, используя:

glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );

После этого проверьте свое изображение, чтобы убедиться, что оно работает.

GLuint name;
int width = 10000;  // really bad width
int height = 512;
GLint size;

glGenTextures( 1, &name );
glBindTexture( GL_TEXTURE_2D, name );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  width, height, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, 0);

GLenum error = glGetError();
if( error ) {
    printf("Failed!");
}
else {
    printf("Succeeded!");
}
person pyj    schedule 11.09.2014
comment
Привет, @MtRoad, у меня нет устройства, на котором можно это проверить (ну, не того, на котором есть проблема), однако я сделал быстрый поиск в Google и нигде не могу найти пример того, как использовать этот GL_PROXY_TEXTURE_ * D. Не могли бы вы отредактировать свой ответ, чтобы привести пример? Спасибо. Я отредактирую свой вопрос, включив в него код текстуры. - person Zippy; 12.09.2014
comment
Да, я только что выполнил проверку и протестировал ее на текстуре, которая (намеренно) была слишком большой, и она выявила ошибку, возвращающую Invalid_value, так что эта часть определяет, когда текстура слишком велика. Однако проблема в том, что мне делать дальше? Если это не удалось, как мне получить код для загрузки уменьшенной версии текстуры из одной из других моих папок ресурсов? Я нигде не могу найти эту информацию! - person Zippy; 12.09.2014
comment
Нет смысла использовать текстуры сверхвысокого качества на дисплеях с низким разрешением, поэтому вы можете отсортировать качество текстуры как низкое, среднее, хорошее, высокое вместо ldpi, mdpi, hdpi и xhdpi. Затем сохраните лучшие и все изображения более низкого качества в каждой папке (с низким уровнем ldpi, низким / средним для mdpi, низким / средним / хорошим с hdpi и т. Д.), А затем выберите лучшую текстуру с учетом GL_MAX_TEXTURE_SIZE. Или вы можете самостоятельно уменьшить разрешение текстуры перед загрузкой в ​​OpenGL. - person pyj; 12.09.2014
comment
Да, у меня уже есть это в значительной степени, низкое качество в LDPI, затем более высокое качество в MDPI, затем более высокое качество по-прежнему в HDPI, затем самое высокое качество в XHDPI, но когда я загружаю ресурс, устройство автоматически выберите, из какой папки он берет ресурсы. Мой вопрос в том, как мне заставить его взять из другой папки. Если вы видите ссылку в моем вопросе, X1 + указан как XHDPI, что означает, что он будет брать ресурсы из папки XHDPI - так же, как мой планшет Nexus 10 со сверхвысоким разрешением. - person Zippy; 12.09.2014