2010-09-18 15 views
14

Esta es solo una pregunta rápida antes de profundizar en la conversión de mi sistema de representación actual a OpenGL. Escuché que las texturas deben estar en los tamaños de la base 2 para que se almacenen para el renderizado. ¿Es esto cierto?¿Puede OpenGL ES renderizar texturas de dimensiones no base 2?

Mi aplicación es muy estrecha en la memoria, pero la mayoría de los mapas de bits no son potencias de dos. ¿El almacenamiento de texturas no base 2 consume más memoria?

+1

potencia de dos! = Cuadrado. 32x64 es potencia de dos, no cuadrada, 13x13 es cuadrada, no potencia de dos. – Bahbar

+0

Buen punto. Sin embargo, en cualquier caso, tiene que ser el poder de dos. – GuyNoir

Respuesta

10

Es cierto que según la versión de OpenGL ES, OpenGL ES 1.0/1.1 tiene la potencia de dos restricciones. OpenGL ES 2.0 no tiene la limitación, pero restringe los modos de ajuste para la no potencia de dos texturas.

Crear texturas más grandes para que coincidan con las dimensiones de POT no desperdicia la memoria de textura.

+0

¿Así que no hay forma de renderizar un mapa de bits de dos dimensiones con OpenGL sin desperdiciar memoria? Eso es molesto. Oh, bueno, me alegro de no haber empezado a revisar mi código todavía. – GuyNoir

+0

Con OpenGL ES 1.0/1.1, no. –

+0

Por cierto, debe saber que OpenGL ES y OpenGL no tienen las mismas limitaciones, OpenGL 2.0 y versiones posteriores admiten texturas NPOT directamente. –

3

No, debe ser una base 2. Sin embargo, puede evitar esto agregando barras negras en la parte superior y/o inferior de la imagen, luego use la matriz de coordenadas de textura para restringir dónde se mapeará la textura de su imagen. Por ejemplo, supongamos que tiene una textura de 13 x 16 píxeles. Se pueden añadir 3 píxeles de negro a la derecha y luego hacer lo siguiente:

static const GLfloat texCoords[] = { 
     0.0, 0.0, 
     0.0, 13.0/16.0, 
     1.0, 0.0, 
     1.0, 13.0/16.0 
    }; 

Ahora, usted tiene un archivo de imagen 2base, pero una textura no 2base. Solo asegúrese de usar escalas lineales :)

+0

El problema aquí es que desperdicia memoria de textura; algo que estoy muy presionada con mi aplicación. – GuyNoir

6

Suresh, la limitación de la potencia de 2 fue incorporada en OpenGL en los (muy) primeros días de los gráficos por computadora (antes de la aceleración de hardware asequible), y se realizó por motivos de rendimiento. El código de renderizado de bajo nivel obtiene un aumento de rendimiento decente cuando se puede codificar de forma rígida para texturas de potencia de dos. Incluso en las GPU modernas, las texturas POT son más rápidas que las texturas NPOT, pero la diferencia de velocidad es mucho menor de lo que solía ser (aunque aún puede notarse en muchos dispositivos ES).

GuyNoir, lo que debe hacer es crear un atlas de textura. Acabo de resolver este problema este fin de semana pasado para mi propio juego de Android. Creé una clase llamada TextureAtlas, y su constructor llama a glTexImage2D() para crear una textura grande de cualquier tamaño que elija (pasando null para los valores de píxel). Luego puedo llamar a add (id, bitmap), que llama glTexSubImage2D(), repetidamente para empacar las imágenes más pequeñas. La clase TextureAtlas rastrea el espacio libre y usado dentro de la textura más grande y los rectángulos en los que se almacena cada mapa de bits. Entonces el código de representación puede llamar a get (id) para obtener el rectángulo de una imagen dentro del atlas (que luego puede convertir a textura coordenadas).

Nota al margen # 1: Elegir la mejor manera de empacar en varios tamaños de textura NO es una tarea trivial. Elegí comenzar con una lógica simple en la clase TextureAtlas (piense en máquina de escribir + retorno de carro + avance de línea) y me aseguro de cargar las imágenes en el mejor orden para aprovechar esa lógica. En mi caso, eso fue para comenzar con las imágenes cuadradas más pequeñas y avanzar hasta las imágenes cuadradas medianas. Luego cargo cualquier imagen corta + ancha, fuerzo un CR + LF, y luego cargo cualquier imagen alta + delgada. Cargué las imágenes cuadradas más grandes al último.

Nota lateral n. ° 2: si necesita varios atlas de textura, intente agrupar las imágenes dentro de cada una que se renderizarán juntas para minimizar el número de veces que necesita cambiar texturas (lo que puede matar el rendimiento). Por ejemplo, en mi juego para Android pongo todos los elementos de la placa de juego estática en un atlas y todos los cuadros de varios efectos de animación en un segundo atlas. De esa forma puedo unir el atlas # 1 y dibujar todo en el tablero, luego puedo unir el atlas # 2 y dibujar todos los efectos especiales encima. Dos selecciones de textura por cuadro es muy eficiente.

Nota lateral n. ° 3: si necesita texturas repetitivas/duplicadas, necesitan ir en sus propias texturas, y necesita escalarlas (no agregar píxeles negros para rellenar los bordes).

+0

Sí, consideré algo similar. Lo único es que todavía hay algunas pequeñas cantidades de memoria desperdiciada, y en un programa en el que estoy constantemente presionando los límites de 24 mb, necesito todo el recuerdo que pueda obtener. – GuyNoir

1

Esto es un poco tarde, pero no potencia de 2 texturas son apoyado bajo OpenGL ES medio a través de extensiones.

El principal es GL_OES_texture_npot. También hay GL_IMG_texture_npot y GL_APPLE_texture_2D_limited_npot para dispositivos con iOS

Compruebe estas extensiones llamando al glGetString(GL_EXTENSIONS) y buscando la extensión que necesita.

También recomendaría mantener sus texturas en tamaños que son múltiplos de 4, ya que algunos hardware se extienden las texturas de no ser así.

Cuestiones relacionadas