¿Por qué las texturas son siempre potencias cuadradas de dos? ¿Y si no lo son?

53

¿Por qué la resolución de las texturas en los juegos siempre es una potencia de dos (128x128, 256x256, 512x512, 1024x1024, etc.)? ¿No sería inteligente ahorrar en el tamaño del archivo del juego y hacer que la textura se ajuste exactamente al modelo sin envoltura UV?

¿Qué pasaría si hubiera una textura que no fuera una potencia de dos?

¿Sería incorrecto tener una textura como 256x512 o 512x1024? ¿O esto causaría los problemas que pueden causar las texturas sin poder de dos?

Keavon
fuente
99
Sus otros ejemplos también son poderes de dos, pero no el mismo poder de dos. La potencia de dos hace que la textura esté optimizada para el hardware de gráficos.
MichaelHouse
1
@ Byte56 Creo que quiere decir 2 ^ nx 2 ^ n textura, donde n varía de 1 a infinito. (No realmente infinito.)
Robin
También tenga en cuenta que los poderes de dos tienen el beneficio de hacer mipmaps triviales.
Pubby
Debido a que la textura normalmente se envuelve (aunque puede elegir esto en un sombreador personalizado) no necesita desperdiciar espacio, simplemente envuelva las coordenadas uv de sus polígonos alrededor de los bordes y puede hacer uso del espacio disponible mucho más fácilmente. Si no tiene una necesidad de presión, lo más seguro es mantener el ancho = altura = 2 ^ n texturas porque permitirá una gama más amplia de hardware a costa de un diseño ultravioleta un poco más complicado.
Daniel Carlsson
No siempre son poderes de dos.
Almo

Respuestas:

49

¿Por qué la resolución de las texturas en los juegos es siempre una potencia de dos (128x128, 256x256, 512x512, 1024x1024, etc.)?

Como Byte56 implicaba, las restricciones de tamaño de "poder de dos" son (eran) que cada dimensión debe ser, independientemente, un poder de dos, no que las texturas deben ser cuadradas y tener dimensiones que son un poder de dos.

Sin embargo, en las tarjetas modernas y en las API gráficas modernas, esta "restricción" se ha relajado significativamente, de modo que las dimensiones de las texturas pueden ser, dentro de lo razonable, casi cualquier cosa que desee. Sin embargo:

¿No sería inteligente ahorrar en el tamaño del archivo del juego y hacer que la textura se ajuste exactamente al modelo sin envoltura UV? ¿Qué pasaría si hubiera una textura que no fuera una potencia de dos?

Al garantizar que las dimensiones de la textura sean una potencia de dos, la tubería de gráficos puede aprovechar las optimizaciones relacionadas con la eficiencia en el trabajo con potencias de dos. Por ejemplo, puede ser (y fue hace varios años antes de que tuviéramos GPU dedicadas y compiladores de optimización extremadamente inteligentes) más rápido para dividir y multiplicar por potencias de dos. Trabajar en potencias de dos también simplificó las operaciones dentro de la tubería, como el cálculo y el uso de mapas MIP (un número que es una potencia de dos siempre se dividirá por la mitad, lo que significa que no tiene que lidiar con escenarios en los que debe redondear sus dimensiones de mipmap arriba o abajo).

Es cierto que "desperdicias" algo de espacio de esta manera, pero el espacio extra generalmente vale la pena para el intercambio en el rendimiento del render. Además, existen técnicas, como la compresión o el empaquetamiento de múltiples imágenes en un solo espacio de textura que puede aliviar parte del desperdicio de almacenamiento.

