Como inverter uma textura BC6 / BC7?

8

Eu tenho algum código para carregar arquivos de imagem DDS em texturas OpenGL e gostaria de estendê-lo para suportar os formatos compactados BC6 e BC7 introduzidos no D3D11. Como o DirectX e o OpenGL discordam sobre se a origem de uma textura está no canto superior esquerdo ou inferior esquerdo, meu carregador DDS inverte os pixels de cada imagem ao longo do eixo Y antes de passar os pixels para o OpenGL.

Inverter texturas compactadas apresenta uma ruga adicional: além de inverter cada linha de blocos de 4x4 pixels, você também precisa inverter os pixels dentro de cada bloco. Encontrei o código aqui para inverter os blocos BC1 / BC2 / BC3 e, a partir dos diagramas de blocos no MSDN , foi fácil adaptar o código de inversão do BC3 para lidar com BC4 e BC5. Os bc6 e BC7 formatos olhar significativamente mais intimidante, no entanto. Existe um truque semelhante para modificar esses formatos, ou eu teria que descomprimir e recomprimir totalmente cada bloco?

ATUALIZAÇÃO: Acontece que o flip de textura só foi necessário porque minhas coordenadas de textura estavam sendo invertidas incorretamente no momento da exportação. A remoção de ambos os flips tornou o código mais simples e rápido (obrigado Humus!). O lançamento de blocos BC6 / BC7 ainda pode ser um desafio interessante, mas não é mais relevante para o meu cenário original.

pós-bomismo
fonte
11
Observe que, se você inverter as coordenadas da textura em vez das imagens da textura, não poderá usar FBOs com as mesmas malhas / shaders.
msell
Isso é verdade. Deixar as texturas do DDS desmarcadas também faz com que elas apareçam de cabeça para baixo em ferramentas como o gDEBugger . Hrm.
Postgoodism

Respostas:

6

Suspeito que seja realmente possível inverter blocos BC6-7 com muito menos trabalho do que descomprimir e recomprimir completamente, mas ainda não é um piquenique e é muito mais complexo do que inverter os blocos BC1-5.

Primeiro, o BC6-7 possui uma variedade de modos que podem ser selecionados por bloco. Os modos têm layouts binários completamente diferentes, então você precisa escrever uma rotina de flip diferente para cada modo (existem ~ 20 deles no total, IIRC).

Outra dificuldade são os modos particionados, nos quais os pixels do bloco são particionados em 2 ou 3 subconjuntos, cada um com seu próprio segmento de linha RGB. A partição deve ser escolhida de um conjunto predefinido; os do BC6 podem ser vistos aqui . O problema é que esse conjunto de partições não é simétrico sob inversões verticais. No entanto, suspeito que seja simétrico sob alguma combinação de inversões verticais e intercambiando os dois subconjuntos. Por exemplo, observando a partição nº 22 (6a linha, 3ª coluna) nesse link, não há uma versão invertida verticalmente na tabela, mas se você inverter verticalmente eAo trocar 0s e 1s, você acaba com a partição 9 (terceira linha, segunda coluna). Eu não verifiquei que todas as partições podem ser invertidas dessa maneira, nem as do BC7 (que também inclui partições com 3 subconjuntos).

Mesmo que isso funcione, você ainda não está em casa. Em BC1-5, a ordem dos dois pontos finais do segmento de linha RGB foi usada para alternar os modos, mas em BC6-7 a ordem dos pontos finais é escolhida para fixar um bit dos índices por pixel em cada subconjunto de partições. Portanto, se você alterar a partição, também poderá precisar trocar a ordem dos pontos de extremidade.

E por último, mas não menos importante, em BC6-7 os pontos finais são frequentemente compactados em delta (ou seja, um ponto final é armazenado com precisão total e os outros são armazenados como deltas de menor precisão). A troca de subconjuntos de partições e ordem dos terminais mudará qual terminal é de alta precisão, portanto você terá que embaralhar os bits de baixa precisão e anular alguns deltas.

Em suma, não parece que haja qualquer impedimento fundamental (embora eu não tenha realmente escrito o código), mas com certeza seria muito trabalho mudar ou girar esses formatos. Se possível, eu recomendo inverter as imagens no seu pipeline de arte antes de serem compactadas.

(BTW, a especificação mais completa do BC6-7 que encontrei é a especificação ARB_texture_compression_bptc ; também escrevi um post sobre os formatos BCn há algum tempo.)

Nathan Reed
fonte
Obrigado; Estou suficientemente aterrorizada. Na verdade, fui procurar sua postagem no blog, mas não conseguia lembrar o link. É um excelente recurso em todas as coisas BCn; só isso vale a pena ser votado!
Postgoodism
0

A inversão é apenas uma questão de padrão nos dois formatos. Você pode ir contra o padrão.

Provavelmente é melhor fazer isso no lado do OpenGL, porque o OpenGL é de nível mais baixo e, portanto, menos propenso a perder otimização ao fazer coisas como esta.

Robert Wm Ruedisueli
fonte