Por que as texturas são sempre potências quadradas de dois? E se não estiverem?

53

Por que a resolução de texturas nos jogos sempre é uma potência de dois (128x128, 256x256, 512x512, 1024x1024 etc.)? Não seria inteligente economizar no tamanho do arquivo do jogo e fazer com que a textura se encaixasse exatamente no modelo desembrulhado por UV?

O que aconteceria se houvesse uma textura que não fosse uma potência de dois?

Seria incorreto ter uma textura semelhante a 256x512 ou 512x1024? Ou isso causaria os problemas que texturas sem poder de duas podem causar?

Keavon
fonte
9
Seus outros exemplos também são poderes de dois, mas não o mesmo poder de dois. Os poderes de dois tornam a textura otimizada para o hardware gráfico.
MichaelHouse
11
@ Byte56 Acho que ele quer dizer 2 ^ nx 2 ^ n textura, onde n varia de 1 a infinito. (Não é realmente infinito.)
Robin
Observe também que os poderes de dois têm o benefício de tornar mipmaps triviais.
Pubby
Como a textura normalmente envolve (embora você possa escolher isso em um sombreador personalizado), você não precisa perder espaço, basta envolver as coordenadas uv dos polígonos nas bordas e usar o espaço disponível com muito mais facilidade. Se você não tem uma necessidade premente, é mais seguro manter as texturas width = height = 2 ^ n, pois permitirá uma maior variedade de hardware ao custo de um layout uv um pouco mais complicado.
Daniel Carlsson
Nem sempre são poderes de dois.
Almo

Respostas:

49

Por que a resolução de texturas nos jogos sempre é uma potência de dois (128x128, 256x256, 512x512, 1024x1024 etc.)?

Como Byte56 sugeriu, as restrições de tamanho "poder de dois" são (eram) que cada dimensão deve ser, independentemente, um poder de dois, não que as texturas devam ser quadradas e ter dimensões que sejam um poder de dois.

No entanto, em placas modernas e em quais APIs gráficas modernas, essa "restrição" foi relaxada significativamente, de modo que as dimensões das texturas podem ser, dentro da razão, praticamente o que você quiser. Contudo:

Não seria inteligente economizar no tamanho do arquivo do jogo e fazer com que a textura se encaixasse exatamente no modelo desembrulhado por UV? O que aconteceria se houvesse uma textura que não fosse uma potência de dois?

Ao garantir que as dimensões da textura sejam um poder de dois, o pipeline de gráficos pode tirar proveito das otimizações relacionadas à eficiência no trabalho com poderes de dois. Por exemplo, pode ser (e foi há vários anos antes que tivéssemos GPUs dedicadas e compiladores de otimização extremamente inteligentes) mais rápidos para dividir e multiplicar por potências de dois. Trabalhar com poderes de duas operações simplificadas também dentro do pipeline, como computação e uso de mipmaps (um número que é um poder de dois sempre se dividirá igualmente pela metade, o que significa que você não precisa lidar com cenários nos quais deve arredondar suas dimensões do mipmap para cima ou para baixo).

É verdade que você "desperdiça" algum espaço dessa maneira, mas o espaço extra geralmente vale a pena pela troca no desempenho da renderização. Além disso, existem técnicas, como compactação ou compactação de várias imagens em um único espaço de textura que podem aliviar parte do desperdício de armazenamento.

Josh
fonte
11
"É verdade que você" desperdiça "algum espaço dessa maneira, mas o espaço extra geralmente vale a pena pela troca no desempenho da renderização". - Cerca de dez anos atrás, eu trabalhava em um estúdio que estava portando um jogo de PS2 para o XBox. Embora o PS2 não suporte tecnicamente texturas que não sejam de duas potências, em alguns casos, você pode forçá-lo a fazê-lo com uma manipulação inteligente e sem perda de velocidade. O XBox, por outro lado, não os suportava completamente . O resultado final é que, apesar do XBox ter quase o dobro da RAM do PS2, tivemos que reduzir algumas das texturas para podermos ajustar.
ZorbaTHut
Estou tendo dificuldade em encontrar uma citação, mas li anteriormente que as imagens JPEG devem ter múltiplos de 8 para obter a máxima eficiência, pois qualquer coisa fora dela ainda requer um bloco 8x8.
salmonmoose
11
@salmonmoose: correto; O JPEG compacta cada bloco de 8x8 de forma independente e encobre os blocos na borda. Mas isso não tem relação com essa pergunta.
MSalters 26/03
11
JPEGs são codificados em blocos 8x8, sim. Isso não é realmente uma consideração de eficiência. E não é necessariamente uma potência de 2 também. :)
Kylotan
Um exemplo é no Android, onde muitas vezes as texturas que não são poweroft resultam em texturas brancas.
user717572
17

Por que as texturas são sempre potências quadradas de dois?

As texturas nem sempre são quadradas nem sempre são potências de dois . A razão pela qual eles tendem a ser poderes de dois é geralmente aumentar a compatibilidade com placas de vídeo mais antigas que impuseram essa restrição. Quanto às texturas não quadradas, isso geralmente não é um problema. Para resumir:

  • As texturas normalmente não precisam ser quadradas - embora o DirectX tenha uma D3DPTEXTURECAPS_SQUAREONLYcapacidade, mas eu trabalhei com texturas não quadradas, mesmo em hardware mais antigo, sem problemas.
  • As texturas devem ter potências de dois, porque muitas placas gráficas mais antigas ainda o exigem. O motivo dessa restrição foi para que eles pudessem executar algumas otimizações nas operações de mapeamento de textura. A maioria das placas gráficas modernas também não tem essa restrição.