Josh
fuente
11
"Es cierto que" desperdicias "algo de espacio de esta manera, pero el espacio adicional generalmente vale la pena para el intercambio en el rendimiento del render". - Hace unos diez años trabajé en un estudio que transportaba un juego de PS2 a la Xbox. Si bien la PS2 no admite técnicamente texturas sin potencia de dos, en algunos casos puede forzarlo a hacerlo con una pequeña manipulación inteligente y sin pérdida de velocidad. El XBox, por otro lado, no los soportó por completo . El resultado final es que, a pesar de que XBox tiene casi el doble de RAM que la PS2, tuvimos que reducir la muestra de algunas de las texturas para que se ajustaran.
ZorbaTHut
Me está costando encontrar una cita, pero he leído anteriormente que las imágenes JPEG deben estar en múltiplos de 8 para una máxima eficiencia, ya que cualquier cosa fuera de eso todavía requiere un bloque de 8x8.
salmonmoose
1
@salmonmoose: Correcto; JPEG comprime cada bloque de 8x8 de forma independiente y rellena los bloques en el borde. Pero eso no está relacionado con esta pregunta.
MSalters
1
Los archivos JPEG están codificados en bloques de 8x8, sí. Sin embargo, eso no es realmente una consideración de eficiencia. Y tampoco es necesariamente una potencia de 2. :)
Kylotan
Un ejemplo es en Android, donde a menudo las dos texturas que no son de potencia resultan en texturas blancas.
user717572
17

¿Por qué las texturas son siempre potencias cuadradas de dos?

Las texturas no siempre son cuadradas ni siempre son potencias de dos . La razón por la que tienden a ser potencias de dos es generalmente para aumentar la compatibilidad con las tarjetas de video más antiguas que impusieron esa restricción. En cuanto a las texturas no cuadradas, eso no suele ser un problema. Para resumir:

  • Por lo general, las texturas no necesitan ser cuadradas , aunque DirectX tiene una D3DPTEXTURECAPS_SQUAREONLYcapacidad, pero he trabajado con texturas no cuadradas, incluso en hardware antiguo sin problemas.
  • Las texturas deben ser potencias de dos porque muchas tarjetas gráficas más antiguas aún lo requieren. La razón de esa restricción fue para que pudieran realizar algunas optimizaciones en las operaciones de mapeo de texturas. La mayoría de las tarjetas gráficas modernas tampoco tienen esta restricción.
David Gouveia
fuente
12
Cabe señalar que por "tarjetas gráficas antiguas" se refiere a cosas hechas antes de 2006 más o menos.
Nicol Bolas
1
@NicolBolas Gracias, en realidad estaba tratando de encontrar algunas referencias sobre ese punto.
David Gouveia
7

Se relaciona con las optimizaciones de la tarjeta gráfica. Han sido diseñados para procesarlos de esa manera. La mayoría de las tarjetas en estos días le permitirán cargar texturas con dimensiones que no son potencias de dos, pero probablemente tendrá un impacto negativo en el rendimiento. Existe una buena posibilidad de que cuando se cargue realmente se convierta, lo que le costará tiempo de carga y no ahorrará memoria. Las texturas no cuadradas generalmente están bien, siempre que ambas dimensiones sean potencias de dos.

Una forma de lidiar con texturas de tamaños extraños es usar un Atlas de texturas . Básicamente, coloca varias texturas juntas en una sola textura y usa las coordenadas de textura de sus vértices para hacer referencia a la imagen particular que necesita. Esto también viene con beneficios de rendimiento adicionales, ya que permite evitar cambios de estado. Un uso común de esto es colocar todos los elementos de la interfaz en una sola textura, lo que significa que si ha agrupado los vértices de sus interfaces en un solo objeto de memoria intermedia, puede dibujar todo con una sola llamada, en lugar de cambiar texturas muchas veces y haciendo un sorteo por separado para cada uno.

Jason Morales
fuente
6

El problema es que algunos hardware tienen soporte limitado para texturas que no tienen potencia de dos dimensiones.

Por ejemplo, mire la parte inferior de http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876%28v=vs.85%29.aspx y lea las notas al pie 3 y 4 allí.

