Eu tenho um mundo baseado em cubo como o Minecraft e me pergunto se existe uma maneira de construir um cubo com menos de 24 vértices para reduzir o uso de memória.
Não me parece possível por dois motivos: os normais não saem bem e as texturas por rosto não funcionam.
É este o caso ou estou errado? Talvez haja alguma nova tecnologia DX11 sofisticada que possa ajudar?
Edit: Apenas para esclarecer, tenho 2 requisitos: preciso de normais de superfície para cada face do cubo para obter iluminação adequada e preciso de uma maneira de abordar um índice diferente em uma matriz de textura para cada face do cubo
Respostas:
Se você só precisa de normais por face e se seus cabos de texto para uma face são estritamente 0/0, 0/1, 1/0, 1/1 (ou similares para se adequar ao seu layout), você pode construir um cubo com 8 verts e 30 (faixa com reinicialização) ou 36 (lista) índices. Busque os normais e os cabos de texto usando uma pesquisa de matriz constante baseada em SV_VertexID no seu sombreador de vértices.
Fazer isso significa que você nem precisa incluir cabos de texto ou normais no seu buffer de vértice, o que proporcionará ainda mais economia de memória.
Indo mais longe, você ainda pode ir até 24 verts por cubo, mas também usar instanciamento. Cada cubo teria um tamanho fixo no seu buffer de vértice (1x1x1) e você teria um fator de escala e uma posição (assumindo que seus cubos não giram, uma matriz se o fizer) como dados por instância. No caso não rotativo, você tem um custo único de 24 verts, mas cada cubo precisa apenas de 6 flutuadores para especificar completamente. No caso rotativo, você está olhando para 16 carros alegóricos, mas mesmo isso é uma economia substancial (nesse caso, é mais provável que você gargale o lado da CPU nas transformações de matriz - para o caso não rotativo que constrói uma matriz em tempo real seu sombreador de vértice - mesmo que seja feito por vértice, é tão estupidamente rápido que você nem precisa se preocupar com isso).
Para texturas por face, basta usar uma matriz de textura. Você precisa garantir que cada textura na matriz tenha o mesmo tamanho, é claro, e ainda precisará interromper o lote atual se a própria matriz precisar mudar, mas, caso contrário, ele fará o trabalho muito bem. Adicione um terceiro texcoord à sua definição de vértice, que define a fatia da matriz a ser usada para cada face.
Você não precisa de um GS com isso, e ele deve ser executado mais rapidamente do que usar um, pois ter o estágio de sombreador de geometria ativado imporá uma sobrecarga extra por si só.
Eu tenho código de referência no meu mecanismo que apenas desenha um monte de cubos usando esse método, e posso facilmente percorrer mais de 300.000 cubos enquanto ainda limpo 60 fps, em uma GPU relativamente baixa, e sem fazer mais nada para otimizar o processo . É certo que não os estou iluminando nem texturizando, mas tenho a mistura alfa ativada, o descarte da face posterior desativado e, em geral, se equilibra com a parte "não fazendo mais nada para otimizar", portanto, você deve ter uma idéia razoável do tipo de estimativa que você pode acertar com este método.
fonte
Eu acho que a principal otimização que você pode fazer é baseada no fato de que nem todo cubo precisará de todos os 24 vértices . De fato, os únicos cubos que precisam de 24 vértices são aqueles que flutuam no ar, o que provavelmente é uma ocorrência rara.
Em geral, gere apenas quads para os rostos que estão em contato com o ar . Isso significa que, se dois cubos estão se tocando, você não precisa gerar nenhum vértice para a face em que eles estão tocando.
A imagem abaixo demonstra esse conceito, mas em 2D para facilitar a compreensão. Na imagem, existem 11 blocos ocupados (representados pelos círculos cinzentos preenchidos), que normalmente exigiriam 4 x 11 = 44 arestas para representar (4 porque é um quadrado, não um cubo). Mas, como você pode ver, você realmente só precisa desenhar as arestas quando estiver em contato com um quadrado vazio, que neste caso é de apenas 8 arestas.
Se um exemplo tão simples em 2D conseguiu reduzir 44 arestas para 8 arestas, imagine os ganhos em um grande mundo 3D ...
Essa é a abordagem descrita neste artigo , que eu recomendo que você leia, apesar de ter como objetivo o OpenGL. Os conceitos devem ser bastante universais.
Você também pode provavelmente usar um sombreador de geometria para gerar os vértices em tempo real na GPU, eliminando a necessidade de armazená-los na memória, mas não tenho experiência com isso, nem sei quão bem ele funcionaria para uma grande mundo.
fonte