David Gouveia
fonte
12
Deve-se notar que, por "cartões gráficos mais antigos", ele quer dizer coisas feitas antes de 2006.
Nicol Bolas
11
@ NicolBolas Obrigado, eu estava realmente tentando encontrar algumas referências sobre esse ponto.
David Gouveia
7

Relaciona-se às otimizações da placa gráfica. Eles foram projetados para processá-los dessa maneira. A maioria dos cartões estes dias irá permitir que você para carregar texturas com dimensões que não são potências de dois, mas ele provavelmente vai ter um impacto negativo no desempenho. Há uma boa chance de que, quando carregada, ela realmente seja convertida, custando tempo de carregamento e não economizando memória. Texturas não quadradas geralmente são boas, desde que ambas as dimensões sejam potências de duas.

Uma maneira de lidar com texturas de tamanho ímpar é usar um Atlas de Textura . Basicamente, você coloca várias texturas juntas em uma única textura e usa as coordenadas de textura de seus vértices para referenciar a imagem específica que você precisa. Isso também traz benefícios adicionais de desempenho, pois permite evitar alterações de estado. Um uso comum disso é colocar todos os elementos da interface em uma única textura, o que significa que, se você tiver agrupado os vértices da interface em um único objeto de buffer, poderá desenhar a coisa toda com uma única chamada, em vez de alternar as texturas. várias vezes e fazendo uma chamada de empate separada para cada uma.

Jason Morales
fonte
6

O problema é que alguns hardwares têm suporte limitado para texturas que não têm poder de duas dimensões.

Por exemplo, consulte a parte inferior de http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876%28v=vs.85%29.aspx e leia as notas de rodapé 3 e 4.

3 Nos níveis de recurso 9_1, 9_2 e 9_3, o dispositivo de exibição suporta o uso de texturas 2-D com dimensões que não são potências de dois em duas condições. Primeiro, apenas um nível de mapa MIP para cada textura pode ser criado e, segundo, nenhum modo de amostrador de quebra automática para texturas é permitido (ou seja, os membros AddressU, AddressV e AddressW de D3D11_SAMPLER_DESC não podem ser definidos como D3D11_TEXTURE_ADDRESS_WRAP).

4 Nos níveis de recurso 10_0, 10_1 e 11_0, o dispositivo de exibição suporta incondicionalmente o uso de texturas 2-D com dimensões que não são potências de dois.

Adão
fonte
6

O hardware gráfico é otimizado para operações de matriz, operações de fragmento e operações de vetor. Simplificando, as matrizes quadradas são mais fáceis de lidar, pois os cálculos podem ser feitos em blocos (chamados fragmentos), o hardware é otimizado para operações de bloco, e é por isso que existem coisas como buffers de arquivo, a memória RAM não blit para disco até um bloco foi preenchido. O mesmo se aplica à memória gráfica.

O buffer de quadros é composto por fragmentos quadrados. Por exemplo, em uma tela com uma resolução de 800x600 e um espaço de cores RGB (0-255), existem pontos de 800x600 com 3 bytes por canal, há um total geral de 3x800x600 = 1.440.000 bytes para endereçar no buffer de quadros. Isso significa que existem 1.875 fragmentos endereçáveis ​​com 256x256x3 bytes. Como os dados da textura são quadrados, facilita significativamente o mapeamento da matriz GRAM para a matriz do buffer de tela usando a escala bicúbica, onde, como se não fosse quadrado, o viés para o lado mais longo levaria mais tempo para calcular quando necessário. ser escalado.

Muitas APIs de gráficos aceitam dados de textura não quadrada, porque aceitam coordenadas de mapeamento UV como dados de ponto flutuante; no entanto, uma vez enviado à GPU, o preenchimento é adicionado aos dados de textura, porque as proporções reais da imagem não alteram o mapeamento parece não ser afetado, no entanto, o preenchimento é adicionado aos dados de textura, porque a GPU gosta de endereçá-los como um quadrado perfeito.

Portanto, se uma imagem de 100x1024 for usada e uma imagem de 1024x1024, o que significa que 946.176 bytes são desperdiçados. Ainda mais se a composição precisar ser feita, pois será necessário adicionar um canal alfa para indicar que os dados do preenchimento não devem afetar a textura composta.

awiebe
fonte
Esta é uma explicação interessante (titbit sobre matrizes quadradas) que não é encontrada na potência usual de 2 respostas (+1) - você poderia fornecer algumas citações, se possível?
Samaursa
1

Nosso mundo digital trabalha com numeração binária e, em seguida, para multiplay ou dividir por 2 um valor, você pode "mover" um valor para a esquerda ou direita, ou seja,

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

Trabalhar com valores "potência de dois" é mais fácil para uma CPU.

esdebon
fonte
0

O hardware moderno pode (finalmente) lidar com a ativação dos modos de quebra de linha na falta de energia de duas texturas baseadas, no entanto, a falta de energia de duas texturas ainda tende a desperdiçar memória da GPU, pois elas tendem a se acumular ao longo da largura por uma quantidade específica de hardware ( para algum tamanho de bloco ou arredondado para a próxima potência de dois tamanhos que contém a textura).

Como isso depende do hardware e os fornecedores geralmente não abordam os detalhes desses detalhes, a coisa mais segura a fazer é continuar usando energia de duas dimensões para texturas, para não desperdiçar RAM da GPU.

Zoner
fonte