3 En los niveles de característica 9_1, 9_2 y 9_3, el dispositivo de visualización admite el uso de texturas 2D con dimensiones que no son potencias de dos en dos condiciones. Primero, solo se puede crear un nivel de mapa MIP para cada textura, y segundo, no se permiten modos de muestra de envoltura para texturas (es decir, los miembros AddressU, AddressV y AddressW de D3D11_SAMPLER_DESC no se pueden establecer en D3D11_TEXTURE_ADDRESS_WRAP).

4 En los niveles de característica 10_0, 10_1 y 11_0, el dispositivo de visualización admite incondicionalmente el uso de texturas 2D con dimensiones que no son potencias de dos.

Adán
fuente
6

El hardware de gráficos está optimizado para operaciones matriciales, operaciones de fragmentos y operaciones vectoriales. En pocas palabras, las matrices cuadradas son más fáciles de manejar, ya que los cálculos se pueden hacer en bloques (llamados fragmentos), el hardware está optimizado para operaciones de bloque, por lo que hay cosas como búferes de archivos, la memoria RAM no se bloquea en el disco hasta que se bloquea. ha sido poblado Lo mismo se aplica a la memoria gráfica.

El búfer de cuadro está compuesto por fragmentos que son cuadrados. Por ejemplo, en una pantalla con una resolución de 800x600 y un espacio de color RGB (0-255) hay 800x600 puntos con 3 bytes cada canal, hay un total de 3x800x600 = 1,440,000 bytes para direccionar en el búfer de cuadros. Eso significa que hay 1.875 fragmentos direccionables que son 256x256x3 bytes. Debido a que los datos de textura son cuadrados, hace que sea mucho más fácil mapear desde la matriz GRAM a la matriz del búfer de pantalla usando la escala bicúbica, donde como si no fuera cuadrado, el sesgo para el lado más largo tomaría más tiempo para calcular cuándo era necesario ser escalado

Muchas API de gráficos aceptarán datos de textura no cuadrados, porque aceptan coordenadas de mapeo UV como datos de coma flotante, sin embargo, una vez que se envían a la GPU, se agrega relleno a los datos de textura, porque las proporciones reales de la imagen no cambian el mapeo parece no verse afectado, sin embargo, se agrega relleno a los datos de textura, porque a la GPU le gusta abordarlo como un cuadrado perfecto.

Entonces, si se usa una imagen de 100x1024, y se usa una imagen de 1024x1024, lo que significa que se desperdician 946,176 bytes. Aún más si se va a realizar la composición, ya que será necesario agregar un canal alfa para indicar que los datos de relleno no deberían afectar la textura compuesta.

Awiebe
fuente
Esta es una explicación interesante (titbit sobre matrices cuadradas) que no se encuentra en el poder habitual de 2 respuestas (+1): ¿podría proporcionar algunas citas si es posible?
Samaursa
1

Nuestro mundo digital funciona con numeración binaria para luego multiplicar o dividir entre 2 un valor que puede "mover" un valor a la izquierda o la derecha, es decir

<<  Left shift      x = 5 << 1    0101 << 1     1010     10
>>  Right shift     x = 5 >> 1    0101 >> 1     0010      2

Trabajar con valores "potencia de dos" es más fácil para una CPU.

esdebon
fuente
0

El hardware moderno puede (finalmente) hacer frente a los modos de ajuste habilitados en la falta de potencia de dos texturas basadas, sin embargo, la falta de potencia de dos texturas todavía tiende a desperdiciar la memoria de la GPU, ya que tienden a acolcharse a lo largo del ancho por una cantidad específica de hardware (ya sea a algún tamaño de mosaico o redondeado a la siguiente potencia de dos tamaños que contiene la textura).

Como esto depende del hardware y los vendedores generalmente no entrarán en los detalles de estos detalles, lo más seguro es continuar usando potencia de dos dimensiones para las texturas, para no desperdiciar la memoria RAM de la GPU.

Zoner
fuente