Prefácio: Esta questão virá do ponto de vista do Direct3D, porque é com isso que estou familiarizado.
Obviamente, temos uma pequena sobrecarga toda vez que alteramos os buffers de vértice ou índice no Direct3D (ou seja, com IASetIndexBuffer
). Mas suponho que, se alocarmos um buffer gigante de índice / vértice, teremos que gerenciar a memória manualmente e acabar com um problema de fragmentação (ou pausar enquanto trocamos todos os dados).
Então, como os motores comerciais carregam / descarregam dados? Estou me inclinando para uma abordagem baseada em 'pacote'; portanto, um 'pacote' de modelos tem seu próprio buffer de vértice / índice que podemos carregar / descarregar, pois o pacote não é mais necessário; e tente desenhar todas as instâncias do mesmo pacote.
Mas eu gostaria de saber qual é a maneira aceita / padrão de lidar com isso?
fonte
Respostas:
Existem várias técnicas diferentes para organizar os dados, e muitos jogos usam uma mistura deles.
Para geometria estática, é melhor ter menos IBs e VBs individuais.
Tradicionalmente, os jogos são baseados em 'nível', o que significa que os recursos de uma seção do jogo são carregados e o jogo começa. Para minimizar o tempo de carregamento, as informações são organizadas de maneira ideal para dar suporte a isso (por exemplo, carregar tudo para o nível o mais rápido possível, sem procurar na mídia / disco), possivelmente replicando informações entre os níveis. Nessa abordagem, um esquema é ter um VB e IB grande para um modelo ou uma série de modelos e, em seguida, enviar subconjuntos para desenhar.
Para a geração Xbox 360 / PS 3, a quantidade de RAM era bastante pequena em relação ao tamanho dos jogos, então os mecanismos se tornaram orientados para 'streaming', o que significa que eles carregam conteúdo dinamicamente à medida que o jogador os move. Isso também é chamado de abordagem de "mundo aberto". Nessa abordagem, o desafio é dividir a geometria em bits que você pode carregar com base em dicas espaciais. Outro desafio especialmente para plataformas de 32 bits é garantir que a memória não se torne fragmentada (ou mesmo fragmentação do espaço de endereço virtual) por um longo período de tempo - jogos baseados em níveis geralmente redefinem a memória entre os níveis, algo que os mecanismos de streaming não podem fazer tão facilmente. Portanto, é útil compactar em um tamanho fixo ou conjunto de tamanhos fixos para os IBs / VBs que foram alocados e reutilizados como um pool.
Para a geração Xbox One / PS 4, há muita RAM para trabalhar em relação aos consoles anteriores e muitos núcleos extras; portanto, muitos jogos estão compactando agressivamente seus ativos e usando núcleos de CPU "extras" para descompactá-los no fundo. Com o espaço de endereço virtual de 64 bits, há menos preocupação com a fragmentação do espaço de endereço virtual. Essa abordagem mantém o tempo de carregamento baixo, compacta os recursos para o download digital e suporta a renderização em 'mundo aberto'. Aqui, a abordagem de pool para gerenciar IBs / VBs é usada.
Há também o envio de geometria dinâmica, que é frequentemente usada para terrenos, modelos deformáveis / destrutíveis, etc. Não é eficiente em termos de largura de banda de barramento da GPU; portanto, os jogos geralmente têm uma mistura de geometria estática e dinâmica. Nesse caso, o padrão de atualização DISCARD Direct3D Map DISCARD normalmente significa que você está usando apenas um IB / VB (ou, para cenários de renderização multithread, IB / VB duplo que você troca preenchendo / processando cada quadro).
fonte