2012-02-10 5 views
10

documentation indica que esto "asigna" almacenamiento para una textura y sus niveles. El pseudocódigo proporcionado parece indicar que esto es para los niveles de mipmap.¿Qué hace glTexStorage?

¿Cómo se relaciona el uso de glTexStorage con glGenerateMipmap? glTexStorage parece "bloquear" el tamaño de almacenamiento de una textura. Me parece que esto solo serviría para hacer las cosas menos flexibles. ¿Se supone que habrá mejoras de rendimiento aquí?

Es bastante nuevo y solo está disponible en 4.2, así que intentaré evitar usarlo, pero estoy confundido porque su descripción lo hace parecer algo importante.

¿Cómo se gestiona el almacenamiento de texturas en las versiones GL anteriores? Cuando llamo al glTexImage2D, borro y libero el almacenamiento previamente asociado con el identificador de textura, ¿sí? y generar mipmaps también maneja automáticamente el almacenamiento para mí también.

Recuerdo que utilicé el método glTexSubImage2D de la vieja escuela para implementar el renderizado a textura de OpenGL 2-style para hacer algunos efectos de post-proceso en mi experimento de motor anterior. Tiene sentido que glTexStorage proporcione una forma más sensata de administrar los recursos relacionados con la textura, ahora que tenemos mejores formas de hacer RTT.

+0

"solo disponible en 4.2" Está disponible en la extensión ARB_texture_storage, que está ampliamente disponible (o lo estará pronto). NVIDIA lo admite en todo lo que se remonta a la GeForce 6600, y AMD lo admite en todo el hardware de clase HD. Dejando de lado los errores, debes usarlos siempre que sea posible. –

+0

Dado que la lista de comentarios sobre la respuesta es tan larga, la pondré aquí. Afortunadamente, en el hardware de Apple, la extensión correspondiente 'EXT_texture_storage' es compatible con" todos los procesadores SGX Series 5 ", y también señalaré que' glTexStorage' está en el núcleo GL ES 3.0. –

Respuesta

26

Para entender lo que hace glTexStorage, debe comprender lo que hacen las funciones glTexImage*.

glTexImage2D hace tres cosas:

  1. Se asigna almacenamiento OpenGL para una capa específica mipmap, con un tamaño específico. Por ejemplo, puede asignar una imagen 2D de 64x64 como nivel de mipmap 2.
  2. Establece el formato interno para el nivel de mipmap.
  3. Carga datos de píxeles a la textura. El último paso es opcional; si pasa NULL como valor de puntero (y ningún objeto de búfer está vinculado a GL_PIXEL_UNPACK_BUFFER), no se produce ninguna transferencia de píxeles.

La creación manual de una textura mipmapped requiere una secuencia de llamadas glTexImage, una para cada nivel de mipmap. Cada uno de los tamaños de los niveles de mipmap debe tener el tamaño adecuado en función del tamaño del nivel anterior.

Ahora, si mira la sección 3.9.14 de la especificación GL 4.2, verá dos páginas de reglas que un objeto de textura debe seguir para ser "completo". No se puede acceder a un objeto de textura incompleto.

Entre esas reglas se encuentran cosas como "los mipmaps deben tener el tamaño apropiado". Tomemos el ejemplo que di más arriba: una imagen 2D de 64x64, que es el nivel 2 de mipmap. Sería código OpenGL perfectamente válido para asignar un nivel 1 de mipmap que usaba una textura de 256x256. O un 16x16. O un 10x345. Todos ellos serían perfectamente funcionales en lo que respecta al código fuente. Obviamente, producirían tonterías como textura, ya que la textura sería incompleta.

