Como obter os blocos vistos pelo jogador?

15

Estou escrevendo um jogo semelhante ao Minecraft usando o mecanismo Ogre e estou com um problema. Preciso otimizar meu jogo, porque quando tento desenhar 10000 blocos, tenho 2 FPS ... Então, tive a ideia de bloquear a exibição do avião e ocultar os blocos invisíveis. Mas tenho um problema - como sei quais blocos de cada vez são visíveis para o jogador?

E - se você conhece outros métodos de otimização para esse jogo, escreva o que e como usá-los no Ogre.

m4tx
fonte

Respostas:

16

Bem, o Ogre já implementa a seleção de frustum (que basicamente não extrai nada que não possa ser visto pela câmera), mas acho que seu problema é diferente.

Você não deve realmente exibir 10000 blocos, o que é comumente feito (ou pelo menos nos poucos minecraft baseados em Ogre3d, como clones que eu já vi (dos quais também estou criando um) e no original) está criando uma malha ( de alguma região NxNxN de blocos) que possui as faces externas dos cubos mostrados. Ou seja, quando você coloca 2 cubos lado a lado, as duas faces tocando não podem ser vistas e, portanto, não precisam ser desenhadas.

Essas faces também devem ser desenhadas em algo assim: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=DynamicGrowingBuffers, pois as placas de vídeo modernas preferem uma malha de 100000 polígonos versus 1000 malhas de 100 polígonos.

Elva
fonte
10

Existem alguns aspectos para esse problema. Em primeiro lugar, como você está desenhando seus 10000 blocos? Você está realmente desenhando-os como 10000 objetos separados? Nesse caso, é quase certamente o gargalo da garrafa, não a falta de seleção da oclusão. Você deve agrupar esses blocos em um número menor de malhas (talvez alguns milhares por malha) para reduzir as chamadas de empate.

Quanto à sua pergunta real, existem três tipos de seleção de oclusão que vêm à mente.

1) Blocos fora do campo de visão. Isso significa blocos que estão atrás de você ou dois do lado. O Ogre já os remove pela seleção de frustum de exibição.

2) Blocos 'subterrâneos' ou completamente cercados por outros blocos para que nunca possam ser vistos de nenhum ângulo. Você pode identificá-los olhando os blocos vizinhos de tamanho considerável. Se todos eles são sólidos, seu bloco está oculto. A GPU nunca deve ouvir sobre esses blocos - eles devem ser ignorados quando você estiver construindo a malha que representa sua superfície.

3) Blocos que estão na superfície e podem ser vistos em algumas posições do nível, mas que atualmente estão ocultos por uma colina (ou algo assim). Esse é o caso mais complicado que ainda não resolvi, mas há uma boa chance de que as consultas de oclusão de hardware possam ser usadas para esse caso.

É um plug vergonhoso, mas eu tenho uma biblioteca bastante madura que várias pessoas estão usando para desenvolver clones do Minecraft, incluindo alguns usando o Ogre. Você define o conteúdo do volume e ele gera a malha de superfície que pode ser renderizada. Aqui está a página inicial:

http://www.thermite3d.org/

E aqui está um vídeo do projeto de outra pessoa que está usando:

http://www.youtube.com/watch?v=Jju6WRPEK7o

David Williams
fonte
4

Você pode usar a seleção de backface para selecionar vértices e seus pixels associados que não estão voltados para o player. O buffer de profundidade deve cuidar do resto. 10k blocos realmente não são muito, meu 5770 pode renderizar 100k verts a 1500fps. Eu acho que você está fazendo algo muito errado.

DeadMG
fonte
Concordo. Este é provavelmente um problema com qualquer outra coisa.
Notabene
1

Se você tiver 10000 objetos separados, o gargalo provavelmente é a contagem primitiva, não o vértice, o polígono ou o preenchimento. Asse seus objetos em um número menor de objetos poligonais mais altos para maior velocidade.

O Minecraft tem um conceito de blocos de cubos, mas não consigo encontrar a referência no momento.

Aqui também estão minhas experiências em desenhar toneladas de cubos com várias técnicas. Não inclui o cozimento (ainda).

Jari Komppa
fonte
0

O que faço é depois de criar minha matriz de blocos, mas antes de criar os vértices, executo uma sub chamada UpdateBlockVisiblility.

O sub simplesmente verifica os vizinhos do bloco e atualiza o booleano facevisível dos blocos de acordo.

#define BLOCKFACE_NORTH 0

#define BLOCKFACE_SOUTH 1 

etc etc etc

if(IsBlockAt(NorthOfBlock))
  Blocks[Whatever].facevisible[BLOCKFACE_NORTH] = false;

Então eu só crio os vértices para o rosto se estiver visível! Simple :)

BMW
fonte