Gerenciando dados Voxel

8

Venho programando em C ++ como hobby há cerca de 4 meses e adorei criar coisas usando voxels. Eu escrevi um "jogo" (mais do que apenas um desafio pessoal, como realmente fiz o terreno, sem jogabilidade) que transformou um mundo semelhante ao Minecraft, mas recentemente estive pensando em tentar escrever um jogo / desafio / etc que usa um algoritmo como Marching Cubes ou Dual Contouring e reduz o tamanho do voxel. Quando escrevi meu projeto parecido com o Minecraft, armazenei os dados de cada parte em uma matriz multidimensional de curtos não assinados (resultando em 65536 tipos de blocos diferentes). Além disso, para renderização, armazenei apenas um ponto (como um GLubyte) e outro GLubyte para indicar qual dos 6 enfrenta o ponto representado. Renderizei a face usando um sombreador de geometria.

Com o novo projeto em que estou pensando, o que não consigo entender é como posso armazenar dados voxel suficientes para ter voxels em torno de ~ 5cm ou 10cm em comparação com os voxels antigos de 1m. Quando renderizei uma área de blocos de 704x704x704, meu projeto antigo usava cerca de 670 MB de RAM. Se eu reduzisse o tamanho do voxel para 10 cm e mantivesse a mesma distância de renderização, seriam cerca de 649 GB de dados do Voxel (assumindo 2 bytes por voxel e uma área de 7040 ^ 3 voxels). Existe alguma maneira de armazenar os dados do voxel de maneira mais eficiente que ainda permita uma ampla variedade de tipos diferentes de voxel?

Sombra
fonte

Respostas:

5

Você precisa ter todos os blocos (presumindo que esteja usando blocos) na memória de uma só vez? Alguns serão ocluídos - particularmente no subsolo - ou atrás de montanhas etc. Muitos lotes provavelmente estarão vazios / vazios e poderão ser marcados com uma bandeira.

Além disso, você pode usar uma octree LOD ou estrutura semelhante para tentar manter os detalhes visíveis no momento inversamente relacionados à distância do observador. Como afirma Jason, é muito mais provável que você compre desempenho, mas é uma grande mudança estrutural em relação a um mapa de partes planas.

Veja este artigo sobre clipes de vídeo do meu blog favorito (ele tem um mecanismo voxel semelhante ao que você descreve com um tamanho voxel de ~ um decímetro).

ThorinII
fonte
2
Primeiro, sim, estou usando pedaços. Em segundo lugar, sua sugestão sobre descarregar pedaços completamente ocultos definitivamente ajudaria bastante, obrigado. Logo de cara, um método potencial que eu poderia usar seria usar uma consulta de oclusão com a caixa delimitadora do pedaço (já que todos os tamanhos são conhecidos) para ver se um pedaço está visível e carregar / descarregar um pedaço dependendo do resultado. Editar: acabei de ver sua edição e, na verdade, eu já vi esse blog. É a razão pela qual eu quero experimentar com um tamanho menor de voxel =) #
Shadow #
A oclusão é muito menos importante que o LOD. A oclusão não ajuda a menos que você esteja no subsolo ou olhando para o lado de uma montanha. O LOD por si só permite renderizar um planeta inteiro. As consultas de oclusão são uma péssima idéia, pois apresentam uma viagem de ida e volta de GPU-> CPU-> GPU. A renderização condicional é viável, no entanto, mas a CPU provavelmente pode fazer o suficiente por si só.
Bom ponto. Acabei de afirmar o LOD em segundo porque é uma grande mudança estrutural.
ThorinII
3

A abordagem padrão para mecanismos como o VoxLap de Ken Silverman e seu sucessor Ace of Spades, é usar a compactação RLE e vários outros truques no nível de bits para armazenar e acessar os dados. Esse tipo de compactação 1D tende a ser altamente eficiente e consideravelmente mais fácil de usar do que o octrees. Acredito que o mecanismo do Silverman alcançou uma resolução de voxel de algo como 10 cm em cubos. Algo que você normalmente não vê hoje, e que foi alcançado em um hardware muito mais fraco.

Eu acredito que também é verdade que sua abordagem não armazenou cores para voxels não expostos, que calculou cores para voxels de superfície em função da altura, ou lembrando quais áreas do terreno foram abertas e colorindo-as como "solo fresco " Você pode usar algum tipo de função contínua, como o ruído permanente, para fazer isso, mas pode rapidamente ficar caro para grandes áreas de superfície (a menos que, talvez, seja executado na GPU).

Octrees não são ruins, mas são difíceis de usar na prática, e a alocação eficiente de cache é consideravelmente mais desafiadora que o RLE, que é fácil de linearizar por partes. O artigo seminal de Tero Karras e Samuli Laine sobre SVOs indica quanto esforço é necessário para a implementação de octree verdadeiramente eficiente - e isso está considerando apenas a renderização, não a jogabilidade ou a comunicação em rede.

Engenheiro
fonte
0

Não sei até onde você chegou no seu projeto, mas eu e um amigo meu estamos usando o algoritmo Dual Marching Cubes , com base na estrutura chunck da Octree e usando uma grade dupla para renderizar os dados. Tem muitas vantagens, como pouca memória necessária e uma renderização muito rápida. Pode ser um pouco complicado implementar o Nível de detalhe (LOD) em bordas de blocos com outros blocos, mas se você tiver algum tempo livre, poderá descobrir como os desenvolvedores do Ogre3D fizeram .

Leggy7
fonte