Consideremos nuevamente el mapa mip 64x64 2. Lo creo como mi primera imagen. Ahora, yo podría crear un 128x128 mipmap 1. Pero podría también crear una 128x12 mipmap 1. Ambos son completamente consistentes con el nivel de 64x64 mipmap 2 (tamaños mipmap siempre redondeando hacia abajo).Si bien ambos son consistentes, también son diferentes tamaños. Si un controlador tiene que asignar la cadena completa de mipmap de una vez (lo cual es totalmente posible), ¿qué tamaño asigna? No sabe. No puede saber hasta que asignas explícitamente el resto.

Aquí hay otro problema. Digamos que tengo una textura con una cadena completa de mipmap. Está completamente texturado, de acuerdo con las reglas. Y luego llamo al glTexImage2D de nuevo. ¿Ahora que? Podría cambiar accidentalmente el formato interno. Cada nivel de mipmap tiene un formato interno separado; si no todos están de acuerdo, entonces la textura está incompleta. Podría cambiar accidentalmente el tamaño de la textura, volviendo a hacer la textura incompleta.

glTexStorage previene todos estos posibles errores. Crea todos los mipmaps que desee por adelantado, dado el tamaño del nivel base. Asigna todos los mipmaps con el mismo formato de imagen, por lo que no se puede arruinar. Hace que la textura sea inmutable, por lo que no puede venir y tratar de romper la textura con una mala llamada glTexImage2D. Y previene otros errores que ni siquiera me molesté en cubrir.

La pregunta no es "¿qué hace glTexStorage?" La pregunta es "¿por qué vamos tan largo sin".

glTexStorage no tiene relación con glGenerateMipmap; son funcionalidad ortogonal. glTexStorage hace exactamente lo que dice: asigna textura espacio de almacenamiento. No llena ese espacio con nada. Por lo tanto, crea una textura con un tamaño dado lleno de datos no inicializados. Al igual que glRenderbufferStorage, asigna un buffer de representación con un tamaño dado lleno de datos no inicializados. Si usa glTexStorage, debe cargar datos con glTexSubImage (ya que glTexImage está prohibido en una textura inmutable).

glTexStorage crea espacio para mipmaps. glGenerateMipmap crea los datos mipmap en sí (las versiones más pequeñas de la capa base). También puede crear espacio para mipmaps si ese espacio no existe. Se usan para dos cosas diferentes.

+0

¡Esta es una respuesta maravillosa, gracias! Entonces, ¿debería usar 'glGenerateMipmap' en una textura asignada' glTexStorage' (después de actualizar el nivel superior con 'glTexSubImage' por ejemplo) para realizar la actualización correcta de la cadena mipmap? ¿Qué debo hacer si deseo cambiar el tamaño o el formato de una textura que 'glTexStorage''d? ¿Tendré que eliminar la textura por completo y volver a crearla con las nuevas dimensiones? Supongamos que impongo el patrón de uso en mi código que solo establezco el nivel superior usando 'glTexImage2D', y siempre llamo a' glGenerateMipmap' después. ¿Está asegurada la integridad? –

+1

@StevenLu: Una de las razones por las que 'glTexStorage' hace que la textura sea inmutable es una gran y gigantesca pista de que * no * debes tratar de reasignar el almacenamiento de una textura. Si desea cambiar los datos en la textura, puede hacerlo fácilmente con 'glTexSubImage'. Pero no debería tener que hacer que el mismo objeto de textura sea más grande o más pequeño.Si lo haces, lo que quieres es crear una * nueva * textura. –

+0

"¿Está completa la integridad?" Hasta que lo rompas. Por lo tanto, está garantizado siempre que no cambie nada una vez que esté configurado. Soy de la opinión de que la mejor manera de corregir errores es hacer que sea imposible que sucedan. Si algo en una API puede causar problemas, entonces cambie la API para que esos problemas no puedan ser causados. 'glTexStorage' hace eso. –

1

Antes de llamar a glGenerateMipmap, se debe establecer el nivel de mapa base de mip. (ya sea con almacenamiento mutable o inmutable) .so ..., puede usar glTexImage2D+glGenerateMipmap solamente, ¡más simple!