visão global
O principal motivo para a Virtual Texturing (VT), ou Sparse Virtual Textures , como às vezes é chamado, é como uma otimização de memória. O essencial é apenas mover para a memória de vídeo os texels reais (generalizados como páginas / blocos) que você pode precisar para um quadro renderizado. Assim, você terá muito mais dados de textura no armazenamento offline ou lento (HDD, disco óptico, nuvem) do que caberia na memória de vídeo ou até na memória principal. Se você entende o conceito de memória virtual usado pelos sistemas operacionais modernos, é a mesma coisa em sua essência (o nome não é dado por acidente).
O VT não requer a recálculo dos UVs no sentido de que você faria isso em cada quadro antes de renderizar uma malha e, em seguida, reenviaria os dados de vértice, mas requer um trabalho substancial nos shaders Vertex e Fragment para executar a pesquisa indireta dos UVs recebidos. Em uma boa implementação, no entanto, deve ser completamente transparente para o aplicativo se estiver usando uma textura virtual ou tradicional. Na verdade, na maioria das vezes, um aplicativo combina os dois tipos de texturização, virtual e tradicional.
Teoria de lotes pode, em teoria, funcionar muito bem, embora eu nunca tenha examinado os detalhes disso. Como os critérios habituais para o agrupamento da geometria são as texturas, e com o VT, todos os polígonos da cena podem compartilhar a mesma textura "infinitamente grande", teoricamente, você poderia obter um desenho completo da cena com uma chamada de desenho. Mas, na realidade, outros fatores entram em jogo, tornando isso impraticável.
Problemas com o VT
Ampliar / reduzir e movimento abrupto da câmera são as coisas mais difíceis de lidar em uma configuração de TV. Pode parecer muito atraente para uma cena estática, mas assim que as coisas começarem a se mover, serão solicitadas mais páginas / blocos de textura do que você pode transmitir para armazenamento externo. As entradas e saídas do arquivo assíncrono e a segmentação podem ajudar, mas se for um sistema em tempo real, como em um jogo, você precisará renderizar alguns quadros com blocos de menor resolução até que os de alta resolução cheguem, de vez em quando , resultando em uma textura embaçada. Não há bala de prata aqui e esse é o maior problema com a técnica, IMO.
A Texturização virtual também não lida com transparência de maneira fácil; portanto, polígonos transparentes precisam de um caminho de renderização tradicional separado para eles.
Em suma, o VT é interessante, mas eu não o recomendaria para todos. Pode funcionar bem, mas é difícil de implementar e otimizar, além de haver muitos casos de canto e ajustes específicos de caso necessários para o meu gosto. Mas, para grandes jogos de mundo aberto ou aplicativos de visualização de dados, pode ser a única abordagem possível para ajustar todo o conteúdo ao hardware disponível. Com muito trabalho, ele pode ser executado com bastante eficiência, mesmo em hardware limitado, como podemos ver nas versões PS3 e XBOX360 do Rage da id .
Implementação
Consegui fazer o VT funcionar no iOS com o OpenGL-ES, até certo ponto. Minha implementação não é "entregável", mas eu poderia fazê-lo se quisesse e tivesse os recursos. Você pode ver o código-fonte aqui , pode ajudar a ter uma idéia melhor de como as peças se encaixam. Aqui está um vídeo de uma demonstração em execução no iOS Sim. Parece muito lento porque o simulador é péssimo para emular shaders, mas roda sem problemas em um dispositivo.
O diagrama a seguir descreve os principais componentes do sistema em minha implementação. Difere bastante da demonstração SVT de Sean (link abaixo), mas está mais próxima da arquitetura do apresentado pelo artigo Acelerando a Texturização Virtual Usando CUDA , encontrado no primeiro livro do GPU Pro (link abaixo).
Page Files
são as texturas virtuais, já cortadas em blocos (páginas AKA) como uma etapa de pré-processamento, para que estejam prontas para serem movidas do disco para a memória de vídeo sempre que necessário. Um arquivo de paginação também contém todo o conjunto de mipmaps, também chamados de mipmaps virtuais .
Page Cache Manager
mantém uma representação do lado do aplicativo Page Table
e das Page Indirection
texturas. Como mover uma página do armazenamento offline para a memória é caro, precisamos de um cache para evitar recarregar o que já está disponível. Esse cache é um cache LRU ( Menos Utilizado Recentemente) muito simples . O cache também é o componente responsável por manter as texturas físicas atualizadas com sua própria representação local dos dados.
A Page Provider
é uma fila de trabalhos assíncrona que vai buscar as páginas necessárias para uma determinada visão da cena e enviá-los para o cache.
A Page Indirection
textura é uma textura com um pixel para cada página / bloco na textura virtual, que mapeará os UVs recebidos para a Page Table
textura do cache que possui os dados texel reais. Essa textura pode ficar muito grande, por isso deve usar um formato compacto, como RGBA 8: 8: 8: 8 ou RGB 5: 6: 5.
Mas ainda falta uma peça-chave aqui, e é assim que se determina quais páginas devem ser carregadas do armazenamento no cache e, consequentemente, no Page Table
. É aí que o Feedback Pass e o Page Resolver
enter.
O Feedback Pass é uma pré-renderização da exibição, com um sombreador personalizado e com uma resolução muito mais baixa, que gravará os IDs das páginas necessárias no buffer de estrutura de cores. Essa colcha de retalhos colorida do cubo e da esfera acima são índices de páginas reais codificados como uma cor RGBA. Essa renderização antes da passagem é então lida na memória principal e processada pelo Page Resolver
para decodificar os índices da página e disparar os novos pedidos com o Page Provider
.
Após o pré-passe de Feedback, a cena pode ser renderizada normalmente com os shaders de pesquisa do VT. Mas observe que não esperamos que a nova solicitação de página termine, isso seria terrível, porque simplesmente bloquearíamos a E / S de arquivo síncrono. Os pedidos são assíncronos e podem ou não estar prontos no momento em que a visualização final é renderizada. Se eles estiverem prontos, doce, mas se não estiver, sempre manteremos uma página bloqueada de um mipmap de baixa resolução no cache como fallback, portanto, teremos alguns dados de textura para usar, mas ficará embaçado.
Outros recursos que valem a pena conferir
O VT ainda é um tópico bastante interessante sobre computação gráfica; portanto, há toneladas de bom material disponível; você poderá encontrar muito mais. Se houver mais alguma coisa que eu possa adicionar a esta resposta, não hesite em perguntar. Estou um pouco enferrujado sobre o assunto, não li muito sobre isso no ano passado, mas é sempre bom que a memória revisite as coisas :)
Texturização virtual é o extremo lógico dos atlas de textura.
Um atlas de textura é uma única textura gigante que contém texturas para malhas individuais dentro dele:
Os atlas de textura se tornaram populares devido ao fato de que a alteração de texturas causa um fluxo completo de pipeline na GPU. Ao criar as malhas, os UVs são comprimidos / deslocados para que representem a "porção" correta de todo o atlas de textura.
Como @ nathan-reed mencionado nos comentários, uma das principais desvantagens dos atlas de textura é a perda de modos de quebra automática, como repetição, grampo, borda, etc. Além disso, se as texturas não tiverem bordas suficientes, você poderá acidentalmente amostra de uma textura adjacente ao fazer a filtragem. Isso pode levar a artefatos sangrentos.
Os Atlas de textura têm uma grande limitação: tamanho. As APIs gráficas colocam um limite suave para o tamanho da textura. Dito isto, a memória gráfica é tão grande. Portanto, há também um limite rígido no tamanho da textura, dado pelo tamanho do seu v-ram. Texturas virtuais resolvem esse problema, emprestando conceitos da memória virtual .
As texturas virtuais exploram o fato de que, na maioria das cenas, você vê apenas uma pequena porção de todas as texturas. Portanto, apenas esse subconjunto de texturas precisa estar no vram. O restante pode estar na RAM principal ou no disco.
Existem algumas maneiras de implementá-lo, mas vou explicar a implementação descrita por Sean Barrett em sua palestra no GDC . (que eu recomendo assistir)
Temos três elementos principais: a textura virtual, a textura física e a tabela de pesquisa.
A textura virtual representa o mega atlas teórico que teríamos se tivéssemos vram suficientes para caber em tudo. Na verdade, ele não existe na memória em nenhum lugar. A textura física representa os dados de pixel que realmente temos no vram. A tabela de pesquisa é o mapeamento entre os dois. Por conveniência, dividimos os três elementos em blocos ou páginas de tamanhos iguais.
A tabela de pesquisa armazena a localização do canto superior esquerdo do bloco na textura física. Então, dado um UV para toda a textura virtual, como obtemos o UV correspondente para a textura física?
Primeiro, precisamos encontrar o local da página dentro da textura física. Então precisamos calcular a localização do UV dentro da página. Finalmente, podemos adicionar esses dois deslocamentos para obter a localização do UV dentro da textura física
Calculando pageLocInPhysicalTex
Se tornarmos a tabela de pesquisa do mesmo tamanho que o número de blocos na textura virtual, podemos apenas amostrar a tabela de pesquisa com a amostragem do vizinho mais próximo e obteremos a localização do canto superior esquerdo da página na textura física.
Calculando inPageLocation
inPageLocation é uma coordenada UV relativa à parte superior esquerda da página, e não à parte superior esquerda de toda a textura.
Uma maneira de calcular isso é subtraindo a UV da parte superior esquerda da página e depois escalando para o tamanho da página. No entanto, isso é um pouco de matemática. Em vez disso, podemos explorar como o ponto flutuante IEEE é representado. O ponto flutuante IEEE armazena a parte fracionária de um número por uma série de frações de base 2.
Neste exemplo, o número é:
Agora vamos ver uma versão simplificada da textura virtual:
O bit 1/2 indica se estamos na metade esquerda da textura ou na direita. O 1/4 bit indica em que quarto da metade estamos. Neste exemplo, como a textura é dividida em 16 ou 4 em um lado, esses dois primeiros bits nos dizem em que página estamos. bits nos dizem a localização dentro da página.
Podemos obter os bits restantes deslocando o flutuador com exp2 () e removendo-os com fract ()
Onde numTiles é um int2 fornecendo o número de ladrilhos por lado da textura. No nosso exemplo, isso seria (4, 4)
Então, vamos calcular o inPageLocation para o ponto verde, (x, y) = (0,6875, 0,375)
Uma última coisa a fazer antes de terminarmos. Atualmente, inPageLocation é uma coordenada UV no 'espaço' da textura virtual. No entanto, queremos uma coordenada UV no 'espaço' da textura física. Para fazer isso, basta escalar inPageLocation pela proporção entre o tamanho da textura virtual e o tamanho da textura física
Portanto, a função final é:
fonte